8

Using CoreGraphics (inside my drawRect method), I'm trying to apply a blend mode to an image (transparent png), and then adjust the alpha of the result. I'm assuming that this needs to be done in two steps, but I could be wrong. Here's what I have so far (which works fine):

CGContextRef context = UIGraphicsGetCurrentContext();

CGContextSaveGState(context);

//SET COLOR - EDIT... added a more practical color example
CGContextSetRGBFillColor(context, 0.0, 1.0, 0.0, 1);

//flips drawing context (apparently this is necessary)
CGContextTranslateCTM(context, 0.0, self.bounds.size.height);
CGContextScaleCTM(context, 1.0, -1.0);//flip context

//DRAW PIN IMAGE
UIImage *pin = [UIImage imageNamed:@"pin"];
CGRect pinrect = CGRectMake(12, 17, 25, 25);    
CGContextDrawImage(context, pinrect, pin.CGImage);//draws image in context

//Apply blend mode
CGContextSetBlendMode(context, kCGBlendModeColor); 
CGContextClipToMask(context, pinrect, pin.CGImage); // restricts drawing to within alpha channel

//fills context with mask, applying blend mode
CGContextFillRect(context, pinrect); 

CGContextRestoreGState(context);

// -- Do something here to make result 50% transparent ?? --

I'm assuming that I need to draw all this into some kind of separate context somewhere, call CGContextSetAlpha(...), and then re-draw it back to my original context, but I'm not sure how. Setting the alpha before my final CGContextFillRect will just change the amount that the blend mode was applied, not the alpha of the entire image.

EDIT: screenshot posted

enter image description here

Thanks in advance.

4
  • 1
    What if you call CGContextSetAlpha before you draw the image? You might also want to reset it to 1 after you draw the image but before you apply the blend.
    – ughoavgfhw
    Commented May 5, 2011 at 22:09
  • Thanks, but unfortunately this fades both the image as well as the amount that the blend mode is applied. ie. It'll be 50% transparent, and 50% shifted to green. I want it 100% shifted to green and then 50% transparent.
    – Chazbot
    Commented May 7, 2011 at 17:19
  • I still don't get what the result should look like, can you provide some pictures, please? Commented May 7, 2011 at 17:30
  • Did you try setting the alpha back to 1? I tested it and I think the result is what you're looking for. I'll post an answer including my result.
    – ughoavgfhw
    Commented May 7, 2011 at 19:33

1 Answer 1

8

Using transparency layers, you can apply the blend to an image drawn at 100% and display the result at 50%. The result looks like this:
Image showing output I used the textured background so that you could clearly see that the lower image is 50% transparent to everything, instead of just the other image as was the case in my previous attempt. Here is the code:

CGContextRef context = UIGraphicsGetCurrentContext();

CGContextTranslateCTM(context, 0.0, self.bounds.size.height);
CGContextScaleCTM(context, 1.0, -1.0);//flip context

CGRect fullImageRect = (CGRect){42,57,100,100};
CGRect transparentImageRect = (CGRect){12,17,100,100};
CGContextSetRGBFillColor(context, 0.0, 1.0, 0.0, 1);

// Draw image at 100%
UIImage *testImage = [UIImage imageNamed:@"TestImage"];
CGContextDrawImage(context,fullImageRect,testImage.CGImage);

// Set 50% transparency and begin a transparency layer. Inside the transparency layer, the alpha is automatically reset to 1.0
CGContextSetAlpha(context,0.5);
CGContextBeginTransparencyLayer(context, NULL);
// Draw the image. It is viewed at 100% within the transparency layer and 50% outside the transparency layer.
CGContextDrawImage(context, transparentImageRect, testImage.CGImage);
// Draw blend on top of image
CGContextClipToMask(context, transparentImageRect, testImage.CGImage);
CGContextSetBlendMode(context, kCGBlendModeColor);
CGContextFillRect(context, transparentImageRect);
// Exit transparency layer, causing the image and blend to be composited at 50%.
CGContextEndTransparencyLayer(context);

Edit: Old content removed as it took a lot of space and wasn't helpful. Look in the revision history if you want to see it.

2
  • Thanks a ton for throwing this together. In the above example, you're correct; the bottom image is drawn with the image at 50% and the blend at 100%, but it looks as though it's only 50% transparent to the pink+blue circle. In other words, 50% of the gray background does not show through your bottom image, which is what I need. The top circle does this, but it's color shift isn't 100%. Sorry to be a stickler for details, and thanks again for your help.
    – Chazbot
    Commented May 7, 2011 at 20:00
  • OK, now I understand what you want, and I figured out how to do it. You need to use transparency layers. I'll modify my post to show this.
    – ughoavgfhw
    Commented May 7, 2011 at 20:20

Not the answer you're looking for? Browse other questions tagged or ask your own question.