I need to crop UIImage which is loaded in UIScrollview with some rect of Another UIView which is also in UIScrollView
Following is View Hierarchy
--> View
--> UIScrollView
--> viewBase (UIView)
--> UIImageView -> (Zoomed & rotated )
--> UIView (Target View)(Movable User can move anywhere in scrollview to crop rect)
My Image is Rotated & Zoomed I need to get exact part of image in TargetView
I am drawing UIImage with rotation on context following is code
CGFloat angleCroppedImageRetreacted = atan2f(self.imgVPhoto.transform.b, self.imgVPhoto.transform.a);
angleCroppedImageRetreacted = angleCroppedImageRetreacted * (180 / M_PI);
UIView *rotatedViewBox = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, self.imgVPhoto.image.size.width, self.imgVPhoto.image.size.height)];
rotatedViewBox.transform = CGAffineTransformMakeRotation(-angleCroppedImageRetreacted);
CGSize rotatedSize = rotatedViewBox.frame.size;
UIGraphicsBeginImageContext(rotatedSize);
CGContextRef bitmap = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(bitmap, rotatedSize.width / 2.0f, rotatedSize.height / 2.0f);
CGContextRotateCTM(bitmap, -angleCroppedImageRetreacted);
CGContextScaleCTM(bitmap, 1.0f, -1.0f);
CGContextDrawImage(bitmap, CGRectMake(-self.imgVPhoto.image.size.width / 2.0f,
-self.imgVPhoto.image.size.height / 2.0f,
self.imgVPhoto.image.size.width,
self.imgVPhoto.image.size.height),
self.imgVPhoto.image.CGImage);
UIImage *resultImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
And it works fine . I am getting Rotated UIImage same as i can see in Simulator
For converting Point of Target View to UIImage I use following code which is NOT WORKING
CGPoint imageViewPoint = [self.viewBase convertPoint:self.targetImageview.center toView:self.imgVPhoto];
float percentX = imageViewPoint.x / self.imgVPhoto.frame.size.width;
float percentY = imageViewPoint.y / self.imgVPhoto.frame.size.height;
CGPoint imagePoint = CGPointMake(resultImage.size.width * percentX, resultImage.size.height * percentY);
rect.origin = imagePoint;
//rect.origin.x *= (self.imgVPhoto.image.size.width / self.imgVPhoto.frame.size.width);
//rect.origin.y *= (self.imgVPhoto.image.size.height / self.imgVPhoto.frame.size.height);
imageRef = CGImageCreateWithImageInRect([resultImage CGImage], rect);
img = [UIImage imageWithCGImage:imageRef scale:viewImage.scale orientation:viewImage.imageOrientation];
I think issue is we can't use Rect after Transform Apply
Please Help me to crop UIImage which is zoomed and rotated from rect on same Hierarchy
If you need more info pls ask
I am answering my own question .
Thanks to Matic for giving a idea
I changed a logic
I have achieved same functionality what i looking for
CGPoint locationInImageView = [self.viewBase convertPoint:self.targetImageview.center toView:self.view]; // received from touch
locationInImageView = [self.view convertPoint:locationInImageView toView:self.imgVPhoto];
// I GOT LOCATION IN UIIMAGEVIEW OF TOUCH POINT
UIGraphicsBeginImageContextWithOptions(self.view.frame.size, NO, 0);
[self.imgVPhoto.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *img1 = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// I GOT UIIMAGE FROM CURRENT CONTEXT
CGFloat width = self.targetImageview.frame.size.width * self.zoomScale ;
CGFloat height = self.targetImageview.frame.size.height * self.zoomScale ;
//2 IS SCALE FACTOR
CGFloat xPos = (locationInImageView.x * 2) - width / 2;
CGFloat yPos = (locationInImageView.y * 2) - height / 2;
CGRect rect1 = CGRectMake(xPos, yPos, width, height);
CGImageRef imageRef = CGImageCreateWithImageInRect([img1 CGImage], rect1);
// YAHHH YOU HAVE EXACT IMAGE
UIImage *img = [UIImage imageWithCGImage:imageRef scale:img1.scale orientation:img1.imageOrientation];
Related
I am working in iOS application where I want to select card rectangle from captured image using camera. So if anybody knows any solution please let me know. Thank you.
My code is below:
/**
* Cut out a image to a new image with the rect
*
* #param image UIImage image origin image
* #param rect CGRect rect the rect area you want
*
* #return UIImage
*/
+ (UIImage *)ct_imageFromImage:(UIImage *)image inRect:(CGRect)rect{
CGFloat scale = [UIScreen mainScreen].scale;
CGFloat x= rect.origin.x*scale,y=rect.origin.y *scale,w=rect.size.width*scale,h=rect.size.height*scale;
CGRect dianRect = CGRectMake(x, y, w, h);
//cut the image with the rect area
CGImageRef sourceImageRef = [image CGImage];
CGImageRef newImageRef = CGImageCreateWithImageInRect(sourceImageRef, dianRect);
UIImage *newImage = [UIImage imageWithCGImage:newImageRef scale:[UIScreen mainScreen].scale orientation:UIImageOrientationUp];
return newImage;
}
I want to rotate image (arrow) in circular path in coreGraphics like this image. in circular path.
input image:
output after rotation:
This will return rotated image
- (UIImage *)rotateImage:(UIImage *)image onDegrees:(float)degrees
{
CGFloat rads = M_PI * degrees / 180;
float newSide = MAX([image size].width, [image size].height);
CGSize size = CGSizeMake(image.size.width, newSide);
UIGraphicsBeginImageContext(size);
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(ctx, image.size.width, newSide/2);
CGContextRotateCTM(ctx, rads);
CGRect r = CGRectMake(0,-[image size].height/2,image.size.width,image. size.height);
[image drawInRect:r];
UIImage *i = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return i;
}
UIImage *arrowRotated180 = [self rotateImage:[UIImage imageNamed:#"arrowImage"] onDegrees:180];
UIImage *arrowRotated90 = [self rotateImage:[UIImage imageNamed:#"arrowImage"] onDegrees:90];
Put three images and rotate 2 & 3 image as follow.
imageview2.transform = CGAffineTransformMakeRotation(M_PI/4);
imageview3.transform = CGAffineTransformMakeRotation(M_PI/2);
Hope this will help you...
try UIcollectionview it worked my case .
I have been looking around to find a way to crop an image (imageView) inside ScrollView. What i need to achieve here is user pinch to zoom an image, (which is working great) and then able to crop ONLY the part of the image that is shown on the screen after the zoom. so in another words, if i have a series of number 1 to 10, user zoom it to see only number 4 and 5 and when user taps crop, i ONLY need image of 4 and 5 that was visible at the time of crop. I'm using this code...
- (UIImage *)croppedImageWithImage:(UIImage *)image zoom:(CGFloat)zoom
{
CGFloat zoomReciprocal = 1.0f / zoom;
CGRect croppedRect = CGRectMake(self.scrollView.contentOffset.x*zoom,
self.scrollView.contentOffset.y*zoom,
image.size.width * zoomReciprocal,
image.size.height * zoomReciprocal);
CGImageRef croppedImageRef = CGImageCreateWithImageInRect([image CGImage], croppedRect);
UIImage* croppedImage = [[UIImage alloc] initWithCGImage:croppedImageRef scale:[image scale] orientation:[image imageOrientation]];
CGImageRelease(croppedImageRef);
return croppedImage;
}
This method crops the image however, the x and y values are incorrect... What do i have to do to get the correct x and y of my crop area?
FYI.. the image i'm trying to crop is 2200 * 3200, not sure if that would make any difference?
I solved it!! here is the updated method for others who might come across this issue.
- (UIImage *)croppedImageWithImage:(UIImage *)image zoom:(CGFloat)zoom {
CGFloat zoomReciprocal = 1.0f / zoom;
CGFloat xOffset = image.size.width / self.scrollViewBackground.contentSize.width;
CGFloat yOffset = image.size.height / self.scrollViewBackground.contentSize.height;
CGRect croppedRect = CGRectMake(self.scrollViewBackground.contentOffset.x * xOffset,
self.scrollViewBackground.contentOffset.y * yOffset,
image.size.width * zoomReciprocal,
image.size.height * zoomReciprocal);
CGImageRef croppedImageRef = CGImageCreateWithImageInRect([image CGImage], croppedRect);
UIImage *croppedImage = [[UIImage alloc] initWithCGImage:croppedImageRef scale:[image scale] orientation:[image imageOrientation]];
CGImageRelease(croppedImageRef);
return croppedImage;
}
I want to rotate a UIImageView with the press of a button. I am using this code:
#import "UIImage-Extensions.h"
UIImage *rotatedImage = [SplashItGroupPicker.image imageRotatedByDegrees:360/arrayCount];
SplashItGroupPicker.image = rotatedImage;
and in "UIImage-Extensions.h" i have:
#interface UIImage (CS_Extensions)
- (UIImage *)imageRotatedByRadians:(CGFloat)radians;
- (UIImage *)imageRotatedByDegrees:(CGFloat)degrees;
and in the .m:
- (UIImage *)imageRotatedByRadians:(CGFloat)radians
{
return [self imageRotatedByDegrees:RadiansToDegrees(radians)];
}
- (UIImage *)imageRotatedByDegrees:(CGFloat)degrees
{
// calculate the size of the rotated view's containing box for our drawing space
UIView *rotatedViewBox = [[UIView alloc] initWithFrame:CGRectMake(0,0,self.size.width, self.size.height)];
CGAffineTransform t = CGAffineTransformMakeRotation(DegreesToRadians(degrees));
rotatedViewBox.transform = t;
CGSize rotatedSize = rotatedViewBox.frame.size;
// Create the bitmap context
UIGraphicsBeginImageContext(rotatedSize);
CGContextRef bitmap = UIGraphicsGetCurrentContext();
// Move the origin to the middle of the image so we will rotate and scale around the center.
CGContextTranslateCTM(bitmap, rotatedSize.width/2, rotatedSize.height/2);
// // Rotate the image context
CGContextRotateCTM(bitmap, DegreesToRadians(degrees));
// Now, draw the rotated/scaled image into the context
CGContextScaleCTM(bitmap, 1.0, -1.0);
CGContextDrawImage(bitmap, CGRectMake(-self.size.width / 2, -self.size.height / 2, self.size.width, self.size.height), [self CGImage]);
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
...the rotation works fine, but when the image is rotated, the image also gets smaller and I can't understand why. Any ideas?
Here's a guess, is this only happening on Retina screens? Whenever saving a UIImage from a graphics context, you need to make sure the scale is correct. This is how I have done it:
CGFloat scale = [[UIScreen mainScreen] scale];
CGSize size = CGSizeMake(rotatedViewBox.frame.size.width * scale, rotatedViewBox.frame.size.height * scale);
UIGraphicsBeginImageContext( size );
/* Do your image manipulations here */
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// overwrite the image with one that has the correct scale set
newImage = [UIImage imageWithCGImage:newImage.CGImage scale:scale orientation:newImage.imageOrientation];
Using Kekoa's snippet (thanks a ton), I was able to get a working rotateImage function that works on retina devices based on Apples rotateImage code:
- (UIImage *)imageRotatedByDegrees:(CGFloat)degrees {
CGFloat radians = DegreesToRadians(degrees);
UIView *rotatedViewBox = [[UIView alloc] initWithFrame:CGRectMake(0,0, self.size.width, self.size.height)];
CGAffineTransform t = CGAffineTransformMakeRotation(radians);
rotatedViewBox.transform = t;
CGSize rotatedSize = rotatedViewBox.frame.size;
UIGraphicsBeginImageContextWithOptions(rotatedSize, NO, [[UIScreen mainScreen] scale]);
CGContextRef bitmap = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(bitmap, rotatedSize.width / 2, rotatedSize.height / 2);
CGContextRotateCTM(bitmap, radians);
CGContextScaleCTM(bitmap, 1.0, -1.0);
CGContextDrawImage(bitmap, CGRectMake(-self.size.width / 2, -self.size.height / 2 , self.size.width, self.size.height), self.CGImage );
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
There is no need to UIGraphicsGetImageFromCurrentImageContext. its a way to get screenshot of desired portion of mainscreen. so the result image quality affected. the only way to get Rotated Image is...
first rotate your image view by(if you want to show rotated view)
[mainImgV setTransform:CGAffineTransformRotate(mainImgV.transform, M_PI)];
it will rotate your imageview.
now you will take this rotated image by these lines.(you can call these lines without rotate imgaeview also.)
CGImageRef cgRef = mainImgV.image.CGImage;
newImage = [[UIImage alloc] initWithCGImage:cgRef scale:1.0 orientation:UIImageOrientationDown];
there is no need to save or take screenshot or compromise bad quality image. just enjoy coding.
I'am doing an app something like this: You load a photo and you put images over it, like balloons, etc..
When I try to merge one of this over images with only resize it works fine. Like 10px more than it should be but no problem.
The problem comes when you rotate the image [UIImageView] it appears much bigger that the image its, I try allot of things and nothing. I leave the code. I hope someone could help.
Note: The image size its inside UIImageView, then multiplied it by the scale of the main image
- (UIImage *)mergeImage:(UIImageView *)mainImage withImageView:(UIImageView *)imageView {
UIImage *temp = imageView.image;
UIImage *tempMain = mainImage.image;
CGFloat mainScale = [self imageViewScaleFactor:mainImage];
CGFloat tempScale = 1/mainScale;
NSLog(#"%f", tempScale);
//Rotate UIIMAGE
UIGraphicsBeginImageContext(temp.size);
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGAffineTransform transform = CGAffineTransformIdentity;
transform = CGAffineTransformTranslate(transform, temp.size.width/2, temp.size.height/2);
CGFloat angle = atan2(imageView.transform.b, imageView.transform.a);
transform = CGAffineTransformRotate(transform, angle);
transform = CGAffineTransformScale(transform, 1.0, -1.0);
CGContextConcatCTM(ctx, transform);
// Draw the image into the context
CGContextDrawImage(ctx, CGRectMake(-temp.size.width/2, -temp.size.height/2, temp.size.width, temp.size.height), temp.CGImage);
// Get an image from the context
temp = [UIImage imageWithCGImage: CGBitmapContextCreateImage(ctx)];
NSLog(#"%f %f %f", mainScale, mainImage.frame.size.width, mainImage.frame.size.height);
UIGraphicsBeginImageContextWithOptions(tempMain.size, NO, 1.0f);
//Get imageView size & position
NSLog(#"%f %f %f %f", imageView.frame.origin.x, imageView.frame.origin.y, imageView.frame.size.width, imageView.frame.size.height);
CGFloat offsetX = 0;
CGFloat offsetY = -44;
if (tempMain.size.height > tempMain.size.width) {
offsetX = ((tempMain.size.width * mainScale) - 320)/2;
}else{
offsetY = ((tempMain.size.height * mainScale) - 416)/2;
offsetY -= 44;
}
CGFloat imageViewX = (imageView.frame.origin.x + offsetX) * tempScale;
CGFloat imageViewY = (imageView.frame.origin.y + offsetY) * tempScale;
CGFloat imageViewW = imageView.frame.size.width * tempScale;
CGFloat imageViewH = imageView.frame.size.height * tempScale;
CGRect tempRect = CGRectMake(imageViewX, imageViewY, imageViewW, imageViewH);
[tempMain drawAtPoint:CGPointZero];
[temp drawInRect:tempRect];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
Thanks
This is the solution that works for me
Merging a previosly rotated by gesture UIImageView with another one. WYS is not WYG
I just take a photo to the main screen and then crop it to the size of the photo, its faster, and clean. and the resolution it ok if the apps runs in retina in a normal device isn't too good. And you need to prepare that code to work in retina & non-retina