Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Generative Art I

0.00/5 (No votes)
29 Dec 2014 2  
Turtle graphics: fundamental C# classes and methods for the artwork production in the area of generative art.

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

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here