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 :)
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.
精彩评论