I would like to create a new UIImage by cropping the image inside a UIImageVie
I know the answer has been but I had some problems getting above right so, I wont to post my solution too.
The problem is the image is scaled with a aspect fit, but we know the scale factor for both the width and the height. Then we can calculate the right cropping rectangle pretty easy:
-(UIImage*)crop:(CGRect)frame
{
// Find the scalefactors UIImageView's widht and height / UIImage width and height
CGFloat widthScale = self.bounds.size.width / self.image.size.width;
CGFloat heightScale = self.bounds.size.height / self.image.size.height;
// Calculate the right crop rectangle
frame.origin.x = frame.origin.x * (1 / widthScale);
frame.origin.y = frame.origin.y * (1 / heightScale);
frame.size.width = frame.size.width * (1 / widthScale);
frame.size.height = frame.size.height * (1 / heightScale);
// Create a new UIImage
CGImageRef imageRef = CGImageCreateWithImageInRect(self.image.CGImage, frame);
UIImage *croppedImage = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
return croppedImage;
}
I use the method below.
-(UIImage *)getNeedImageFrom:(UIImage*)image cropRect:(CGRect)rect
{
CGSize cropSize = rect.size;
CGFloat widthScale =
image.size.width/self.imageViewOriginal.bounds.size.width;
CGFloat heightScale =
image.size.height/self.imageViewOriginal.bounds.size.height;
cropSize = CGSizeMake(rect.size.width*widthScale,
rect.size.height*heightScale);
CGPoint pointCrop = CGPointMake(rect.origin.x*widthScale,
rect.origin.y*heightScale);
rect = CGRectMake(pointCrop.x, pointCrop.y, cropSize.width,
cropSize.height);
CGImageRef subImage = CGImageCreateWithImageInRect(image.CGImage, rect);
UIImage *croppedImage = [UIImage imageWithCGImage:subImage];
CGImageRelease(subImage);
return croppedImage;
}
Based on my other answer to a similar question I have written this method for a UIImageView category:
-(CGRect) cropRectForFrame:(CGRect)frame
{
NSAssert(self.contentMode == UIViewContentModeScaleAspectFit, @"content mode must be aspect fit");
CGFloat widthScale = self.bounds.size.width / self.image.size.width;
CGFloat heightScale = self.bounds.size.height / self.image.size.height;
float x, y, w, h, offset;
if (widthScale<heightScale) {
offset = (self.bounds.size.height - (self.image.size.height*widthScale))/2;
x = frame.origin.x / widthScale;
y = (frame.origin.y-offset) / widthScale;
w = frame.size.width / widthScale;
h = frame.size.height / widthScale;
} else {
offset = (self.bounds.size.width - (self.image.size.width*heightScale))/2;
x = (frame.origin.x-offset) / heightScale;
y = frame.origin.y / heightScale;
w = frame.size.width / heightScale;
h = frame.size.height / heightScale;
}
return CGRectMake(x, y, w, h);
}
You can pass in the frame of your green rect (assuming it is a subview of the image view) and get the crop rect back for cropping the UIImage. Note that it only works for 'aspect fit' mode! I haven't tested it though. So, tell me if it works!
I think you don't understand what you are doing. You can't "crop" a UIImageView - only UIImages. So your croppedImage method should be in a UIImage category and not a UIImageView category. The bounds rect you pass to the crop method must be in relation to the image size, not to the imageview bounds. It is irrelevant what the contentMode of the image view is - the cropping of the image will always work the same. First get the image from the image view. Then create a new cropped image from it and finally set the cropped image for the image view. This can be done in one line of code:
imageView.image = [imageView.image croppedImage:rect];
Since your contentMode is 'aspect fit' the new image will automatically stretch to fit in the view frame. You can also try to change the view frame based on the image.size to avoid pixelation effects.