Make a closeup map in C#

[closeup map]

This example makes a closeup map that shows an enlarged area under the mouse as you move it across the map. The program stores an enlarged version of the map in the hidden PictureBox named picHidden. When the mouse moves, the program copies part of that image over the smaller image that is visible, giving a closeup of the area under the mouse.

The following code shows how the program starts.

private const int ScaleFactor = 2;
private const int SmallRadius = 25;
private const int BigRadius = SmallRadius * ScaleFactor;
private const int BigDiameter = 2 * BigRadius;

private int OriginalWid, OriginalHgt;
private Bitmap BigMap, OriginalMap, ModifiedMap, MapPatch;
private Rectangle PatchRect =
    new Rectangle(0, 0, BigDiameter, BigDiameter);
private Rectangle SrcRect =
    new Rectangle(0, 0, BigDiameter, BigDiameter);
private Rectangle DestRect =
    new Rectangle(0, 0, BigDiameter, BigDiameter);

// Save the original small map image.
private void Form1_Load(object sender, EventArgs e)
    OriginalWid = picMap.Image.Width;
    OriginalHgt = picMap.Image.Height;

    // Save the big map.
    BigMap = (Bitmap)picHidden.Image;

    // Save the original map.
    OriginalMap = (Bitmap)picMap.Image;

    // Make a copy to display.
    ModifiedMap = (Bitmap)(OriginalMap.Clone());

    // Make a patch area.
    MapPatch = new Bitmap(BigDiameter, BigDiameter);

This code first defines some constants. Then when the form loads, it saves references to the large (hidden) and small (visible) images. It also makes a copy of the small image to modify later.

The program executes the following code when the mouse moves over the visible map.

// Prepare the new map image.
private void picMap_MouseMove(object sender, MouseEventArgs e)
    // Adjust where the source and destination bitmaps are.
    SrcRect.X = e.X * ScaleFactor - BigRadius;
    SrcRect.Y = e.Y * ScaleFactor - BigRadius;
    DestRect.X = e.X - BigRadius;
    DestRect.Y = e.Y - BigRadius;

    // Make a piece of the small map with a transparent hole in it.
    using (Graphics gr = Graphics.FromImage(MapPatch))
        // Draw the small map image into the patch.
        gr.DrawImage(OriginalMap, PatchRect, DestRect,

        // Make a transparent hole in the patch.
        using (SolidBrush br =
            new SolidBrush(Color.FromArgb(255, 1, 2, 3)))
            gr.FillEllipse(br, PatchRect);

    using (Graphics gr = Graphics.FromImage(ModifiedMap))
        gr.SmoothingMode = SmoothingMode.AntiAlias;

        // Restore the original map.
        gr.DrawImage(OriginalMap, 0, 0, OriginalWid, OriginalHgt);

        // Copy a chunk of the big image into it.
        gr.DrawImage(BigMap, DestRect, SrcRect, GraphicsUnit.Pixel);

        // Draw the patch to make the closeup round.
        gr.DrawImage(MapPatch, DestRect, PatchRect,

        // Outline the area.
        gr.DrawEllipse(Pens.Blue, DestRect);

        // Display the result.
        picMap.Image = ModifiedMap;

When the mouse moves, the program adjusts the source and destination rectangles for the big and small maps. These indicate what part of the big image is copied onto what part of the small image.

The code then copies the small map image into the MapPatch bitmap. It fills an ellipse in the center of the patch and uses MakeTransparent to make this ellipse transparent.

Next the code copies the original small map onto the modified version to erase the previous closeup. It copies a piece of the big map onto the modified one.

The program then copies the patch over the enlarged area. Because the patch contains a transparent hole, this leaves the elliptical area in the middle enlarged but makes the corners outside of the ellipse look like the underlying small map.

Finally the program draws an ellipse to outline the closeup. It finishes by displaying the result.

Download Example   Follow me on Twitter   RSS feed   Donate

This entry was posted in drawing, graphics, image processing and tagged , , , , , , , , , , . Bookmark the permalink.

Leave a Reply

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