ryan lindsey
ryan lindsey

Reputation: 155

UIImage Blend Mode Problems

I'm trying to overlay 2 images. The bottom image is loaded from the image library in to a UIImageView object with an alpha set to 1.0. All pixels in this image have an alpha value of 1.0 as well. The second image I'm creating in a context. The alpha values vary from pixel to pixel for this image. After creating the second image in context, I then draw it to a second UIImageView displayed on top of the first UIImageView. This 2nd UIImageView also has an alpha set at 1.0. Both UIImageViews have the background property set to clear.

I'm trying to change the individual alpha values of the pixels in the second image at runtime using a slider, however, I can't get the RGB values of the second image to blend properly with the 1st image. I don't want to blend based off of lightness, darkness, etc. It seems I want kCGBlendModeCopy, but this still seems to blend based off of lightness or some other parameter.

To help visualize the problem: Imagine my bottom UIImageView is a photograph of a person. My top UIImageView consists of 2 solid separated circles; 1 Red and 1 Green. Using a slider, if I change the alpha values of the pixels that are Red from 0.0 to 1.0 and back, then the Red circle should fade in to solid red, and fade complete out smoothly.

I can verify that my alpha values are working correctly by setting the RGB data array values to equal the alpha value and setting the alpha value to 1.0. This shows a black circle fading to white and back.

Here's the code I'm using to create the second image that's being overlaid on the first.

//image <-- is the name of the second UIImageView that's passed to this method
//rgbaDataNew <-- is the name of my pixel data array for the second image

CGContextRef context;
CGImageRef imageRef;    
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

context = CGBitmapContextCreate(rgbaDataNew, width, height, 8, 4 * width, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); 
imageRef = CGBitmapContextCreateImage (context);
UIImage * topImage = [UIImage imageWithCGImage:imageRef];

CGContextSetBlendMode(context, kCGBlendModeCopy);
CGContextDrawImage(context, CGRectMake(0, 0, width, height), [topImage CGImage]);

image.image = [UIImage imageWithCGImage:CGBitmapContextCreateImage (context)];

CGColorSpaceRelease(colorSpace);    
CGContextRelease(context);  
CGImageRelease(imageRef);

Upvotes: 0

Views: 2497

Answers (1)

David Hoerl
David Hoerl

Reputation: 41642

I would attack this problem in a slightly different way, but it would involve doing a small amount of Quartz work.

Create a UIView subclass and add the first imageView as a property, and also some other values to define what it is you want to do with the overlay.

In the subclass's drawRect, draw the image first using the UIImageView's - (void)drawInRect:(CGRect)rect method.

You can then use quartz to draw objects over the image exactly how you want (using the view's properties that give you the frame, color, opacity etc. You can easily find example code using Quartz.

Alternately, if you really want to use the second imageView, then you can, after drawing the bottom view, use the second view's - (void)drawInRect:(CGRect)rect blendMode:(CGBlendMode)blendMode alpha:(CGFloat)alpha method to overlay it.

In either case you use a UIView subclass.

Upvotes: 0

Related Questions