nano
nano

Reputation: 2521

iOS - Painting on an Image - apply mask

I have one image where users can paint over it. For painting I'm using something like:

override func touchesEnded(touches: Set<NSObject>, withEvent event: UIEvent) {
    if (touches.count == 1) {
        let touch = touches.first as! UITouch
        if (touch.tapCount == 1) {
            let touch = touches.first as! UITouch
            let currentPoint = touch.locationInView(self)
            UIGraphicsBeginImageContextWithOptions(self.frame.size, false, self.scale)
            self.image?.drawInRect(CGRectMake(0, 0, self.frame.size.width, self.frame.size.height))
            CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound)
            CGContextSetLineWidth(UIGraphicsGetCurrentContext(), self.width);
            CGContextSetStrokeColorWithColor(UIGraphicsGetCurrentContext(), UIColor.whiteColor().colorWithAlphaComponent(1.0).CGColor);
            CGContextBeginPath(UIGraphicsGetCurrentContext());

            CGContextMoveToPoint(UIGraphicsGetCurrentContext(), startPoint.x, startPoint.y);
            CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y)

            CGContextStrokePath(UIGraphicsGetCurrentContext());
            self.image = UIGraphicsGetImageFromCurrentImageContext();
            UIGraphicsEndImageContext();
        }
    }
}

So the result is a white line over the original image.

Then in the next screen I want to show just the painted line but in transparent color, so the original image can be shown. I'm trying to apply masks, but the white line is not totally transparent.

func mergeImages(image: UIImage) {
    let maskImage = UIImage(named: "03-tobacco.png")
    let maskRef = maskImage?.CGImage;

    let mask = CGImageMaskCreate(
        CGImageGetWidth(maskRef),
        CGImageGetHeight(maskRef),
        CGImageGetBitsPerComponent(maskRef),
        CGImageGetBitsPerPixel(maskRef),
        CGImageGetBytesPerRow(maskRef),
        CGImageGetDataProvider(maskRef),
        nil,
        false)
    let masked = CGImageCreateWithMask(image.CGImage, mask)
    let maskedImage = UIImage(CGImage: masked)!
    self.signatureImage.image = maskedImage
}

How can I achieve this?

Upvotes: 2

Views: 1498

Answers (4)

xKore Evolution
xKore Evolution

Reputation: 11

In Swift 5 you can try something like this:

class DrawViewTest: UIImageView {
var lastPoint: CGPoint = .zero

override init(frame: CGRect) {
    super.init(frame: frame)
    let panRecognizer = UIPanGestureRecognizer(target: self, action: #selector(handlePan(_:)))
    self.addGestureRecognizer(panRecognizer)
    self.image = UIImage(named: "your_image")
    self.isUserInteractionEnabled = true
}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

@objc func handlePan(_ gesture: UIPanGestureRecognizer) {
    let currentPoint = gesture.location(in: self)

    switch gesture.state {
    case .began:
        lastPoint = currentPoint
    case .changed:
        drawLine(from: lastPoint, to: currentPoint)
        lastPoint = currentPoint
    case .ended:
        drawLine(from: lastPoint, to: currentPoint)
    default:
        break
    }
}

func drawLine(from startPoint: CGPoint, to endPoint: CGPoint) {
    UIGraphicsBeginImageContextWithOptions(self.frame.size, false, 0)
    self.image?.draw(in: self.bounds)

    if let context = UIGraphicsGetCurrentContext() {
        context.setLineWidth(5.0)
        context.setStrokeColor(UIColor.systemRed.cgColor)
        context.setLineCap(.round)

        context.move(to: startPoint)
        context.addLine(to: endPoint)
        context.strokePath()

        self.image = UIGraphicsGetImageFromCurrentImageContext()
    }

    UIGraphicsEndImageContext()
}

}

Upvotes: 0

Neph Muw
Neph Muw

Reputation: 930

To avoid inconveniences try set up subclass of UIView above UIImageView. Set it background color to clear. And drow inside subclass of UIView - thats it.

Upvotes: 0

nano
nano

Reputation: 2521

Instead of applying masks, this is how I solved it:

UIGraphicsBeginImageContextWithOptions(size, false, 0.0)

let areaSize = CGRect(x: 0, y: 0, width: size.width, height: size.height)
image.drawInRect(areaSize
    maskImage!.drawInRect(areaSize, blendMode: kCGBlendModeSourceIn, alpha: 1.0)        
var newImage:UIImage = UIGraphicsGetImageFromCurrentImageContext()

I paint the line first and then I apply the "background" image using blend mode kCGBlendModeSourceIn so it paints only over that line.

Hope it helps others!

Upvotes: 1

Daij-Djan
Daij-Djan

Reputation: 50140

you aren't using the white line as your mask but 03-tobacco.png

if you want the white line to mask, you need to change maskImage and self.image

Upvotes: 0

Related Questions