如何在“方面适合”模式下将UIImageView裁剪为新的UIImage?

在这里输入图像说明

我想通过在UIImageView中裁剪图像来创build一个新的UIImage。 例如在上面的图片中,我想要一个绿色区域的新UIImage。 我发现代码来做到这一点,通常它看起来像这样(作为一个UIImage类别):

- (UIImage *)croppedImage:(CGRect)bounds { CGImageRef imageRef = CGImageCreateWithImageInRect([self CGImage], bounds); UIImage *croppedImage = [UIImage imageWithCGImage:imageRef]; CGImageRelease(imageRef); return croppedImage; } 

理所当然 不过,我的UIImageView是在contentMode'方面适合'。 看起来像CGIctCreateWithImageInRect CGRect计算复杂,我一直无法找出正确的解决scheme。

我想我需要对图像应用相同的转换到绿色矩形?

另外:我在这里发现了另一个问题( 如何在UIImageView中对图像应用方面合适性之后知道图像的大小 ),这似乎显示了获取尺寸的蛮力方式,但是我仍然不确定如何适合种植情况。

有任何想法吗?

编辑 :在我的情况下,我实际上有一个正方形如上所示在UIImageView覆盖视图中绘制。 所以虽然我意识到我裁剪的UIImage(在UIImageView内),我需要以某种方式改变绿色的CGRect,以便“匹配”适应'方面适应'时完成的转换。 例如,如果我离开我的UIImageView在'左上angular'模式,那么一切工作正常,因为底层的UIImage和UIImageView之间有1:1的映射。 “左上angular”模式的问题是,整个图像并不总是显示,因为它可能比我的UIImageView更大。

根据我对其他类似问题的回答 ,我已经为UIImageView类别编写了这个方法:

 -(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); } 

你可以传入你的绿色矩形的框架(假设它是图像视图的子视图),并获得裁剪矩形UIImage。 请注意,它只适用于“方面适合”模式! 我还没有testing过。 所以,告诉我,如果它的工作!

我知道答案是,但我有一些问题得到正确的,所以我不会发布我的解决scheme。

问题是图像的缩放比例与方面匹配,但我们知道宽度和高度的比例因子。 然后我们可以很容易地计算出正确的裁剪矩形:

 -(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; } 

我想你不明白你在做什么。 你不能“裁剪”UIImageView – 只有UIImages。 所以你的croppedImage方法应该在UIImage类别而不是UIImageView类别。 您传递给裁剪方法的边界必须与图像大小相关,而不是imageview边界。 这与图像视图的内容模式无关 – 图像的裁剪将始终如一。 首先从图像视图中获取图像。 然后从中创build一个新的裁剪图像,最后设置图像视图的裁剪图像。 这可以在一行代码中完成:

 imageView.image = [imageView.image croppedImage:rect]; 

由于您的contentMode是“宽高比”,新图片将自动拉伸以适应视图框架。 你也可以尝试改变基于image.size的视图框架,以避免像素效应。

我使用下面的方法。

 -(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; }