IOS set transparent border of path of cgcontext - ios

I have added a bezier path to my context as follows
for (Face* face in facesArray) {
UIBezierPath* customPath = [UIBezierPath bezierPath];
[customPath moveToPoint:face.rightEyePosition];
[customPath addQuadCurveToPoint:face.leftEyePosition controlPoint:face.foreheadPosition];
[customPath addQuadCurveToPoint:face.mouthPosition controlPoint:face.lowerLeftContrlPoint];
[customPath moveToPoint:face.rightEyePosition];
[customPath addQuadCurveToPoint:face.mouthPosition controlPoint:face.lowerRightContrlPoint];
UIGraphicsBeginImageContextWithOptions(originalImage.size, NO, 0.0);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextBeginPath (context);
CGContextAddPath(context,customPath.CGPath);
CGContextClosePath (context);
CGContextClip (context);
[imageView.image drawInRect: CGRectMake(0, 0, imageView.image.size.width, imageView.image.size.height)];
UIImage* resultImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
Above code crops the image according to bezier shape. I want borders of cropped image transparent. How should I set transparency to corners ob bezier path

Related

Remove outside of bezier path

I have a function where I fill the image with a color and use a UIBezierPath to erase a point for corners.
CGRect rect = CGRectMake(0.0f, 0.0f, width, height);
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetBlendMode(context, kCGBlendModeCopy);
// Fill image
CGContextSetFillColorWithColor(context, [[UIColor redColor] CGColor]);
CGContextFillRect(context, rect);
// Round corners
UIBezierPath *bezierPath = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:15.0];
CGContextSetStrokeColorWithColor(context, [[UIColor clearColor] CGColor]);
[bezierPath stroke];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
With the above, I get an image that does have the Bézier path cut out, and the background filled.
However, how can I remove the corners outside of the path, or get at least some way to reference where they are so I can clear them?
A couple of options:
Use CoreGraphics, like you have, but clip it to a path:
CGRect rect = CGRectMake(0.0f, 0.0f, width, height);
UIGraphicsBeginImageContextWithOptions(rect.size, false, 0);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetBlendMode(context, kCGBlendModeCopy);
// Round corners
UIBezierPath *bezierPath = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:15.0];
CGContextAddPath(context, bezierPath.CGPath);
CGContextClip(context);
// Fill image
CGContextSetFillColorWithColor(context, [[UIColor redColor] CGColor]);
CGContextFillRect(context, rect);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
Alternatively, eliminate CoreGraphics and just fill the UIBezierPath:
UIGraphicsBeginImageContextWithOptions(rect.size, false, 0);
[[UIColor redColor] setFill];
[[UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:15.0] fill];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
Note, in both of those examples, I used UIGraphicsBeginImageContextWithOptions, supplying a scale of 0 (a scale optimized for display on the device in question). If you really want, you can supply a scale of 1, which obviously will be a bit pixelated when rendered on a retina device, but that's up to you.

Drawing cicles on an image view objective c

I am trying to draw circles on an image view for an ios application and there will be many circles and I want them to be in the same layer. My circle drawing code is;
UIBezierPath *circle = [UIBezierPath bezierPathWithArcCenter:center
radius:radius
startAngle:0
endAngle:2.0*M_PI
clockwise:YES];
CAShapeLayer *circleLayer = [CAShapeLayer layer];
circleLayer.bounds = CGRectMake(0, 0, 2.0*radius, 2.0*radius);
circleLayer.path = circle.CGPath;
circleLayer.backgroundColor = [UIColor orangeColor].CGColor;
and I need some thing different than the code below;
[imageView.layer addSublayer:circleLayer];
thanks.
From this site: http://www.cocoanetics.com/2010/07/drawing-on-uiimages/
- (UIImage *)imageByDrawingCircleOnImage:(UIImage *)image
{
// begin a graphics context of sufficient size
UIGraphicsBeginImageContext(image.size);
// draw original image into the context
[image drawAtPoint:CGPointZero];
// get the context for CoreGraphics
CGContextRef ctx = UIGraphicsGetCurrentContext();
// set stroking color and draw circle
[[UIColor redColor] setStroke];
// make circle rect 5 px from border
CGRect circleRect = CGRectMake(0, 0,
image.size.width,
image.size.height);
circleRect = CGRectInset(circleRect, 5, 5);
// draw circle
CGContextStrokeEllipseInRect(ctx, circleRect);
// make image out of bitmap context
UIImage *retImage = UIGraphicsGetImageFromCurrentImageContext();
// free the context
UIGraphicsEndImageContext();
return retImage;
}

Gradient Filling a PNG with Quartz

How can I fill the non-transparent areas of a PNG UIImage with a linear gradient? I'd like to reuse a PNG shape for MKAnnotationViews, but change the gradient per annotation's properties.
To use an image as a mask for a gradient (i.e. to have a gradient in the shape of the non-transparent pixels of your image), you can:
create a simple view with a gradient (you can either create a simple UIView and use the addGradientLayerToView shown below to give it a gradient or you can create the gradient PNG in advance and add it to your bundle).
apply your PNG as a mask to that gradient view:
UIImage *mask = [UIImage imageNamed:#"mask.png"];
CALayer *maskLayer = [CALayer layer];
maskLayer.frame = CGRectMake(0, 0, mask.size.width, mask.size.height);
maskLayer.contents = (id)[mask CGImage];
gradientViewToMask.layer.mask = maskLayer;
To apply a gradient to the transparent pixels, you can either:
Create a new image with a gradient:
- (UIImage *)imageWithGradient:(UIImage *)image
{
UIGraphicsBeginImageContextWithOptions(image.size, NO, 1.0);
CGContextRef context = UIGraphicsGetCurrentContext();
size_t locationCount = 2;
CGFloat locations[2] = { 0.0, 1.0 };
CGFloat components[8] = { 0.0, 0.8, 0.8, 1.0, // Start color
0.9, 0.9, 0.9, 1.0 }; // End color
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
CGGradientRef gradient = CGGradientCreateWithColorComponents (colorspace, components, locations, locationCount):
CGPoint startPoint = CGPointMake(0.0, 0.0);
CGPoint endPoint = CGPointMake(0.0, image.size.height);
CGContextDrawLinearGradient (context, gradient, startPoint, endPoint, 0);
CGContextTranslateCTM(context, 0, image.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
CGContextDrawImage(context, CGRectMake(0.0, 0.0, image.size.width, image.size.height), [image CGImage]);
UIImage *gradientImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
CGGradientRelease(gradient);
CGColorSpaceRelease(colorspace);
return gradientImage;
}
You can also add a CAGradientLayer to a view and then add the UIImageView as a subview of that view.
- (void)addGradientLayerToView:(UIView *)view
{
CAGradientLayer *gradient = [CAGradientLayer layer];
gradient.frame = view.bounds;
gradient.colors = #[(id)[[UIColor colorWithRed:0.0 green:0.8 blue:0.8 alpha:1.0] CGColor],
(id)[[UIColor colorWithRed:0.9 green:0.9 blue:0.9 alpha:1.0] CGColor]];
[view.layer insertSublayer:gradient atIndex:0];
}
Note, you have to #import <QuartzCore/QuartzCore.h> as well as add the QuartzCore framework to your project.
I ended up hacking together some bits of Rob's code and an extension to UIImage I found at http://coffeeshopped.com/2010/09/iphone-how-to-dynamically-color-a-uiimage
+ (UIImage *)imageNamed:(NSString *)name withGradient:(CGGradientRef)gradient
{
// load the image
UIImage *img = [UIImage imageNamed:name];
// begin a new image context, to draw our colored image onto
UIGraphicsBeginImageContextWithOptions(img.size, NO, [[UIScreen mainScreen] scale]);
// get a reference to that context we created
CGContextRef context = UIGraphicsGetCurrentContext();
// 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 overlay, and the original image
CGContextSetBlendMode(context, kCGBlendModeOverlay);
CGRect rect = CGRectMake(0, 0, img.size.width, img.size.height);
// set a mask that matches the shape of the image, then draw (overlay) a colored rectangle
CGContextClipToMask(context, rect, img.CGImage);
CGContextAddRect(context, rect);
//gradient
CGPoint startPoint = CGPointMake(0.0, img.size.height);
CGPoint endPoint = CGPointMake(0.0, 0.0);
CGContextDrawLinearGradient (context, gradient, startPoint, endPoint, 0);
// generate a new UIImage from the graphics context we drew onto
UIImage *coloredImg = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
CGGradientRelease(gradient);
//return the color-burned image
return coloredImg;
}

How to crop an uiimageView from a rectangle overlay?

I want to crop a part of an uiimageview that on my view controller. I'm creating a rectangle on top of it:
UIGraphicsBeginImageContext(self.view.bounds.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextMoveToPoint(context, newPoint1.x, newPoint1.y);
CGContextAddLineToPoint(context, newPoint1.x, newPoint2.y);
CGContextAddLineToPoint(context, newPoint2.x, newPoint2.y);
CGContextAddLineToPoint(context, newPoint2.x, newPoint1.y);
CGContextAddLineToPoint(context, newPoint1.x, newPoint1.y);
CGContextClosePath(context);
UIColor *blue = [UIColor colorWithRed: (0.0/255.0 ) green: (0.0/255.0) blue: (255.0/255.0) alpha:0.4];
CGContextSetFillColorWithColor(context, blue.CGColor);
CGContextDrawPath(context, kCGPathFillStroke);
I can't figure out how to crop it right. I'm able to retrieve a capture of the screen : entirely blank with my rectangle on it:
UIImage *cropImage = UIGraphicsGetImageFromCurrentImageContext();
rectImage = cropImage;
UIGraphicsEndImageContext();
UIImageCrop *rectImageView = [[UIImageCrop alloc]initWithImage:rectImage];
[self.view addSubview:rectImageView];
So I'm aware that there is something I've missed about it, any help?
- (UIImage *)captureScreenInRect:(CGRect)captureFrame
{
CALayer *layer;
layer = self.view.layer;
UIGraphicsBeginImageContext(self.view.frame.size);
CGContextClipToRect (UIGraphicsGetCurrentContext(),captureFrame);
[layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *screenImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return screenImage;
}
this is just for reference change this code according to your requirement
hope this will help you
You can get cropped image using :
- (UIImage*) getCroppedImage {
CGRect rect = PASS_YOUR_RECT;
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
// translated rectangle for drawing sub image
CGRect drawRect = CGRectMake(-rect.origin.x, -rect.origin.y, your_image.size.width, your_image.size.height);
// clip to the bounds of the image context
// not strictly necessary as it will get clipped anyway?
CGContextClipToRect(context, CGRectMake(0, 0, rect.size.width, rect.size.height));
// draw image
[your_image drawInRect:drawRect];
// grab image
UIImage* croppedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return croppedImage;
}
Hope it helps you.

iOS: Inverse UIBezierPath (bezierPathWithOvalInRect)

I have an jpg Image with a round object in a rect and want to make the envoirement of the round object transparent...
(Remove red area in this example)
With the help of this iOS make part of an UIImage transparent and "UIBezierPath bezierPathWithOvalInRect" i've got a little success, but this make a path around my object, and I need to invert it, to make the outside and not the inside of the path transparent..
Im not shure where I have to change my code to get the right result..
Here is my code:
//BezierPath
UIBezierPath *bezierPath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, 100, 100)];
// Create an image context containing the original UIImage.
UIGraphicsBeginImageContext(_imgTemp.image.size);
[_imgTemp.image drawAtPoint:CGPointZero];
// Clip to the bezier path and clear that portion of the image.
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextAddPath(context,bezierPath.CGPath);
CGContextClip(context);
CGContextClearRect(context,CGRectMake(0,0,self._imgTemp.image.size.width,self._imgTemp.image.size.height));
// Build a new UIImage from the image context.
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
self._imgTemp.image = newImage;
Anybody got the resolving?
To only draw within the black circle you should move [_imgTemp.image drawAtPoint:CGPointZero]; to after CGContextClip(context); and then remove the CGContextClearRect( ... ) call entirely:
//BezierPath
UIBezierPath *bezierPath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, 100, 100)];
// Create an image context containing the original UIImage.
UIGraphicsBeginImageContext(_imgTemp.image.size);
// Clip to the bezier path and clear that portion of the image.
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextAddPath(context,bezierPath.CGPath);
CGContextClip(context);
// Draw here when the context is clipped
[_imgTemp.image drawAtPoint:CGPointZero];
// Build a new UIImage from the image context.
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
self._imgTemp.image = newImage;

Resources