Subtract one image from another iOS

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();

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.


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.