iOS: 2 Step Image Processing with CoreGraphics - iphone

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
Thanks in advance.

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:
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.

Related

How can I reset or clear the clipping mask associated with a CGContext?

I'm drawing to a CGContext and using a CGImageRef-based mask:
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextClipToMask(context, rect, _firstMaskImageRef);
CGContextSetFillColorWithColor(context, color);
CGContextFillRect(context, rect);
I have a second mask that I then want to switch to:
CGContextClipToMask(context, rect, _secondMaskImageRef);
CGContextSetFillColorWithColor(context, color); // color has changed FWIW
CGContextFillRect(context, rect); // as has rect
But, this intersects the two masks instead of replacing the first.
How do you (if you can) clear out or reset the clipping mask for a CGContext?
You can save the graphics state before you set the clipping mask, and then reset it afterwards, like this:
CGContextSaveGState (context);
...Set your first clipping mask, fill it, etc.
CGContextRestoreGState (context);
...Do other stuff
To reset the clipping mask, use:
CGContextResetClip(context);
Later versions of Swift (3+?) use the following syntax instead:
context.saveGState()
// set your clipping mask, etc.
context.restoreGState()
// everything's back to normal

Filling Colors inside edges

I am new to Iphone development.
Currently i am making coloring app.
I am using apple's paint app as ref to create my app.
I successfully create app where u can color on a screen with given texture image
What i did is
I create a custom UIView which extends opengl and i detect touches on it and draw accordingly.
I also kept background UIImageView which contain outline images, so it feels like your drawing above that Image.
Everything works fine
but i wanted to fill color inside black edges
Like if a image has four square which has black edges and inside of that square is blank and if i touch any square it should fill that square with selected color(mostly i am working on irregular shape)
Can anyone tell me how can i fill colors inside that square
The flood fill algo looks slow as i have some big images which will take time to fill the color
so is there any easy method by which i can fill color
A sample code will b very helpful as i am new to iPhone Dev
I implemnted this kind of feature in my recent project. The difference is: I filled color in border only.
Check my code over here, it might get helpful to you
// apply color to only border & return an image
+ (UIImage *)imageNamed:(NSString *)name withColor:(UIColor *)color
{
// load the image
UIImage *img = [UIImage imageNamed:name];
// begin a new image context, to draw our colored image onto
UIGraphicsBeginImageContext(img.size);
// get a reference to that context we created
CGContextRef context = UIGraphicsGetCurrentContext();
// set the fill color
[color setFill];
// translate/flip the graphics context (for transforming from CG* coords to UI* coords
CGContextTranslateCTM(context, 0, img.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
// set the blend mode to color burn, and the original image
CGContextSetBlendMode(context, kCGBlendModeColorBurn);
CGRect rect = CGRectMake(0, 0, img.size.width, img.size.height);
CGContextDrawImage(context, rect, img.CGImage);
// set a mask that matches the shape of the image, then draw (color burn) a colored rectangle
CGContextClipToMask(context, rect, img.CGImage);
CGContextAddRect(context, rect);
CGContextDrawPath(context,kCGPathFill);
// generate a new UIImage from the graphics context we drew onto
UIImage *coloredImg = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
//return the color-burned image
return coloredImg;
}
Enjoy Programming !

CGImageCreateWithImageInRect causing distortion

I'm using CGImageCreateWithImageInRect to do a magnifying effect, and it works beautifully, except when I get close to the edges of my view. In that case, clipping causes the image to be distorted. Right now I grab a 72x72 chunk of the view, apply a round mask to it, and then draw the masked image, and a circle on top.
When the copied chunk is near the edge of the view, It winds up smaller than 72x72 because of clipping, and then when it's drawn in the magnifying glass it gets stretched out.
When the touch point is close to the left edge, for example, I would like to create an image where the left part is filled with a solid color, and the right half contains part of the view that's being magnified. Then apply the mask to that image and add the overlay on top.
Here's what I'm doing now. imageRef is the image being magnified, mask is a round mask, and overlay is a circle to mark the edges of the magnified region.
CGImageRef subImage = CGImageCreateWithImageInRect(imageRef, CGRectMake(touchPoint.x - 36, touchPoint.y - 36, 72, 72));
CGImageRef xMaskedImage = CGImageCreateWithMask(subImage, mask);
CGContextRef context = UIGraphicsGetCurrentContext();
CGAffineTransform xform = CGAffineTransformMake(1.0, 0.0, 0.0, -1.0, 0.0, 0.0);
CGContextConcatCTM(context, xform);
CGRect area = CGRectMake(touchPoint.x - 84, -touchPoint.y, 170, 170);
CGRect area2 = CGRectMake(touchPoint.x - 80, -touchPoint.y + 4, 160, 160);
CGContextDrawImage(context, area2, xMaskedImage);
CGContextDrawImage(context, area, overlay);
I solved this by using CGBitmapContextCreate() to create a bitmap context. Then I drew the captured area into a smaller area of this context, and created an image from it with CGBitmapContextCreateImage(). That was the missing piece of the puzzle.

iPhone: How to change the color of an image

I have a small image from a database and the image's average color need to be altered slightly.
It's a CGImageRef and I thought of creating a CGContext, drawing the image to this context, then subsequently changing the bitmap data somehow and finally rendering it.
But how can I alter the color information?
Thanks for your help!
Check out this Apple Q&A on pixel data manipulation for details on how you might go about that.
Draw a color onto the object like this:
// first draw image
[self.image drawInRect:rect];
// prepare the context to draw into
CGContextRef context = UIGraphicsGetCurrentContext();
// set the blend mode and draw rectangle on top of image
CGContextSetBlendMode(context, kCGBlendModeColor);
CGContextClipToMask(context, self.bounds, image.CGImage); // this restricts drawing to within alpha channel
CGContextSetRGBFillColor(context, 0.75, 0.0, 0.0, 1.0); // this is your color, a light reddish tint
CGContextFillRect(context, rect);
I put this into the drawRect: method of a custom UIView. That UIView has an ivar, UIImage *image that holds the image you want to tint or color.

how to draw on the surface of imageview transparently

i want to track finger touch and draw the path on top of the imageView.
following is what i did:
In the touch event:
UIgraphicsBeginImageContext(imageView.frame.size);
[imageView.image drawInRect:CGRectMake(0,0,imageView.size.width,imageView.size.height)];
//drawing.....
imageView.image=UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
however, the drawing opaque the background Image?
how to drawing the path while still can make the background available?
thanks in advance:)
If you're doing simple vector drawing, you can set a color with a non-1.0 alpha value. These shapes will then be translucent when you draw them on top of your image. For example:
CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
CGFloat values[4] = {1.0, 0.0, 0.0, 0.5};
CGColorRef translucentRed = CGColorCreate(space, values);
CGContextSetStrokeColorWithColor(context, translucentRed);
CGContextSetFillColorWithColor(context, translucentRed)
// Do your drawing here
CGColorRelease(translucentRed);
CGColorSpaceRelease(space);
will create a translucent red color and set the current stroke and fill to use that color.
Note that overlapping drawn elements will have darker areas because of this translucency, which might be an effect that you don't want.