Introduction
Generative art refers to art that in whole or in part has been created with the use of an autonomous system (Wikipedia). This tip focuses on the technical part of that challenge and provides first basic C# classes and methods for developers/digital artists who want to produce these kind of artworks. Concerning the artistic aspect, you can find lots of material, e.g., here.
This tip shows how incredibly easy the technical part of the production of generative artworks can be.
Basic Approach
For producing your first generative artwork, you have to accomplish the following tasks:
- Create a canvas
- Generate something on it
- Sign the result
- Save the artwork
var canvas = new GenArtCanvas(width * zoom, height * zoom, backgroundColor);
canvas.Generate(zoom);
canvas.Sign(signature, margin);
canvas.Save(outputDirectory + title + format);
Create Canvas
The class GenArtCanvas
inherits everything from Canvas
:
public class GenArtCanvas : Canvas
{
public GenArtCanvas(double Width, double Height, Brush BackgroundColor)
: base()
{
this.Width = Width;
this.Height = Height;
this.Background = BackgroundColor;
}
}
The canvas
is not displayed on the screen. It only uses the memory. You cannot observe the process of painting, but in the end, you will see the result in the stored file.
Generate Artwork
Now you choose an algorithm. In this case, it is a so-called turtle graphics. But this is the part where you should bring in your own creativity. You may adapt well-known algorithms (like this one) or create your own ones.
public void Generate(int Zoom)
{
this.Children.Add(Generator.TurtleWalk(2000, new Point(Width / 2, Height / 2),
new Vector(1, 0), Brushes.Black, 1 * Zoom, 20 * Zoom));
}
This generator works with a Polyline
which is generated as random turtle walk and then simply added to the canvas
.
public class Generator
{
private static Random RandomNumbers = new Random();
public static Polyline TurtleWalk(int NumberOfSteps, Point Point,
Vector Vector, Brush Color, double Thickness, int Length)
{
var points = new PointCollection();
var result = new Polyline()
{
Stroke = Color,
StrokeThickness = Thickness,
StrokeStartLineCap = PenLineCap.Round,
StrokeEndLineCap = PenLineCap.Round,
StrokeLineJoin = PenLineJoin.Round,
Points = points
};
points.Add(Point);
for (var i = 0; i < NumberOfSteps; i++)
{
Vector = Vector / Vector.Length * Length;
Vector = RotatedVector(Vector, RandomNumbers.Next(0, 361));
Point += Vector;
points.Add(Point);
}
return result;
}
private static Vector RotatedVector(Vector OldVector, double Angle)
{
var matrix = Matrix.Identity;
matrix.Rotate(Angle);
return matrix.Transform(OldVector);
}
}
It is up to you which algorithm you use and how much random action you implement here in your personal generator.
Sign Artwork
Of course, your artwork needs a signature:
public void Sign(string Signature, double Margin)
{
var signature = new Label()
{
Content = Signature,
FontSize = (int)(Height * 1 / 100)
};
signature.Measure(new Size(Double.MaxValue, Double.MaxValue));
this.Children.Add(signature);
Canvas.SetLeft(signature, Width - Margin - signature.DesiredSize.Width);
Canvas.SetTop(signature, Height - Margin - signature.DesiredSize.Height);
}
In this case, the size of the signature is set to 1 percent of the height of the canvas.
Save Artwork
Now the artwork is saved as an imagefile
. The format depends on the extension of the OutputFileName
.
public void Save(string OutputFileName)
{
BitmapEncoder encoder = null;
RenderTargetBitmap renderBitmap;
var size = new Size(Width, Height);
Measure(size);
Arrange(new Rect(size));
renderBitmap = new RenderTargetBitmap((int)size.Width,
(int)size.Height, 96d, 96d, PixelFormats.Pbgra32);
renderBitmap.Render(this);
using (FileStream outStream = new FileStream(OutputFileName, FileMode.Create))
{
if (OutputFileName.ToUpper().EndsWith(".PNG"))
encoder = new PngBitmapEncoder();
if (OutputFileName.ToUpper().EndsWith(".JPG") ||
OutputFileName.ToUpper().EndsWith(".JPEG"))
encoder = new JpegBitmapEncoder();
if (OutputFileName.ToUpper().EndsWith(".TIFF"))
encoder = new TiffBitmapEncoder();
if (encoder == null)
encoder = new BmpBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(renderBitmap));
encoder.Save(outStream);
}
}
Finally, look at the produced file and enjoy the result!
Points of Interest
This code works with a zoom
-factor. This is helpful for the fast trial of new algorithms (when set to a lower value) and the high-quality generation of the file for the print shop (when set to a higher value).
History
- 29th December, 2014 - Published
- 31st December, 2014 - Different output file formats added
- 11th January, 2015 - Links to other articles in the series added