Click here to Skip to main content
11,642,216 members (59,512 online)
Click here to Skip to main content

The Secret of Marching Ants

, 14 Nov 2005 85.3K 425 53
Rate this:
Please Sign up or sign in to vote.
This article describes how to implement "marching ants".

Sample Image - scrdump.gif

Introduction

Ah! Marching ants! You've gotta love them! They add a sense of quality to your software. You know marching ants? When you select something in Photoshop, Paint Shop Pro or GIMP, the selected area is indicated by an animated dashed line. It looks like there are ants marching along that boundary.

But how on earth do you implement such beasts? This article will show you how to do it.

First attempt

When I wanted to implement marching ants, my first attempt was very simple. I created an array of SBytes. This array represented the selected area. The array was initialized with 0s. A function AddRectangle() changed values in this array to 1s. The 1s indicated the pixels which belonged to the selected area. To draw the outline of the selected area, I scanned the array from top to bottom and from left to right. At each pixel, I tested whether this pixel was an edge pixel or not. Testing if a pixel was an edge pixel is very simple: if the value of the current pixel was 1 and a neighboring pixel was 0, the pixel was an edge pixel. When an edge pixel was found, I set the the value of the array cell to 2.

Now, I had an array with all edge pixels. I converted them to paths. A path consisted of one ore more lines (if you select a rectangular area and you subtract another area inside that area, you need two paths, so in this case, we would have 2 paths with 4 lines). I wrote a function that could draw those paths with dashed lines. Using a timer, I drew each path with a different offset, so that the dashes seemed to move. My ants marched.

But I didn't like my solution that much. I wondered how Photoshop and other programs did it. My solution was also slow.

Second attempt

I downloaded the GIMP source code and studied it a bit. I started from scratch and this second solution is what you can download. The screenshot above also shows what to expect. Note that I only show how to implement marching ants, I don't provide a complete program or even a complete control.

Included in the source code is a program called Fotowinkel (fotowinkel.cs). This program creates a form and adds a PaintBox control to it. (If you wanted to create some sort of paint program, you could start using this control.) PaintBox provides scrollbars for the InnerPaintBox control. InnerPaintBox contains a PaintBoxImage which, in turn, contains a Selection object (Selection.cs). PaintBoxImage draws the background and centers the current image (you cannot specify an image, but this is easy to implement). Use the mouse to select rectangular areas. Each selected area will be added to the current selected area and marching ants will indicate the edges.

Selection.cs contains the selection engine, so to speak. The Selection object contains a bitmap, which is the selection mask. When you select a rectangle, the method AddRectangle() will draw a rectangle on the selection mask. GetOutline() is called at the end of the method. GetOutline() scans the selection mask from top to bottom and then again from left to right, searching for the edges of the current selected area. The lines are animated by drawing the lines using different texture brushes. In the constructor of the Selection object, you can see how I create 8 different texture brushes. The method Animate() will change the current brush when it's called. I borrowed this technique from the GIMP.

Some thoughts

What's the difference between my first attempt and my second? In the first attempt, I have to change the values of the selection mask to indicate what pixels make up the boundary of the selection. This is annoying, because, in practice, you would create a copy of the selection mask when updating the selection outline, which means, more memory (or you could keep an array of the old pixel values, but that would create other problems, such as detecting if an edge pixel already belongs to an edge or not). The advantage of this first technique is that the ants march clockwise, in the second solution definitely not.

Another problem is performance. On my (old) computer, it takes about 2 seconds to update the selection, and we're only talking about a 256x256 selection mask! GDI+ is slow. But using GDI using DllImport is no option because GDI+ uses anti-aliasing.

The demo project allows you to select rectangular areas, but the code is able to handle all kinds of shapes because the engine doesn't know about shapes, it only knows about pixels. If you want to experiment, write a method AddEllipse(Point x, Point y) or something like that and draw an ellipse on the selection mask bitmap. Call GetOutline() and you're done!

A final thought concerns the selection mask bitmap: I use new Bitmap() to create a selection mask, but in reality, this should be a grayscale bitmap.

Update (March 2, 2004)

I updated the source code. To speed up the GetOutline() method, I created a new class called SelectionMask. SelectionMask wraps a Bitmap and provides 4 methods to manipulate that bitmap: Lock(), GetPixel(), SetPixel() and Unlock(). GetPixel() and SetPixel() access the bitmap data directly using unsafe pointers. Wow! This really gives a "turbo boost".

I also added a method AddEllipse(). The demo project now has a menu where you can choose how to select an area: rectangular or elliptical.

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

Share

About the Author

Mike Finnegan
Belgium Belgium
No Biography provided

You may also be interested in...

Comments and Discussions

 
GeneralMy vote of 5 Pin
Maxwolf Goodliffe13-Dec-14 23:49
memberMaxwolf Goodliffe13-Dec-14 23:49 
GeneralMy vote of 5 Pin
manoj kumar choubey26-Feb-12 21:22
membermanoj kumar choubey26-Feb-12 21:22 
Questionwhat if it's complex polygon? how do we march ant along the line with different slopes Pin
scottchu.tw9-Dec-09 17:53
memberscottchu.tw9-Dec-09 17:53 
AnswerRe: what if it's complex polygon? how do we march ant along the line with different slopes Pin
scottchu.tw24-Jun-14 15:50
memberscottchu.tw24-Jun-14 15:50 
Generalfaster animate function Pin
ShyH14-Nov-05 23:55
memberShyH14-Nov-05 23:55 
QuestionIs it a bug? Pin
rutmir14-Nov-05 2:42
memberrutmir14-Nov-05 2:42 
AnswerRe: Is it a bug? Pin
q12345678914-Nov-05 4:53
memberq12345678914-Nov-05 4:53 
GeneralAdding straight line Pin
Craig D.25-Sep-05 16:01
memberCraig D.25-Sep-05 16:01 
GeneralRe: Adding straight line Pin
Anonymous25-Sep-05 22:30
sussAnonymous25-Sep-05 22:30 
GeneralRe: Adding straight line Pin
Craig D.26-Sep-05 4:42
memberCraig D.26-Sep-05 4:42 
GeneralRe: even more Secret. (Color cycling) Pin
Anonymous14-Apr-04 22:13
sussAnonymous14-Apr-04 22:13 
Generaleven more Secret. (Color cycling) Pin
Dnt14-Apr-04 13:27
memberDnt14-Apr-04 13:27 
GeneralAnother Attempt Pin
jbialek24-Mar-04 23:14
memberjbialek24-Mar-04 23:14 
GeneralAnother marching ants technique: DashOffset Pin
Frank Hileman2-Mar-04 4:48
memberFrank Hileman2-Mar-04 4:48 
Generalslightly slow response Pin
Joel Holdsworth1-Mar-04 5:56
memberJoel Holdsworth1-Mar-04 5:56 
GeneralRe: slightly slow response Pin
q1234567891-Mar-04 23:03
memberq1234567891-Mar-04 23:03 
GeneralRe: slightly slow response Pin
Matthew Hazlett2-Mar-04 13:43
memberMatthew Hazlett2-Mar-04 13:43 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.150731.1 | Last Updated 14 Nov 2005
Article Copyright 2004 by Mike Finnegan
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid