Crop an image by drawing with finger touches - ios

I am working on an application wherein the user draws some closed area on an image. I want to crop any closed area drawn on that image. In a way I would like to achieve this functionality in this app
I have done the drawing part using touches method and CGContext but I am unable to crop the drawn area. Please help me out. i am running out of time for the dead line.

I guess you have a CGPathRef that you where able to draw in the CGContext.
From there you can create a layer, assign the image as a content and use a CAShapeLayer a s a mask to crop it.
CGPathRef path;
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
[shapeLayer setPath:path];
CALayer *imgLayer = [CALayer layer];
[imgLayer setContents:img];
[imgLayer setMask:shapeLayer];
[self.layer addSublayer:imgLayer];

Related

Change fill color of a part of a combined path with animation?

In simple words only part of my icon must change color at some event.
I drawing an icon with curves inside an UIView. The drawing boilds
down to combining several paths together like this (swift code):
let combinedPath = CGPathCreateMutableCopy(bezierPath.CGPath)
CGPathAddPath(combinedPath, nil, bezier2Path.CGPath);
CGPathAddPath(combinedPath, nil, bezier3Path.CGPath);
Then I'm adding the combined path to the UIView like this (obj-c, sorry for
the mix):
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.frame = self.bounds;
shapeLayer.path = combinedPath;
self.layer.mask = shapeLayer;
And now at some point in time I want to change the fill color of
only one bezierPath with animation. How can I do this?
You can clean the current mask, and redraw any of the bezierpath with stroke/fill color and combine them together, and set it again. And for drawing animation, you can refer to How to Animate CoreGraphics Drawing of Shape Using CAKeyframeAnimation

Draw circle around an imageview [duplicate]

This question already has answers here:
Circular Progress Bars in IOS
(7 answers)
Closed 7 years ago.
I want circlular border to appear on my profile image. I also want only a certain percentage of the border to be completed based on how much of the profile information is completed.
If username, email, gender, school and address is required, and if the user only provides 3 of the above fields i want the circular border to be 60% completed and likewise.
My code is as follows: However, it only displays a 100% completed circle and i am not able to control what percentage of the circle i am suppose to colour. How can i solve this ? The following image demonstrates what i want to achieve.
Image
Code
self.profileImageView.layer.cornerRadius = self.profileImageView.frame.size.width / 2;
self.profileImageView.layer.borderColor = [UIColor whiteColor].CGColor;
self.profileImageView.clipsToBounds = YES;
Just if in case you want the answer by means of code, here it is.
UIBezierPath *circlePath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(200, 400) radius:20.f startAngle:-M_PI_2 endAngle:0 clockwise:NO];
CAShapeLayer *shapeLayer = [[CAShapeLayer alloc] init];
[shapeLayer setStrokeColor:[UIColor blueColor].CGColor];
[shapeLayer setFillColor:[UIColor clearColor].CGColor];
[shapeLayer setLineWidth:5.f];
[shapeLayer setPath:circlePath.CGPath];
[self.view.layer addSublayer:shapeLayer];
The reason you're having trouble with this is that cornerRadius is just a lazy way out. You need to look into drawing the arc yourself.
There are various levels of laziness for this too. The easiest way is to draw it in a layer in front of the image. And even then you have choices: you can draw it using Quartz drawing calls, or you can ask a CAShapeLayer to draw it for you. One nice thing about the CAShapeLayer is that you can easily animate the growth of the arc (by changing the strokeEnd).

Drawing custom shape and animating custom properties using CALayers?

I have a custom shape that i want to draw using UIBezierPaths and i want to use this drawing as a CALayer inside my view. The bezier path i use works if i draw it directly onto the UIView (inside drawRect). I want to know as to how i can use the same bezier drawing and perform the drawing inside my CALayer. I would then add this layer as a sub layer inside my view!
For instance lets say I'm drawing a concentric circle with my bezier paths and i want to draw this using a CALayer, how would i go about animating custom properties of the path, like its center, radius, startAngle and endAngle?
Specifically i want to know how i should
Arrange my CALayer (initializing, drawing , upadte drawing ,etc)
How do i draw the bezier inside my CALayer?
How do i interact between the layer and the view that contains it?
Any help is appreciated!
Here's how you create & draw a UIBezierPath in a CALayer. Using a CAShapeLayer is the easiest way:
UIBezierPath *circlePath = [UIBezierPath bezierPathWithOvalInRect:...];
CAShapeLayer *circleLayer = [CAShapeLayer layer];
circleLayer.path = circlePath.CGPath;
[self.view.layer addSublayer:circleLayer];
Here's a good tutorial on creating animatable properties in CALayers.

Why the circle path of the cashapelayer is not so round?

The doucumet said that the CAShapLayer is anti-aliased ,why got this result.
I also draw a circle with the CGContext in the drawRect method,It's very perfect.
UIBezierPath *path = [UIBezierPath bezierPath];
[path appendPath:[UIBezierPath bezierPathWithOvalInRect:CGRectMake(150, 300, 136, 136)]];
self.circleLayer = [CAShapeLayer layer];
self.circleLayer.path = path.CGPath;
self.circleLayer.frame = self.bounds;
self.circleLayer.fillColor = [[UIColor whiteColor] colorWithAlphaComponent:0.6].CGColor;
[self.layer addSublayer:self.circleLayer];
According to the UIBezierPath docs, bezierPathWithOvalInRect: "creates a closed subpath that approximates the oval using a sequence of Bézier curves," so it may not draw a perfect circle.
If you use a UIBezierPath to draw a circle will not a perfect circle because its an approximation from Bézier curves.
You can draw a perfect circle from a square UIView. For example:
myView.layer.cornerRadius = myView.frame.size.width/2;
In this topic explain three methods to draw a circle -> How to draw a smooth circle with CAShapeLayer and UIBezierPath?
iOS 12:
I had the same issue on iPhone XS and XS Max. I don't know why, but on iPhone 8 there was no issue. The circle was perfectly round.
To solve the issue on XS and XS Max I set the flatness property of UIBezierPath to 0.0 and made sure that the center of the rect used for UIBezierPath is either an integer number or a floating number of e.g. 25.5. The center of my rect was y=51.166666 and this caused the issue that the oval was not round.

Why is making two corners round slower than make all corners round?

Edit: Language updated to improve readability.
I made an image view with 2 rounded corners like this:
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:self.photoImageView.bounds byRoundingCorners:UIRectCornerBottomLeft|UIRectCornerBottomRight cornerRadii:CGSizeMake(10, 10)];
CAShapeLayer *maskLayer = [CAShapeLayer layer];
maskLayer.path = maskPath.CGPath;
self.photoImageView.layer.mask = maskLayer;
But it is slower than making all the corners round using this code.
self.photoImageView.layer.cornerRadius = 10;
Would anyone know what why and how I can improve my '2 corner' code please?
Your code is adding another stage to the drawing. Normally, the background is drawn (with the given cornerRadius) directly to the target, but with a mask specified, it is drawn to a temporary surface, then copied to the target using the mask.
There isn't any built-in functionality for only rounding some background corners in the standard CALayer object.
I do wonder how slow "slower" really is; is this premature optimisation?

Resources