我想通过裁剪UIImageView中的图像来创建一个新的UIImage。例如,在上面的图片中,我想要一个绿色区域的新UIImage。我找到了代码来执行此操作,通常它看起来像这样(作为UIImage类别):
- (UIImage *)croppedImage:(CGRect)bounds {
CGImageRef imageRef = CGImageCreateWithImageInRect([self CGImage], bounds);
UIImage *croppedImage = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
return croppedImage;
}
具有完美的感觉。但是,我的UIImageView在contentMode'aspect fit'中。这似乎使CGImageCreateWithImageInRect的CGRect计算变得复杂,我无法找到正确的解决方案。
我想我需要像对图像一样对绿色矩形应用相同的变换?
另外:我在这里发现了另一个问题(How to know the image size after applying aspect fit for the image in an UIImageView),这似乎显示了一种蛮力的方式来获得规模,但我仍然不确定这是如何适应裁剪的情况。
有什么想法吗?
编辑:在我的情况下,我确实在UIImageView的叠加视图中绘制了如上所示的正方形。因此,当我意识到我正在裁剪UIImage(在UIImageView中)时,我需要以某种方式更改绿色CGRect,使其“匹配”应用“纵横比较”时完成的转换。例如,如果我将UIImageView保留在“左上角”模式,那么一切正常,因为底层UIImage和UIImageView之间存在1:1的映射。 “左上角”模式中的问题是整个图像并不总是显示,因为它可能比我的UIImageView大。
答案 0 :(得分:10)
基于我的other answer类似的问题,我已经为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。请注意,它仅适用于“纵横比”模式!我没有测试过它。所以,告诉我它是否有效!
答案 1 :(得分:4)
我知道答案已经存在,但我遇到了一些问题,所以我也不会发布我的解决方案。
问题是图像是通过纵横拟合来缩放的,但我们知道宽度和高度的比例因子。然后我们可以很容易地计算出正确的裁剪矩形:
-(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;
}
答案 2 :(得分:1)
我想你不明白你在做什么。你不能“裁剪”UIImageView - 只有UIImages。所以你的croppedImage方法应该是UIImage类,而不是UIImageView类。 传递给crop方法的bounds必须与图像大小有关,而不是与imageview边界有关。 与图像视图的contentMode无关 - 图像的裁剪将始终如一。首先从图像视图中获取图像。然后从中创建一个新的裁剪图像,最后为图像视图设置裁剪后的图像。这可以在一行代码中完成:
imageView.image = [imageView.image croppedImage:rect];
由于您的contentMode是“宽高比适合”,因此新图片将自动拉伸以适合视图框。您还可以尝试根据image.size更改视图框以避免像素化效果。
答案 3 :(得分:0)
我使用下面的方法。
-(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;
}