Study a fascinating color illusion in C#


[color illusion]

This example shows how you can generate a fascinating color illusion that tricks your brain trick into thinking that a black and white picture is actually colored. All of the pictures shown above are black and white. All except the one on the lower right also contain colored lines or dots. Your brain uses the color information to infer a color for the black and white areas and produce the color illusion.

If you zoom in on the pictures, you can see that the areas between the colored lines or dots are actually black and white. Here’s a closeup of the picture on the upper left. You can clearly see that the picture is actually black and white.


[color illusion]

To create the color illusion, you can simply draw colored lines, dots, characters, or other small colored areas on top of the black and white image.

This example starts with a full-color image and creates a monochrome version of it. It then uses the color version to draw lines or dots on the monochrome version.

The program uses the following PlaceColorAreas to draw the lines or dots.

// Place areas of color on an image.
private Bitmap PlaceColorAreas(Bitmap bm, Bitmap brush_bm,
    AreaTypes area_type,
    float spacing, float thickness)
{
    // Make a monochrome copy of the image.
    Bitmap result = ToMonochrome(bm);

    // Draw colored stripes on the image.
    using (Graphics gr = Graphics.FromImage(result))
    {
        using (Brush brush = new TextureBrush(brush_bm))
        {
            using (Pen pen = new Pen(brush, thickness))
            {
                int wid = brush_bm.Width;
                int hgt = brush_bm.Height;

                switch (area_type)
                {
                    case AreaTypes.Stripes:
                        // Vertical and horizontal stripes.
                        for (float x = 0; x < wid; x += spacing)
                            gr.DrawLine(pen, x, 0, x, hgt);
                        for (float y = 0; y < hgt; y += spacing)
                            gr.DrawLine(pen, 0, y, wid, y);
                        break;

                    case AreaTypes.DiagonalStripes:
                        // Diagonal stripes.
                        wid *= 2;
                        hgt *= 2;
                        spacing *= (float)Math.Sqrt(2);
                        for (float i = 0; i < wid; i += spacing)
                            gr.DrawLine(pen, i, 0, 0, i);
                        for (float i = -hgt; i < hgt; i += spacing)
                            gr.DrawLine(pen, 0, i, hgt, i + hgt);
                        break;

                    case AreaTypes.Dots:
                        // Dots.
                        for (float x = -spacing / 2f; x < wid;
                                x += spacing)
                            for (float y = -spacing / 2f; y < hgt;
                                    y += spacing)
                                gr.DrawEllipse(pen, x, y,
                                    thickness, thickness);
                        break;

                    case AreaTypes.Text:
                        // Text.
                        using (Font font = new Font("Arial", spacing))
                        {
                            GraphicsUnit unit = GraphicsUnit.Pixel;
                            gr.DrawString(lorem_ipsum, font, brush,
                                brush_bm.GetBounds(ref unit));
                        }
                        break;
                }
            }
        }
    }
    return result;
}

This method first calls the ToMonochrome method to create a monochrome version of the original full-color image. You can read about that method in my earlier post Use an ImageAttributes object to convert an image to monochrome in C#.

Next, the code creates a Graphics object associated with the monochrome image. The program then makes a TextureBrush based on the full-color version of the picture. Anything that the program draws with this brush will copy pieces of the full-color image onto the monochrome version.

The method then uses the brush to create a pen with a desired thickness. Now lines drawn with the pen will show pieces of the TextureBrush, which are bits of the color image.

Now the method gets down to drawing. Depending on the area_type parameter, the method will draw horizontal/vertical stripes, diagonal stripes, dots, or text.

For the stripes, the code simply uses nested loops to draw the appropriate lines. To draw dots, the program uses nested loops to place dots in a grid across the picture.

To draw text, the program simply draws the text stored in the string named lorem_ipsum to it fills the bitmap’s bounds.

That’s about all there is to this example. Download it to experiment with the thickness and spacing of the lines or dots. You can also modify the code to try out filling the image with text. Or try performing the same color illusion on some other images.

[example]

You’ll find that the results are much duller than the original images. The monochrome areas remove a lot of the image’s brightness and the lines don’t restore all of it. For example, the original full-color picture that this example uses is shown on the right.

I tried several experiments that adjusted the colors. For example, I tried increasing the colored image’s brightness to make up for the reduced color in the monochrome areas. The things I tried were a lot of work but didn’t really improve the result very much so I removed them and went back to the basic code shown here.

For more information on this color illusion, see the article This Photo Is Black And White. Here’s The Science That Makes Your Brain See Colour.


Download Example   Follow me on Twitter   RSS feed   Donate




About RodStephens

Rod Stephens is a software consultant and author who has written more than 30 books and 250 magazine articles covering C#, Visual Basic, Visual Basic for Applications, Delphi, and Java.
This entry was posted in drawing, graphics and tagged , , , , , , , , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.