Search code examples
cocoamacosquartz-graphics

Multiplying colors when compositing with Quartz


I'm trying to draw an image with a certain color. To get this effect, first I draw the image (consisting of mostly white and black), and then I draw a rectangle over it in a specified color (let's say red). There are various compositing options available, but none are exactly what I want.

I want the colors (and alpha values) to be multiplied together. I think this is sometimes called a "Modulate" operation in other graphics systems. So, the white values in the image will be multiplied by the red values in the overlay rectangle to produce red. The black values in the image will be multiplied with black to product black.

In other words, R = S * D (result equals source multiplied by destination).

This is the code I'm working with now:

[image drawInRect:[self bounds] fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1];

NSColor * blend = [NSColor colorWithCalibratedRed:1 green:0 blue:0 alpha:1.0];

[blend setFill];
NSRectFillUsingOperation(self.bounds, NSCompositePlusDarker);

NSCompositePlusDarker is NOT what I want, but it's close. (It's addition instead of multiplication).

Is there a way to do this in Quartz? It's very easy to do in OpenGL for instance. I've looked at CIFilter's but they seem a bit cumbersome for this. But if that's the only way, I would appreciate any sample code to get me in the right direction.


Solution

  • Yes.

    Note that AppKit compositing operations and Quartz blend modes, though there are quite a few in common, are not interchangeable. kCGBlendModeMultiply has the same numeric value as NSCompositeCopy, so the latter—flat overwriting—is what will happen if you try to pass it to any of AppKit's drawing APIs.

    So, you'll need to use Quartz for every part of the fill. You can use NSGraphicsContext to get the CGContext you'll need, and you can ask your NSColor for its CGColor.