Subtract one image from another iOS

2020-07-06 08:22发布

问题:

Anybody know how to create subtract one UIImage from another UIImage

for example as this screen:

Thanks for response!

回答1:

what does it mean to subtract an image? the sample image given shows more of a !red operation. let us say that to subtract image a from image b means to set every pixel in b that intersects a pixel in a to transparent. to perform the subtraction, what we are actually doing is masking image b to the inverse of image a. so, a good approach would be to create an image mask from the alpha channel of image a, then apply it to b. to create the mask you would do something like this:

// get access to the image bytes
CFDataRef pixelData = CGDataProviderCopyData(CGImageGetDataProvider(image.CGImage));

// create a buffer to hold the mask values
size_t width = CGImageGetWidth(image.CGImage);
size_t height = CGImageGetHeight(image.CGImage);    
uint8_t *maskData = malloc(width * height);

// iterate over the pixel data, reading the alpha value
uint8_t *alpha = (uint8_t *)CFDataGetBytePtr(pixelData) + 3;
uint8_t *mask = maskData;
for (int y = 0; y < height; y++) {
    for (int x = 0; x < width; x++) {
        *mask = *alpha;
        mask++;      
        alpha += 4;  // skip to the next pixel
    }
}

// create the mask image from the buffer
CGDataProviderRef maskProvider = CGDataProviderCreateWithData(NULL, maskData, width * height, NULL);
CGImageRef maskImage = CGImageMaskCreate(width, height, 8, 8, width, maskProvider, NULL, false);

// cleanup
CFRelease(pixelData);
CFRelease(maskProvider);
free(maskData);

whew. then, to mask image b, all you have to do is:

CGImageRef subtractedImage = CGImageCreateWithMask(b.CGImage, maskImage);

hey presto.



回答2:

I believe you can accomplish this by using the kCGBlendModeDestinationOut blend mode. Create a new context, draw your background image, then draw the foreground image with this blend mode.

UIGraphicsBeginImageContextWithOptions(sourceImage.size, NO, sourceImage.scale)
[sourceImage drawAtPoint:CGPointZero];
[maskImage drawAtPoint:CGPointZero blendMode:kCGBlendModeDestinationOut alpha:1.0f];
UIImage *result = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext();


回答3:

To get those results, use the second image as a mask when you draw the first image. For this kind of drawing, you'll need to use Core Graphics, a.k.a. Quartz 2D. The Quartz 2D Programming Guide has a section called Bitmap Images and Image Masks that should tell you everything you need to know.

You're asking about UIImage objects, but to use Core Graphics you'll need CGImages instead. That's no problem -- UIImage provides a CGImage property that lets you get the data you need easily.



回答4:

Kevin Ballard's solution worked for me! In Swift 3.x:

func subtract(source: UIImage, mask: UIImage) -> UIImage? {
    UIGraphicsBeginImageContextWithOptions(source.size, false, source.scale)
    source.draw(at: CGPoint.zero)
    mask.draw(at: CGPoint.zero, blendMode: .destinationOut, alpha: 1.0)
    let result = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return result
}


回答5:

An updated answer for iOS 10+ and Swift 4+:

func subtract(source: UIImage, mask: UIImage) -> UIImage? {
    return UIGraphicsImageRenderer(size: source.size).image { _ in
        source.draw(at: .zero)
        mask.draw(at: .zero, blendMode: .destinationOut, alpha: 1)
    }
}