Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS Core Graphics How to erase a drawing

I am following this tutorial for my doodle application.

http://www.raywenderlich.com/18840/how-to-make-a-simple-drawing-app-with-uikit

his erase function is using white color drawing. But I am using image background and when I erase, I really need to erase.

I have tried

CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeClear);

But it's not working. Here is my code:

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

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {

    _mouseSwiped = YES;
    UITouch *touch = [touches anyObject];
    CGPoint currentPoint = [touch locationInView:self.tempImageView];

    UIGraphicsBeginImageContext(self.tempImageView.frame.size);
    [self.tempImageView.image drawInRect:CGRectMake(0, 0, self.tempImageView.frame.size.width, self.tempImageView.frame.size.height)];
    CGContextMoveToPoint(UIGraphicsGetCurrentContext(), _lastPoint.x, _lastPoint.y);
    CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y);
    CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
    CGContextSetLineWidth(UIGraphicsGetCurrentContext(), _width );


    CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), _red, _green, _blue, 1.0);

    if (_isErasing) {
        CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeClear);
    }
    else {
        CGContextSetBlendMode(UIGraphicsGetCurrentContext(),kCGBlendModeNormal);
    }

    CGContextStrokePath(UIGraphicsGetCurrentContext());
    self.tempImageView.image = UIGraphicsGetImageFromCurrentImageContext();
    [self.tempImageView setAlpha:_alpha];
    UIGraphicsEndImageContext();

    _lastPoint = currentPoint;
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {

    CGSize size = self.tempImageView.frame.size;

    if(!_mouseSwiped) {
        UIGraphicsBeginImageContext(self.tempImageView.frame.size);
        [self.tempImageView.image drawInRect:CGRectMake(0, 0, size.width, size.height)];
        CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
        CGContextSetLineWidth(UIGraphicsGetCurrentContext(), _width);


        CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), _red, _green, _blue, _alpha);
        CGContextMoveToPoint(UIGraphicsGetCurrentContext(), _lastPoint.x, _lastPoint.y);
        CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), _lastPoint.x, _lastPoint.y);
        CGContextStrokePath(UIGraphicsGetCurrentContext());
        CGContextFlush(UIGraphicsGetCurrentContext());
        self.tempImageView.image = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
    }




    UIGraphicsBeginImageContext(self.drawImageView.frame.size);
    [self.drawImageView.image drawInRect:CGRectMake(0, 0, size.width, size.height) blendMode:kCGBlendModeNormal alpha:1.0];

    if (_isErasing) {
        CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeClear);
    }

    [self.tempImageView.image drawInRect:CGRectMake(0, 0, self.tempImageView.frame.size.width, self.tempImageView.frame.size.height) blendMode:kCGBlendModeNormal alpha:_alpha];


    self.drawImageView.image = UIGraphicsGetImageFromCurrentImageContext();
    self.tempImageView.image = nil;
    UIGraphicsEndImageContext();
}
like image 969
OMGPOP Avatar asked Mar 02 '14 18:03

OMGPOP


People also ask

What is Core Graphics in iOS?

iOS includes the Core Graphics framework to provide low-level drawing support. These frameworks are what enable the rich graphical capabilities within UIKit. Core Graphics is a low-level 2D graphics framework that allows drawing device independent graphics. All 2D drawing in UIKit uses Core Graphics internally.

What can you do with Core Graphics?

Handle path-based drawing, antialiased rendering, gradients, images, color management, PDF documents, and more. The Core Graphics framework is based on the Quartz advanced drawing engine. It provides low-level, lightweight 2D rendering with unmatched output fidelity.

How does drawing to the screen work in iOS?

In iOS, all drawing to the screen—regardless of whether it involves OpenGL, Quartz, UIKit, or Core Animation—occurs within the confines of an instance of the UIView class or a subclass thereof. Views define the portion of the screen in which drawing occurs. If you use system-provided views, this drawing is handled for you automatically.

How do I draw text with Core Graphics?

As with paths and images, drawing text with Core Graphics involves the same basic pattern of setting some graphics state and calling a method to draw. In the case of text, the method to display text is ShowText. When added to the image drawing example, the following code draws some text using Core Graphics:


2 Answers

solved this problem by swapping tempImageView and drawImageView when touch began if it's erasing

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    _mouseSwiped = NO;
    UITouch *touch = [touches anyObject];
    _lastPoint = [touch locationInView:self.tempImageView];

    if (_isErasing) {
        self.tempImageView.image = self.drawImageView.image;
        self.drawImageView.image = nil;
    }

}



- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {

    _mouseSwiped = YES;
    UITouch *touch = [touches anyObject];
    CGPoint currentPoint = [touch locationInView:self.tempImageView];

    UIGraphicsBeginImageContext(self.tempImageView.frame.size);
    [self.tempImageView.image drawInRect:CGRectMake(0, 0, self.tempImageView.frame.size.width, self.tempImageView.frame.size.height)];
    CGContextMoveToPoint(UIGraphicsGetCurrentContext(), _lastPoint.x, _lastPoint.y);
    CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y);
    CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
    CGContextSetLineWidth(UIGraphicsGetCurrentContext(), _width );


    if (_isErasing) {
        CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeClear);
    }
    else {
        CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), _red, _green, _blue, 1.0);
        CGContextSetBlendMode(UIGraphicsGetCurrentContext(),kCGBlendModeNormal);
    }

    CGContextStrokePath(UIGraphicsGetCurrentContext());
    self.tempImageView.image = UIGraphicsGetImageFromCurrentImageContext();
    [self.tempImageView setAlpha:_alpha];
    UIGraphicsEndImageContext();

    _lastPoint = currentPoint;
}





- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {

    CGSize size = self.tempImageView.frame.size;

    if(!_mouseSwiped) {
        UIGraphicsBeginImageContext(self.tempImageView.frame.size);
        [self.tempImageView.image drawInRect:CGRectMake(0, 0, size.width, size.height)];
        CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
        CGContextSetLineWidth(UIGraphicsGetCurrentContext(), _width);


        if (_isErasing) {
            CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeClear);
        }
        else {
            CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), _red, _green, _blue, _alpha);
            CGContextSetBlendMode(UIGraphicsGetCurrentContext(),kCGBlendModeNormal);
        }

        CGContextMoveToPoint(UIGraphicsGetCurrentContext(), _lastPoint.x, _lastPoint.y);
        CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), _lastPoint.x, _lastPoint.y);
        CGContextStrokePath(UIGraphicsGetCurrentContext());
        CGContextFlush(UIGraphicsGetCurrentContext());
        self.tempImageView.image = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
    }




    UIGraphicsBeginImageContext(self.drawImageView.frame.size);
    [self.drawImageView.image drawInRect:CGRectMake(0, 0, size.width, size.height) blendMode:kCGBlendModeNormal alpha:1.0];
    [self.tempImageView.image drawInRect:CGRectMake(0, 0, size.width, size.height) blendMode:kCGBlendModeNormal alpha:_alpha];
    self.drawImageView.image = UIGraphicsGetImageFromCurrentImageContext();
    self.tempImageView.image = nil;
    UIGraphicsEndImageContext();
}
like image 148
OMGPOP Avatar answered Oct 05 '22 22:10

OMGPOP


If anybody is still intereted this is how it worked for me in Swift 3. Thanks for the help OMGPOP

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    swiped = false
    hideAllButtons()
    if let touch = touches.first {
        lastPoint = touch.location(in: self.view)
    }

    if isErasing {
        self.tempImageView.image = self.mainImageView.image
        self.mainImageView.image = nil
    }
}

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    swiped = true
    if let touch = touches.first {
        let currentPoint = touch.location(in: view)
        drawLineFrom(fromPoint: lastPoint, toPoint: currentPoint)

        lastPoint = currentPoint
    }

}

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    showAllButtons()
    if !swiped {
        drawLineFrom(fromPoint: lastPoint, toPoint: lastPoint)
    }

    UIGraphicsBeginImageContext(mainImageView.frame.size)
    mainImageView.image?.draw(in: CGRect(x: 0, y: 0, width: view.frame.size.width, height: view.frame.size.height), blendMode: .normal, alpha: 1.0)
    tempImageView.image?.draw(in:  CGRect(x: 0, y: 0, width: view.frame.size.width, height: view.frame.size.height), blendMode: .normal, alpha: opacity)
    mainImageView.image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    tempImageView.image = nil
}

// Draws a line between two points on the view
func drawLineFrom(fromPoint: CGPoint, toPoint: CGPoint) {
    UIGraphicsBeginImageContext(view.frame.size)
    let context = UIGraphicsGetCurrentContext()
    tempImageView.image?.draw(in: CGRect(x:0, y:0, width: view.frame.size.width, height: view.frame.size.height))

    context?.move(to: fromPoint)
    context?.addLine(to: toPoint)

    context?.setLineCap(.round)
    context?.setLineWidth(brushWidth)

    if isErasing {
        context?.setBlendMode(.clear)
    } else {
        context?.setStrokeColor(red: red, green: green, blue: blue, alpha: 1.0)
        context?.setBlendMode(.normal)
    }
    context?.strokePath()

    tempImageView.image = UIGraphicsGetImageFromCurrentImageContext()
    tempImageView.alpha = opacity
    UIGraphicsEndImageContext()

}
like image 43
benhofmann Avatar answered Oct 06 '22 00:10

benhofmann