Take the 2-minute tour ×

I have a small app that allows the user to draw on the screen with the finger. Yes, nothing original, but it's part of something larger . I have a UIImageView where the user draws, by creating a CGContextRef and the various CG draw functions. I primarily draw strokes/lines with the function CGContextAddLineToPoint

Now my issue is this: The user can draw lines of various colors. I want to give him the ability to use a "rubber" tool to delete some part of the image drawn so far, with the finger. I initially did this by using a white color for the stroke (set with the CGContextSetRGBStrokeColor function) but it didn't work out...because I discovered later that the UIImage on the UIImageView actually had a transparent background, not white...so I would end up with a transparent image with white lines on it!

Is there anyway to set a "transparent" stroke color or is there any other way to clear the content of the CGContextRef under the user's finger, when he moves it? Thanks

share|improve this question

5 Answers 5

up vote 50 down vote accepted

This will do the trick:

CGContextSetBlendMode(context, kCGBlendModeClear)
share|improve this answer
Thanks a million for this! –  Peter Hajas May 8 '10 at 19:14
I searched the internet for weeks trying to figure out how to add erasing to my drawing app. This one line of code is a godsend - I just used it with my existing painting code and DONE! Simply awesome. –  aloo Jun 4 '10 at 20:11
Nailed it, nice work! –  Jason Jun 8 '11 at 20:25

I ended up using Bresenham's line algorithm (harkening back to the days of yore when I had to write my own graphics routines)...

- (void) contextEraseLine:(CGContextRef) ctx from:(CGPoint)startPoint to:(CGPoint) endPoint withThickness:(int)thickness {
    int x, cx, deltax, xstep,
    y, cy, deltay, ystep,
    error, st, dupe;

    int x0, y0, x1, y1;

    x0 = startPoint.x;
    y0 = startPoint.y;
    x1 = endPoint.x;
    y1 = endPoint.y;

    // find largest delta for pixel steps
    st = (abs(y1 - y0) > abs(x1 - x0));

    // if deltay > deltax then swap x,y
    if (st) {
        (x0 ^= y0); (y0 ^= x0); (x0 ^= y0); // swap(x0, y0);
        (x1 ^= y1); (y1 ^= x1); (x1 ^= y1); // swap(x1, y1);

    deltax = abs(x1 - x0);
    deltay = abs(y1 - y0);
    error  = (deltax / 2);
    y = y0;

    if (x0 > x1) { xstep = -1; }
    else         { xstep =  1; }

    if (y0 > y1) { ystep = -1; }
    else         { ystep =  1; }

    for ((x = x0); (x != (x1 + xstep)); (x += xstep))
        (cx = x); (cy = y); // copy of x, copy of y

        // if x,y swapped above, swap them back now
        if (st) { (cx ^= cy); (cy ^= cx); (cx ^= cy); }

        (dupe = 0); // initialize no dupe

        if(!dupe) { // if not a dupe, write it out
    		//NSLog(@"(%2d, %2d)", cx, cy);

    		CGContextClearRect(ctx, CGRectMake(cx, cy, thickness, thickness));


        (error -= deltay); // converge toward end of line

        if (error < 0) { // not done yet
            (y += ystep);
            (error += deltax);

Phew! That's a long way to go to create a (somewhat) clunky eraser line.

To use it, do something like:

- (void)eraseStart {
    // erase lines
    ctx = UIGraphicsGetCurrentContext();
    CGContextDrawImage(ctx,CGRectMake(0,0,drawingBoard.size.width, drawingBoard.size.height),[drawingBoard CGImage]); 

- (void)eraseEnd {
    drawingBoard = UIGraphicsGetImageFromCurrentImageContext();

    [drawingView removeFromSuperview];
    [drawingView release];

    drawingView = [[UIImageView alloc] initWithImage:drawingBoard];
    drawingView.frame = CGRectMake(intEtchX, intEtchY, intEtchWidth, intEtchHeight);

    [self.view addSubview:drawingView];

This assumes you have already created a drawingView (UIImageView) and drawingBoard (UIImage).

Then, to erase a line, simply do something like:

CGContextRef ctx = UIGraphicsGetCurrentContext();
[self eraseStart];
[self contextEraseLine:ctx from:CGPointMake (x1, y1) to:CGPointMake (x2, y2) withThickness:10];
[self eraseEnd];

(replace x1, y1, x2, and y2 with appropriate values)...

share|improve this answer

I've tried using:

CGContextSetStrokeColorWithColor (myContext, [[UIColor clearColor] CGColor]);

but that doesn't work, because it seems to be "drawing" on top of the context with an invisible color (and invisible color + whatever color it is drawing on = the color it's drawing on).

The only solution I've found (which isn't optimal) is:

CGContextClearRect (myContext, CGRectMake(x, y, width, height));

Unfortunately, that means you have to trace a series of rects and generate the line yourself...

share|improve this answer
//erase part

//**************Working Code*************// 

[frontImage.image drawInRect:CGRectMake(0, 0, frontImage.frame.size.width, frontImage.frame.size.height)];
CGContextSetLineCap(UIGraphicsGetCurrentContext(),kCGImageAlphaNone); //kCGImageAlphaPremultipliedLast);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 10);
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 1, 0, 0, 10);
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
CGContextClearRect (UIGraphicsGetCurrentContext(), CGRectMake(lastPoint.x, lastPoint.y, 10, 10));
frontImage.image = UIGraphicsGetImageFromCurrentImageContext();

lastPoint = currentPoint;


if (mouseMoved == 10) 
    mouseMoved = 0;
share|improve this answer
This does not work -- In turn draws a brown line over an image view –  Shailesh Sep 30 at 13:00
UIColor *clearColor = [UIColor clearColor];
share|improve this answer

Your Answer


