get circular part of image - ios

i am trying to imitate the new contact ios7 behavior.
I have a UIScrollView with a UImageView inside.
With this code i can draw the circular shape in front of the image.
-(void)viewWillAppear:(BOOL)animated
{
CGFloat screenHeight = [[UIScreen mainScreen] bounds].size.height;
int position = 0;
if (screenHeight == 568)
{
position = 124;
}
else
{
position = 80;
}
CAShapeLayer *circleLayer = [CAShapeLayer layer];
UIBezierPath *path2 = [UIBezierPath bezierPathWithOvalInRect:
CGRectMake(0.0f, position, 320.0f, 320.0f)];
[path2 setUsesEvenOddFillRule:YES];
[circleLayer setPath:[path2 CGPath]];
[circleLayer setFillColor:[[UIColor clearColor] CGColor]];
path;
path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, 320, screenHeight-44) cornerRadius:0];
[path appendPath:path2];
[path setUsesEvenOddFillRule:YES];
fillLayer = [CAShapeLayer layer];
fillLayer.path = path.CGPath;
fillLayer.fillRule = kCAFillRuleEvenOdd;
fillLayer.fillColor = [UIColor blackColor].CGColor;
fillLayer.opacity = 0.8;
[self.view.layer addSublayer:fillLayer];
UILabel *moveLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 10, 320, 50)];
[moveLabel setText:#"Mueva y escale"];
[moveLabel setTextAlignment:NSTextAlignmentCenter];
[moveLabel setTextColor:[UIColor whiteColor]];
[self.view addSubview:moveLabel];
}
I need to get the portion of the image that is inside the circle when the user choose "Use Photo" option.

I wrote this category
#implementation UIImage (PathCropping)
-(UIImage *)imageCroppedWithPath:(UIBezierPath *)path
{
return [self imageCroppedWithPath:path invertPath:NO];
}
-(UIImage *)imageCroppedWithPath:(UIBezierPath *)path
invertPath:(BOOL)invertPath
{
float scaleFactor = [self scale];
CGRect imageRect = CGRectMake(0, 0, self.size.width * scaleFactor, self.size.height *scaleFactor);
CGColorSpaceRef colorSpace = CGImageGetColorSpace(self.CGImage);
CGContextRef context = CGBitmapContextCreate(NULL,
imageRect.size.width,
imageRect.size.height ,
CGImageGetBitsPerComponent(self.CGImage),
0,
colorSpace,
(CGBitmapInfo)CGImageGetAlphaInfo(self.CGImage)
);
CGContextSaveGState(context);
CGContextTranslateCTM(context, 0.0, self.size.height *scaleFactor);
CGContextScaleCTM(context, 1.0 , -1.0);
CGAffineTransform transform = CGAffineTransformMakeScale(scaleFactor, scaleFactor);
[path applyTransform:transform];
if(invertPath){
UIBezierPath *rectPath = [UIBezierPath bezierPathWithRect:imageRect];
CGContextAddPath(context, rectPath.CGPath);
CGContextAddPath(context, path.CGPath);
CGContextEOClip(context);
} else {
CGContextAddPath(context, path.CGPath);
CGContextClip(context);
}
CGContextScaleCTM(context, 1.0, -1.0);
CGContextTranslateCTM(context, 0.0, -self.size.height * scaleFactor);
CGContextDrawImage(context, imageRect, [self CGImage]);
CGImageRef imageRef = CGBitmapContextCreateImage(context);
return [UIImage imageWithCGImage:imageRef scale:scaleFactor orientation:0];
}
#end
The following image was cropped twice with the same path. once inverted, once not inverted. than I merged them again.
NSString *imageName = #"IMG_2345.jpg";
UIImage *image = [UIImage imageNamed:imageName];
UIImage *image2 = [UIImage imageNamed:imageName];
CGSize size = CGSizeMake(320, 320 * image.size.height / image.size.width);
image = [image resizedImage:size interpolationQuality:kCGInterpolationHigh];
image2 = [image2 resizedImage:size interpolationQuality:kCGInterpolationHigh];
image2 = [image2 grayscaledImage];
image = [image imageCroppedWithPath:[self circlePathWithSize: circleSize] invertPath: NO];
image2 = [image2 imageCroppedWithPath:[self circlePathWithSize: circleSize] invertPath: YES];
It is on Github

Related

how to Call static Method which Accept 3 Parameters

How can I call this function?
I am trying to call this function from -viewDidLoad.
I tried [circularImageWithImage(imageView.image, myclor, 0.2)];
static UIImage *circularImageWithImage(UIImage *inputImage,
UIColor *borderColor,
CGFloat borderWidth)
{
CGRect rect = (CGRect){ .origin=CGPointZero, .size=inputImage.size };
UIGraphicsBeginImageContextWithOptions(rect.size, NO, inputImage.scale); {
// Fill the entire circle with the border color.
[borderColor setFill];
[[UIBezierPath bezierPathWithOvalInRect:rect] fill];
// Clip to the interior of the circle (inside the border).
CGRect interiorBox = CGRectInset(rect, borderWidth, borderWidth);
UIBezierPath *interior = [UIBezierPath bezierPathWithOvalInRect:interiorBox];
[interior addClip];
[inputImage drawInRect:rect];
}
UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return outputImage;
}
You can try with this code.
UIImage *image = [UIImage imageNamed:#"yourImage.png"];
UIImageView *imageView = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 100, 100)];//set your frame
//imageView.center = self.view.center;
UIImage *modifiedImage = circularImageWithImage(image, [UIColor redColor], 1.2);//border width >= 1.0 is better. Otherwise you may not see this
imageView.image = modifiedImage;
[self.view addSubview:imageView];
UIImage *sample = circularImageWithImage(imageView.image, myclor, 0.2);

iOS Custom UIImagePickerController Camera Crop to circle,square,triangular shape?

How can i add circular, triangle, square image overlay to UIImagepickercontroller as per above pic
and when user presses camera button then only image inside circular or triangular or square must be captured.
I have used below code but its not giving proper result. kindly see below pic.
Which is totally reverse what i want to achieve.
-(void)openCamera {
self.pickerController = [[UIImagePickerController alloc] init];
self.pickerController.delegate = self;
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])
{
[self.pickerController setSourceType:UIImagePickerControllerSourceTypeCamera];
} else {
UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:#"Tatoo App" message:#"No Camera Available" delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[alertView show];
}
self.pickerController.allowsEditing = NO;
self.pickerController.showsCameraControls = NO;
// creating overlayView
self.overlayView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.pickerController.view.frame.size.width-20, self.pickerController.view.frame.size.height)];
// letting png transparency be
self.overlayView .backgroundColor = [UIColor colorWithRed:0/255 green:0/255 blue:0/255 alpha:0.5];
[self.overlayView .layer setOpaque:NO];
self.overlayView .opaque = NO;
/*
UIView *circleView = [[UIView alloc]initWithFrame:CGRectMake(self.pickerController.view.frame.size.width/4, self.pickerController.view.frame.size.width/4, self.pickerController.view.frame.size.width/2, self.pickerController.view.frame.size.height/4)];
circleView.backgroundColor = [UIColor greenColor];
circleView.layer.cornerRadius = circleView.frame.size.width / 2;
circleView.clipsToBounds = YES;
[self.overlayView addSubview:circleView];
[self.overlayView bringSubviewToFront:circleView];
*/
CAShapeLayer *maskLayer = [CAShapeLayer layer];
self.overlayView.layer.mask = maskLayer;
self.maskLayer = maskLayer;
// create shape layer for circle we'll draw on top of image (the boundary of the circle)
CAShapeLayer *circleLayer = [CAShapeLayer layer];
circleLayer.lineWidth = 3.0;
circleLayer.fillColor = [[UIColor clearColor] CGColor];
circleLayer.strokeColor = [[UIColor blackColor] CGColor];
[self.overlayView.layer addSublayer:circleLayer];
self.circleLayer = circleLayer;
// create circle path
[self updateCirclePathAtLocation:CGPointMake(self.view.bounds.size.width / 2.0, self.view.bounds.size.height / 2.0) radius:self.view.bounds.size.width * 0.30];
CGFloat scale = [[self.overlayView.window screen] scale];
CGFloat radius = self.circleRadius * scale;
CGPoint center = CGPointMake(self.circleCenter.x * scale, self.circleCenter.y * scale);
CGRect frame = CGRectMake(center.x - radius,
center.y - radius,
radius * 2.0,
radius * 2.0);
// temporarily remove the circleLayer
// CALayer *circleLayer = self.circleLayer;
// [self.circleLayer removeFromSuperlayer];
// render the clipped image
UIGraphicsBeginImageContextWithOptions(self.imageOverlay.frame.size, NO, 0.0);
CGContextRef context = UIGraphicsGetCurrentContext();
if ([self.overlayView respondsToSelector:#selector(drawViewHierarchyInRect:afterScreenUpdates:)])
{
// if iOS 7, just draw it
[self.overlayView drawViewHierarchyInRect:self.overlayView.bounds afterScreenUpdates:YES];
}
else
{
// if pre iOS 7, manually clip it
CGContextAddArc(context, self.circleCenter.x, self.circleCenter.y, self.circleRadius, 0, M_PI * 2.0, YES);
CGContextClip(context);
[self.overlayView.layer renderInContext:context];
}
// capture the image and close the context
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// add the circleLayer back
[self.overlayView.layer addSublayer:circleLayer];
// crop the image
CGImageRef imageRef = CGImageCreateWithImageInRect([image CGImage], frame);
UIImage *croppedImage = [UIImage imageWithCGImage:imageRef];
self.takePicture = [UIButton buttonWithType:UIButtonTypeRoundedRect];
self.takePicture.frame = CGRectMake(80.0, self.pickerController.view.frame.size.height-100, 150.0, 30.0);
self.takePicture.tag = 0;
[ self.takePicture setTitle:#"Take" forState:UIControlStateNormal];
[ self.takePicture addTarget:self action:#selector(takeSnapShot:) forControlEvents:UIControlEventTouchUpInside];
[self.overlayView addSubview: self.takePicture];
self.pickerController.cameraOverlayView = self.overlayView;
[self presentViewController:self.pickerController animated:YES completion:nil];
}

How to create circular CGRect

I am using this code to create the rectangle in my app. But i want to make it rounded. How can i do that.
- (void)setCropRect:(CGRect)cropRect
{
if(!CGRectEqualToRect(_cropRect,cropRect)){
_cropRect = CGRectOffset(cropRect, self.frame.origin.x, self.frame.origin.y);
UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, 0.f);
CGContextRef context = UIGraphicsGetCurrentContext();
[[UIColor blackColor] setFill];
UIRectFill(self.bounds);
CGContextSetStrokeColorWithColor(context, [[UIColor whiteColor] colorWithAlphaComponent:0.5].CGColor);
CGContextStrokeRect(context, cropRect);
[[UIColor clearColor] setFill];
UIRectFill(CGRectInset(cropRect, 1, 1));
self.imageView.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
}
I am using this code to crop the image in rectangular shape:
- (CGImageRef)newTransformedImage:(CGAffineTransform)transform
sourceImage:(CGImageRef)sourceImage
sourceSize:(CGSize)sourceSize
sourceOrientation:(UIImageOrientation)sourceOrientation
outputWidth:(CGFloat)outputWidth
cropRect:(CGRect)cropRect
imageViewSize:(CGSize)imageViewSize
{
CGImageRef source = sourceImage;
CGAffineTransform orientationTransform;
[self transform:&orientationTransform andSize:&imageViewSize forOrientation:sourceOrientation];
CGFloat aspect = cropRect.size.height/cropRect.size.width;
CGSize outputSize = CGSizeMake(outputWidth, outputWidth*aspect);
CGContextRef context = CGBitmapContextCreate(NULL,
outputSize.width,
outputSize.height,
CGImageGetBitsPerComponent(source),
0,
CGImageGetColorSpace(source),
CGImageGetBitmapInfo(source));
CGContextSetFillColorWithColor(context, [[UIColor clearColor] CGColor]);
CGContextFillRect(context, CGRectMake(0, 0, outputSize.width, outputSize.height));
CGAffineTransform uiCoords = CGAffineTransformMakeScale(outputSize.width/cropRect.size.width,
outputSize.height/cropRect.size.height);
uiCoords = CGAffineTransformTranslate(uiCoords, cropRect.size.width/2.0, cropRect.size.height/2.0);
uiCoords = CGAffineTransformScale(uiCoords, 1.0, -1.0);
CGContextConcatCTM(context, uiCoords);
CGContextConcatCTM(context, transform);
CGContextScaleCTM(context, 1.0, -1.0);
CGContextConcatCTM(context, orientationTransform);
CGContextDrawImage(context, CGRectMake(-imageViewSize.width/2.0,
-imageViewSize.height/2.0,
imageViewSize.width,
imageViewSize.height)
,source);
CGImageRef resultRef = CGBitmapContextCreateImage(context);
CGContextRelease(context);
return resultRef;
}
Is i can use the brazier curve to crop the image also.
You cannot create a “circular CGRect”, or a rounded CGRect (which is what you appear to actually want). A CGRect has an origin and a width and a height. It doesn't store any corner radiuses (radii).
Instead of using UIRectFill, you need to create a UIBezierPath of a rounded rect and then fill the path. Example:
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:10];
[[UIColor blackColor] setFill];
[path fill];
You can also stroke a path if you need to. Example:
path = [UIBezierPath bezierPathWithRoundedRect:cropRect cornerRadius:10];
path.lineWidth = 10;
[[[UIColor whiteColor] colorWithAlphaComponent:0.5] setStroke];
[path stroke];

Generating a UIView with an image

I have the following method that for some reason does NOT display the image:
- (void)drawRect:(CGRect)rect
{
float cornerRadius = self.bounds.size.width/RADIUS_RATIO;
UIBezierPath *roundedRect = [UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:cornerRadius];
[roundedRect addClip];
[[UIColor whiteColor] setFill];
UIRectFill(self.bounds);
[[UIColor blackColor] setStroke];
[roundedRect stroke];
CGRect imageRect = CGRectInset(self.bounds,
self.bounds.size.width * 0.5,
self.bounds.size.height * 0.5);
if (self.faceUp)
{
UIImage *cardFace = [UIImage imageNamed:[NSString stringWithFormat:
#"%#%#.png",[self rankAsStrings],self.suit]];
if (cardFace)
{
NSLog(#"%#%#.png",[self rankAsStrings],self.suit);
[cardFace drawInRect:imageRect];
} else {
NSLog(#"No Image Found: %#%#.png",[self rankAsStrings],self.suit);
}
} else {
[[UIImage imageNamed:#"Back.png"] drawInRect:imageRect];
}
}
Can someone shed some light on this?
P.S. The images are present and I do get the "NSLog(#"%#%#.png",[self rankAsStrings],self.suit);" message in the console.
TIA
I think your imageRect has 0.0 width and 0.0 height. Check the docs for CGRectInset method - it reduces original rect by 2*dx and 2*dy.
I would have done it like this :
myView.backgroundColor = [UIColor colorWithPatternImage: [UIImage imageNamed: #"MyProfilePic.png"]];

How to get rotated image of imageview in uiview?

I created RotatedView subclass of UIView and added UIImageView as subview of RotatedView and also draw a image on RotatedView using drawRect: method same as image of imageView. I applied pinch and rotate gestures on imageView. When i pinch the imageView drawing image is also changed. But when i rotate the imageView, the drawing image is not changed. I used following code::
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
self.backgroundColor = [UIColor redColor];
imageView = [[UIImageView alloc] initWithFrame:CGRectMake(80, 150, 100, 150)];
imageView.image = [UIImage imageNamed:#"Images_6.jpg"];
imageView.userInteractionEnabled = YES;
[self addSubview:imageView];
UIRotationGestureRecognizer *rotationGesture = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:#selector(rotationMethod:)];
rotationGesture.delegate = self;
[imageView addGestureRecognizer:rotationGesture];
}
return self;
}
- (void)drawRect:(CGRect)rect
{
// Drawing code
CGContextRef context =UIGraphicsGetCurrentContext();
CGRect rectFrame = CGRectMake(0, 0, imageView.frame.size.width, imageView.frame.size.height);
CGContextSetStrokeColorWithColor(context, [UIColor blueColor].CGColor);
CGContextSetLineWidth(context, 10.0);
CGContextBeginPath(context);
CGContextMoveToPoint(context, 0, 0);
CGContextAddLineToPoint(context, 90, 0);
CGContextAddLineToPoint(context, 90, 90);
CGContextAddLineToPoint(context, 0, 90);
CGContextAddLineToPoint(context, 0, 0);
CGContextClip(context);
CGContextStrokePath(context);
CGContextDrawImage(context,rectFrame, imageView.image.CGImage);
}
-(void)rotationMethod:(UIRotationGestureRecognizer *)gestureRecognizer{
NSLog(#"rotationMethod");
if ([gestureRecognizer state]==UIGestureRecognizerStateBegan || [gestureRecognizer state]==UIGestureRecognizerStateChanged) {
CGAffineTransform transform = CGAffineTransformRotate(gestureRecognizer.view.transform, gestureRecognizer.rotation);
gestureRecognizer.view.transform = transform;
[gestureRecognizer setRotation:0];
}
[self setNeedsDisplay];
}
How do i get rotate image in UIView when the imageView is rotated?
**
Edited:
**
I got solution using first method. Now i am using second method. I think this is simple and best but I am not sure which one is best. In second method, image is rotated but not at center point. I am struggle to solve this problem. Please help me.
Modifying methods are:
- (void)drawRect:(CGRect)rect
{
NSLog(#"drawRect");
// Drawing code
CGContextRef context =UIGraphicsGetCurrentContext();
CGContextSetStrokeColorWithColor(context, [UIColor blueColor].CGColor);
CGContextSetLineWidth(context, 10.0);
CGContextBeginPath(context);
CGContextMoveToPoint(context, imageRect.origin.x, imageRect.origin.y);
CGContextAddLineToPoint(context, imageRect.size.width, imageRect.origin.y);
CGContextAddLineToPoint(context, imageRect.size.width, imageRect.size.height);
CGContextAddLineToPoint(context, imageRect.origin.x, imageRect.size.height);
CGContextAddLineToPoint(context, imageRect.origin.x, imageRect.origin.y);
CGContextClip(context);
CGContextStrokePath(context);
CGContextDrawImage(context, imageRect, [self rotateImage:imageView.image].CGImage);
}
-(void)rotationMethod:(UIRotationGestureRecognizer *)gestureRecognizer{
NSLog(#"rotationMethod");
if ([gestureRecognizer state]==UIGestureRecognizerStateBegan || [gestureRecognizer state]==UIGestureRecognizerStateChanged) {
CGAffineTransform transform = CGAffineTransformRotate(gestureRecognizer.view.transform, gestureRecognizer.rotation);
gestureRecognizer.view.transform = transform;
lastRotation = gestureRecognizer.rotation;
[gestureRecognizer setRotation:0];
}
[self setNeedsDisplay];
}
- (UIImage *)rotateImage:(UIImage *) img
{
NSLog(#"rotateImage");
CGAffineTransform transform = imageView.transform;
transform = CGAffineTransformTranslate(transform, img.size.width, img.size.height);
transform = CGAffineTransformRotate(transform, lastRotation);
transform = CGAffineTransformScale(transform, -1, -1);
CGContextRef ctx = CGBitmapContextCreate(NULL, img.size.width, img.size.height,
CGImageGetBitsPerComponent(img.CGImage), 0,
CGImageGetColorSpace(img.CGImage),
CGImageGetBitmapInfo(img.CGImage));
CGContextConcatCTM(ctx, transform);
CGContextDrawImage(ctx, CGRectMake(20,20,img.size.width,img.size.height), img.CGImage);
CGImageRef cgimg = CGBitmapContextCreateImage(ctx);
UIImage *newImg = [UIImage imageWithCGImage:cgimg];
CGContextRelease(ctx);
CGImageRelease(cgimg);
return newImg;
}
You need to use CGContextScaleCTM and CGContextRotateCTM (and possibly to appropriately transform your CGContextRef to match your UIImageView's transform.
Take a look at the Quartz 2D Programming Guide
Ok. Finally i got it using ANImageBitmapRep. I declared lastRotation, angle,rotateMe in RotatedView.h class.
-(void)rotationMethod:(UIRotationGestureRecognizer *)gestureRecognizer{
if ([gestureRecognizer state]==UIGestureRecognizerStateBegan) {
if (!rotateMe) {
rotateMe = [[ANImageBitmapRep alloc] initWithImage:displayImageView.image];
}else{
rotateMe =[ANImageBitmapRep imageBitmapRepWithImage:displayImageView.image];
}
}
CGFloat rotation = 0.0 - (lastRotation - [gestureRecognizer rotation]);
CGAffineTransform currentTransform = [gestureRecognizer view].transform;
CGAffineTransform newTransform = CGAffineTransformRotate(currentTransform,rotation);
[[gestureRecognizer view] setTransform:newTransform];
lastRotation = [gestureRecognizer rotation];
angle =lastRotation * (180 / M_PI);
[self setNeedsDisplay];
}
- (void)drawRect:(CGRect)rect
{
CGRect imageRect = CGRectMake(0, 0, 90, 90);
// Drawing code
CGContextRef context =UIGraphicsGetCurrentContext();
CGContextSetStrokeColorWithColor(context, [UIColor blueColor].CGColor);
CGContextSetLineWidth(context, 10.0);
CGContextBeginPath(context);
CGContextMoveToPoint(context, imageRect.origin.x, imageRect.origin.y);
CGContextAddLineToPoint(context, imageRect.size.width, imageRect.origin.y);
CGContextAddLineToPoint(context, imageRect.size.width, imageRect.size.height);
CGContextAddLineToPoint(context, imageRect.origin.x, imageRect.size.height);
CGContextAddLineToPoint(context, imageRect.origin.x, imageRect.origin.y);
CGContextClip(context);
CGContextStrokePath(context);
UIImage *rotatedImage1=[UIImage imageWithCGImage:[rotateMe imageByRotating:angle]];
CGContextDrawImage(context, imageRect, rotatedImage1.CGImage);
}
I find this solution. If anyone find best solution, give me suggestions according this problem.

Resources