0

So, I am working on a virtual wall painting app.

I am able to draw some random lines by moving my finger on the image view(which has an image in it). Now I am trying to erase the drawings made on it without success as of yet.

I googled to find some solution and this line below came as full on recommended :-

CGContextSetBlendMode(UIGraphicsGetCurrentContext(),kCGBlendModeClear);

Using this drawing can be erased,but it also erases the image on which the drawing are done. Is there any way to prevent the image from getting erased ? only erase the drawing made on it?

Following is the code I am using to erase the drawings :-

In touchesMoved:-

UITouch *touch = [touches anyObject];
CGPoint previousPoint = [touch locationInView:self.upperImageView];
UIGraphicsBeginImageContext(self.upperImageView.frame.size);
[self.upperImageView.image drawInRect:CGRectMake(0, 0, self.upperImageView.frame.size.width, self.upperImageView.frame.size.height)];

CGContextSaveGState(UIGraphicsGetCurrentContext());
CGContextSetShouldAntialias(UIGraphicsGetCurrentContext(),YES);
CGContextSetLineCap(UIGraphicsGetCurrentContext(), eraserCap);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 45.0);
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 0.25, 0.25, 0.25, 1.0);
CGMutablePathRef pathB = CGPathCreateMutable();
CGPathMoveToPoint(pathB,nil,location.x,location.y);
CGPathAddLineToPoint(pathB,nil,previousPoint.x,previousPoint.y);
CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeClear);
CGContextAddPath(UIGraphicsGetCurrentContext(),pathB);
CGContextStrokePath(UIGraphicsGetCurrentContext());
upperImageView.image = UIGraphicsGetImageFromCurrentImageContext();
CGContextRestoreGState(UIGraphicsGetCurrentContext());
UIGraphicsEndImageContext();
location = previousPoint;

and in touchesEnded:-

UITouch *touch = [touches anyObject];
CGPoint previousPoint = [touch locationInView:self.upperImageView];
UIGraphicsBeginImageContext(self.upperImageView.frame.size);
[self.upperImageView.image drawInRect:CGRectMake(0, 0, self.upperImageView.frame.size.width, self.upperImageView.frame.size.height)];
CGContextSaveGState(UIGraphicsGetCurrentContext());
CGContextSetShouldAntialias(UIGraphicsGetCurrentContext(), YES);
CGContextSetLineCap(UIGraphicsGetCurrentContext(), eraserCap);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 5.0);
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 1.0,1.0,1.0, 0.0);
CGMutablePathRef pathB = CGPathCreateMutable();
CGPathMoveToPoint(pathB, nil, location.x, location.y);
CGPathAddLineToPoint(pathB, nil, previousPoint.x, previousPoint.y);
CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeClear);
CGContextAddPath(UIGraphicsGetCurrentContext(),pathB);
CGContextStrokePath(UIGraphicsGetCurrentContext());
self.upperImageView.image = UIGraphicsGetImageFromCurrentImageContext();
// CGContextRestoreGState(UIGraphicsGetCurrentContext());
UIGraphicsEndImageContext();
previousPoint = location;

Is there anything I am doing wrong ? Please guide me in the right direction here, any help will be truly appreciated.

Shailesh
  • 3,072
  • 3
  • 24
  • 33
  • [This](http://stackoverflow.com/questions/26911271/how-to-undo-a-line-stroke-ios/26988840#26988840) might be helpful. – gabbler Jan 21 '15 at 15:46

2 Answers2

0

You can use different views for your image and drawings. Or keep drawn paths in the array and delete each path separately.

Luniz
  • 59
  • 3
0

Move all of your drawing to a separate UIView that overlays the UIImageView. That way, when you go to "clear" the contents, the original UIImageView is still completely intact underneath.

Something like this will get you set up:

- (void)viewWillAppear {
    // Assumes you add a property of type UIView
    self.drawingView = [[UIView alloc] initWithFrame:self.upperImageView.bounds];
    [self.upperImageView addSubview:drawingView];

}

Then, your drawing code needs to only change to this (notice that you won't need to redraw the image any more):

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *touch = [touches anyObject];
    CGPoint previousPoint = [touch locationInView:self.drawingView];
    UIGraphicsBeginImageContext(self.drawingView.frame.size);
    CGContextSaveGState(UIGraphicsGetCurrentContext());
    CGContextSetShouldAntialias(UIGraphicsGetCurrentContext(),YES);
    CGContextSetLineCap(UIGraphicsGetCurrentContext(), eraserCap);
    CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 45.0);
    CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 0.25, 0.25, 0.25, 1.0);
    CGMutablePathRef pathB = CGPathCreateMutable();
    CGPathMoveToPoint(pathB,nil,location.x,location.y);
    CGPathAddLineToPoint(pathB,nil,previousPoint.x,previousPoint.y);
    CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeClear);
    CGContextAddPath(UIGraphicsGetCurrentContext(),pathB);
    CGContextStrokePath(UIGraphicsGetCurrentContext());
    upperImageView.image = UIGraphicsGetImageFromCurrentImageContext();
    CGContextRestoreGState(UIGraphicsGetCurrentContext());
    UIGraphicsEndImageContext();
    location = previousPoint;
}

Make similar changes in the touchesEnded: method.

mbm29414
  • 11,558
  • 6
  • 56
  • 87
  • Yes .. thats quite a workaround ! but since I am trying to make a virtual wall painting .. I would require "undo" & "redo" (array would come handy here). If I am to maintain a separate view,how can i make a undo/redo stack ? – Shailesh Jan 21 '15 at 14:03
  • Also, I would need to implement a "colour fill" functionality too.. like a user touches anywhere on the image and it colours same coloured areas ..I am not sure if using the overlay view will be useful ?? – Shailesh Jan 21 '15 at 14:05
  • @Shailesh The undo/redo stack can be done whether you do the separate view or not. I'm not advanced enough in graphics to know how to do a color fill. Maybe, if you do a check to see if a particular pixel has been made clear, you replace it with the original color value? I think you've got a big task ahead of you. – mbm29414 Jan 21 '15 at 14:13