I am trying to make my image transparent on corners at the bottom so as to support a face curved look. I have tried with the following code but CGPathAddArc is a bit confusing as I am not much of a math bluff.
Red corners as shown in image defines the area I want to make transparent
UIGraphicsBeginImageContext(originalImage.size);
[originalImage drawAtPoint:CGPointZero];
CGMutablePathRef testRef = CGPathCreateMutable();
//CGAffineTransform temp = CGAffineTransformMakeRotation(M_PI / 2);
//CGPathAddEllipseInRect(testRef, &temp, CGRectMake(0,0,20,20));
//CGPathAddQuadCurveToPoint(testRef, nil, 20,20, 150, 150);
//CGPathAddCurveToPoint(testRef, NULL, 20, 20, 40, 40, 100, 100);
CGPathMoveToPoint(testRef, NULL, 20, 20);
CGPathAddArc(testRef, NULL, 0, 15, 15, M_PI_2, -M_PI_2, true);
// Clip to the path and clear that portion of the image.
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextAddPath(context,testRef);
CGContextClip(context);
CGContextClearRect(context,CGRectMake(0,0,originalImage.size.width,originalImage.size.height));
// Build a new UIImage from the image context.
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
if you are not that familiar with core-foundation and low level stuff, you can simple use [UIBezierPath bezierPathWithRoundedRect:byRoundingCorners:cornerRadii:] to get a Rectangle with rounded corners.
Example:
UIGraphicsBeginImageContext(originalImage.size);
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, originalImage.size.width, originalImage.size.height)
byRoundingCorners:UIRectCornerBottomLeft|UIRectCornerBottomRight
cornerRadii:CGSizeMake(15, 15)];
[path addClip];
[originalImage drawAtPoint:CGPointZero];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
Related
I'm attempting to build a UIImage in code using CoreGraphics (via PaintCode) that has a border and a corner radius. I'm finding that the image has a noticeably thicker border around the corner. This seems like it would either be an iOS bug or something that I'm completely missing. Please advise.
Code:
CGRect rect = CGRectMake(0, 0, 53, 100);
//// UIGraphics for UIImage context
CGContextRef context = UIGraphicsGetCurrentContext();
UIGraphicsPushContext(context);
UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0);
//// Rectangle Drawing
UIBezierPath *rectanglePath = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:cornerRadius];
[backgroundColor setFill];
[rectanglePath fill];
[borderColor setStroke];
rectanglePath.lineWidth = 1.4;
[rectanglePath stroke];
//// UIBezierPath to Image
CGContextAddPath(context, rectanglePath.CGPath);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsPopContext();
UIGraphicsEndImageContext();
return image;
Image:
Here's what a lineWidth of 1 and width of 60 looks like, it still seems a little thick:
For those of you following along at home:
Thanks to the helpful #PixelCutCompany I need to inset the bounds for the UIBezierPath so that the border doesn't exceed the frame of the image I am drawing.
Modified the code as follows for a lineWidth of 1.
CGRect boundedRectForRadius = CGRectMake(1, 1, 58, 98);
UIBezierPath *rectanglePath = [UIBezierPath bezierPathWithRoundedRect:boundedRectForRadius cornerRadius:cornerRadius];
Without this, it was cropping the image as so:
The problem also can be in shift real screen pixels coordinates.
Please check this discussion for more details:
Core Graphics is not drawing a line at the correct width
I have two images, one is a mask that is transparent with some edges / borders and the other is the actual image. I want to merge both of them.
I have used the following code to mask and combine the image:
- (UIImage*) maskImage:(UIImage *)image withMask:(UIImage *)maskImage {
// create a bitmap graphics context the size of the image
CGFloat dim = MIN(image.size.width, image.size.height);
CGSize size = CGSizeMake(dim, dim);
UIGraphicsBeginImageContextWithOptions(size, NO, .0);
UIBezierPath *bezierPath = [UIBezierPath bezierPathWithOvalInRect:(CGRect){ CGPointZero, size }];
[bezierPath fill];
[bezierPath addClip];
CGPoint offset = CGPointMake((dim - image.size.width) * 0.5, (dim - image.size.height) * 0.5);
[image drawInRect:(CGRect){ offset, image.size }];
UIImage *ret = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return ret;
}
The result:
In the result image, the border of the image used as a mask is missing. Can someone please help me with this?
I wrote a masking category for ios (well it is basically cross platform because CoreImage is on both platforms anyway:
github project
the core functionality boils down to this (for your example)
UIImage *person = ...
UIImage *circle = ...
UIImage *result = [person imageMaskedWith:circle];
UIImageView *redbox = [[UIImageView alloc] initWithImage:result];
redbox.backgroundColor = [UIColor redColor]; //this can be a gradient!
the main part of the code from the category:
CGImageRef imageReference = image.CGImage;
CGImageRef maskReference = mask.CGImage;
CGRect rect = CGRectMake(0, 0, CGImageGetWidth(imageReference), CGImageGetHeight(imageReference));
// draw with Core Graphics
UIGraphicsBeginImageContext(rect.size);
CGContextRef bitmap = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(bitmap, 0.0, rect.size.height);
CGContextScaleCTM(bitmap, 1.0, -1.0);
CGContextClipToMask(bitmap, rect, maskReference);
CGContextDrawImage(bitmap, rect, imageReference);
newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
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;
}
I would like to fill the transparent part of an image with another image in iOS.
I have tried some stuff with UIGraphicsContext, but I can't get it working because I've never used that before.
Here is the image:
Some code I tried:
UIImageView *v = [[UIImageView alloc] initWithFrame:CGRectMake(100, 100, 70, 70)];
UIGraphicsBeginImageContextWithOptions(v.frame.size, YES, 0);
CGContextRef context = UIGraphicsGetCurrentContext();
// beach image
UIImage *img = [UIImage imageNamed:#"zivogosce_camping_05.jpg"];
//[img drawInRect:CGRectMake(2, 0, 12, 12)];
UIImage *annotationImg = [UIImage imageNamed:#"custom_annotation"];
[annotationImg drawAtPoint:CGPointMake(0, 0)];
CGContextSetFillColorWithColor(context, [[UIColor colorWithPatternImage:img] CGColor]);
CGContextFillRect(context, CGRectMake(0, 0, 50, 50));
CGContextDrawImage(context, CGRectMake(0, 0, v.frame.size.width, v.frame.size.height), [annotationImg CGImage]);
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
[v setImage:newImage];
UIGraphicsEndImageContext();
But images don't fit well...
Here's how I would do it:
You can make a clipping path in the shape of the circle by doing something like this:
CGContextSaveGState(context);
CGRect circleRect = CGRectMake(circleCenter.x - radius, circleCenter.y - radius, radius * 2.0, radius * 2.0);
CGContextAddEllipseInRect (context, circleRect);
CGContextClip(context);
// ... do whatever you need to in order to draw the inner image ...
CGContextRestoreGState(context);
// ... draw the transparent png ...
Setting a clipping path will cause drawing to only happen within the path. When you restore the state, it removes the clipping path (or rather sets it back to its previous value which is usually allowing it to draw to the entire canvas).
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