Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiplying RGBA with two CGImageRefs

I'd like to multiply r, g, b and a values of two CGImages, to use a single image as both a mask (in its alpha channel) and tint (in the rgb channels). I first tried simply:

CGContextDrawImage(context, CGRectMake(0, 0, _w, _h), handle());
CGContextSetBlendMode(context, kCGBlendModeMultiply);
CGContextDrawImage(context, CGRectMake(0, 0, other->width(), other->height()), over);

However, this only tints, and does not mask. Thus, I extracted the alpha from the masking image into a CGImage mask grayscale image (using a CGDataProvider) and used that as a mask on the context:

// "mask" is "other"'s alpha channel as an inverted grayscale image
CGContextSaveGState(context);
CGContextClipToMask(context, CGRectMake(0, 0, other->width(), other->height()), mask);
CGImageRelease(mask);
CGContextDrawImage(context, CGRectMake(0, 0, _w, _h), handle());
CGContextRestoreGState(context); // Don't apply the clip mask to 'other', since it already has it
CGContextSetBlendMode(context, kCGBlendModeMultiply);
CGContextDrawImage(context, CGRectMake(0, 0, other->width(), other->height()), other->handle());

It still won't look right, though. The image gets lighter; should a multiplied image be always at least darker? Previews of images at:

http://dl.dropbox.com/u/6775/multiply/index.html

Thanks in advance for enlightenment :)

like image 735
nevyn Avatar asked Dec 19 '25 17:12

nevyn


1 Answers

The first thing is that you don't need to extract the alpha channel to a separate channel to do masking. You can just draw it with kCGBlendModeDestinationIn. For an inverted mask, same thing, but with kCGBlendModeDestinationOut.

So, the solution is to draw the second image with Multiply, then draw it again with Destination In or Out.

like image 85
Peter Hosey Avatar answered Dec 23 '25 18:12

Peter Hosey



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!