user1343911
user1343911

Reputation:

Making an eraser tool for a paint app in iOS

I am creating a paint app and I want to know how to implement the eraser tool. I don't want to have my eraser tool to paint white color because I want to allow users to change the background color. And also, is it possible to set the hardness of the brush? If yes, please tell me how.

Thank you

Here's what I've done so far:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = [touches anyObject];
    lastPoint = [touch locationInView:self.view];
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = [touches anyObject];
    CGPoint currentPoint = [touch locationInView:self.view];
    UIGraphicsBeginImageContext(self.view.frame.size);
    [drawImage.image drawInRect:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
    CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
    CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 10);
    CGContextBeginPath(UIGraphicsGetCurrentContext());
    CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 0.0, 0.0, 0.0, 1.0);
    CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
    CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y);
    CGContextStrokePath(UIGraphicsGetCurrentContext());
    drawImage.image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    lastPoint = currentPoint;
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint currentPoint = [touch locationInView:self.view];
UIGraphicsBeginImageContext(self.view.frame.size);
[drawImage.image drawInRect:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 10);
CGContextBeginPath(UIGraphicsGetCurrentContext());
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 0.0, 0.0, 0.0, 1.0);
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y);
CGContextStrokePath(UIGraphicsGetCurrentContext());
drawImage.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

lastPoint = currentPoint;
}
- (IBAction)clear:(id)sender {
drawImage.image = nil;
}

Upvotes: 8

Views: 8018

Answers (3)

Charlie
Charlie

Reputation: 169

Ok so I have been looking for a solution on how to create an eraser for a week now, I had to change the way I looked at it cause no matter how many times I tried to erase something out it would erase the background image too.

However, in the end I did find a solution that suited me (where I could erase the paint and still have the perception of the background image being untouched or erased) and hopefully it will help others. So here goes...

1) Create 2 imageviews in the UIView 2) Set both imageviews with the background image that you want it to be... 3) I created a segmented control to determine if the user wanted to erase 4) Added the following function when segmented control is being selected..

  func drawLineForRubber(fromPoint: CGPoint, toPoint: CGPoint) {

    // 1
    UIGraphicsBeginImageContext(view.frame.size)
    let context = UIGraphicsGetCurrentContext()
    mainImageView.image?.drawInRect(CGRect(x: 0, y: 0, width: view.frame.size.width, height: view.frame.size.height))

    // 2
    CGContextMoveToPoint(context, fromPoint.x, fromPoint.y)
    CGContextAddLineToPoint(context, toPoint.x, toPoint.y)

    // 3
    CGContextSetBlendMode(context, CGBlendMode.Clear)
    CGContextSetLineCap(context, CGLineCap.Round)
    CGContextSetLineWidth(context, 10.0)
    //this line is very important as it paints the screen clear
    CGContextSetRGBStrokeColor(context, red, green, blue, 0.0)
    CGContextSetBlendMode(context, CGBlendMode.Clear)

    // 4
    CGContextStrokePath(context)

    // 5
    mainImageView.image = UIGraphicsGetImageFromCurrentImageContext()
    mainImageView.alpha = opacity
    UIGraphicsEndImageContext()

}

As you will see there is a line in there that sets the CGContextSetRGBStrokeColor with the value of 0.0, this is important cause when the user is erasing the paint, he is erasing the paint from the top imageview along with the paint with a transperent color. However, since you have another imageview underneath it, the perception is it looks like its being rubbed out without affecting the background image.

On the contrary it is rubbed out but the imageview behind, makes it look like it hasnt. When you want to export the image (You can do it in a number of ways but I went with the following) you have painted with the background image just combine both image views as the 1st imageview will have the paint you painted and the 2nd imageview will have the original background image you wanted.

    func share() {

    let layer = UIApplication.sharedApplication().keyWindow!.layer
    let scale = UIScreen.mainScreen().scale
    UIGraphicsBeginImageContextWithOptions(layer.frame.size, false, scale); // reconsider size property for your screenshot

    layer.renderInContext(UIGraphicsGetCurrentContext()!)
    let screenshot = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()


    UIGraphicsBeginImageContext(mainImageView.bounds.size)
    mainImageView.image?.drawInRect(CGRect(x: 0, y: 0,
        width: mainImageView.frame.size.width, height: mainImageView.frame.size.height))

    UIGraphicsEndImageContext()

    let activity = UIActivityViewController(activityItems: [screenshot], applicationActivities: nil)
    presentViewController(activity, animated: true, completion: nil)
}

Hope this helps others along the way.. man it took me ages to get my head around it =)

Upvotes: 1

user1343911
user1343911

Reputation:

Ok here's what I did for the eraser tool:
I add this line of code:
CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeClear);

So the code will be something something like this:

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint currentPoint = [touch locationInView:self.view];
UIGraphicsBeginImageContext(self.view.frame.size);
[drawImage.image drawInRect:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];

// I add this
CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeClear);

CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), sizeSlider.value);
CGContextBeginPath(UIGraphicsGetCurrentContext());
CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeClear);
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y);

CGContextStrokePath(UIGraphicsGetCurrentContext());
drawImage.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
lastPoint = currentPoint;
}

Upvotes: 17

Rock
Rock

Reputation: 1510

i have make paint application and it is available on iTunes "Easy Doodle" App. There is no special logic for eraser. just get RGB value of background image and pass it in

CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(),R value,G value,B value, 1.0);

according to background image selected.

Upvotes: 3

Related Questions