制作 UIImage 的方形裁剪导致图像拉伸
Posted
技术标签:
【中文标题】制作 UIImage 的方形裁剪导致图像拉伸【英文标题】:Making square crop of UIImage causing image to stretch 【发布时间】:2014-05-02 23:27:55 【问题描述】:当尝试对 UIImage 进行中心裁剪时,我得到以下结果(左侧是640*1136
处的原始图像,右侧是在320*320
处适合正方形UIImageView
的裁剪图像):
转为:
我对比率元素进行了相当多的修改,以便它可以正确检测要修剪的数量:使用图像的较短边,基于short_side/width_of_desired_rect
构建比率,但它似乎不起作用在这种情况下。感谢您的帮助!
- (UIImage *)squareImageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize
double ratio;
double delta;
CGPoint offset;
//make a new square size, that is the resized imaged width
CGSize sz = CGSizeMake(newSize.width, newSize.width);
//figure out if the picture is landscape or portrait, then
//calculate scale factor and offset
if (image.size.width > image.size.height)
ratio = newSize.width / image.size.width;
delta = (ratio*image.size.width - ratio*image.size.height);
offset = CGPointMake(delta/2, 0);
else
ratio = newSize.width / image.size.height;
delta = (ratio*image.size.height - ratio*image.size.width);
offset = CGPointMake(0, delta/2);
//make the final clipping rect based on the calculated values
CGRect clipRect = CGRectMake(-offset.x, -offset.y,
(ratio * image.size.width) + delta,
(ratio * image.size.height) + delta);
//for retina consideration
if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)])
UIGraphicsBeginImageContextWithOptions(sz, YES, 0.0);
else
UIGraphicsBeginImageContext(sz);
UIRectClip(clipRect);
[image drawInRect:clipRect];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
【问题讨论】:
仅供参考 - ios 4.0 中添加了UIScreen
的 scale
属性。没有必要再检查它了。
你没有裁剪。您正在将整个图像重新绘制到一个较小的区域中。搜索“ios裁剪图片”,你会找到很多解决问题的方法。
谢谢@rmaddy - 我想我正在裁剪和重绘图像(压扁的图像有 8 个垂直平方数,而原始图像超过 11 个)。
你不想画到clipRect
。您希望以原始纵横比绘制图像,以便仅在 clipRect
中呈现您想要保留的部分。
【参考方案1】:
试试这个:
- (UIImage *)squareImageFromImage:(UIImage *)image scaledToSize:(CGFloat)newSize
CGAffineTransform scaleTransform;
CGPoint origin;
if (image.size.width > image.size.height)
CGFloat scaleRatio = newSize / image.size.height;
scaleTransform = CGAffineTransformMakeScale(scaleRatio, scaleRatio);
origin = CGPointMake(-(image.size.width - image.size.height) / 2.0f, 0);
else
CGFloat scaleRatio = newSize / image.size.width;
scaleTransform = CGAffineTransformMakeScale(scaleRatio, scaleRatio);
origin = CGPointMake(0, -(image.size.height - image.size.width) / 2.0f);
CGSize size = CGSizeMake(newSize, newSize);
if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)])
UIGraphicsBeginImageContextWithOptions(size, YES, 0);
else
UIGraphicsBeginImageContext(size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextConcatCTM(context, scaleTransform);
[image drawAtPoint:origin];
image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
【讨论】:
感谢您回答@fumoboy007 - 不幸的是它没有工作:/ 图像炸得很大并且没有正确裁剪。我还删除了BOOL isLandscape
,因为它没有在其余代码中使用。
嗯……这很奇怪。我可以看一些截图吗?
啊忘了缩放...等一下。
这很好用,无论是前置摄像头还是后置摄像头。谢谢!我只是添加了一些更改,因为 newSize
是 CGSize
而不是 CGFloat
。
不客气。 =) 对于信箱,是的,几乎可以翻转缩放和裁剪逻辑,并绘制一个黑色矩形(或任何颜色)。【参考方案2】:
使用此代码调整图像大小
// Returns image resized to the desired CGSize
- (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize
UIGraphicsBeginImageContext(newSize);
[image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
编辑:你基本上也在这里重绘。如果您一遍又一遍地重复使用相同的图像,最好调用一次并将结果保存为文件。在以后的调用中加载它而不是原始的。
编辑 2:好的,您要做的是在将图像拟合成正方形的同时保持纵横比。上面的代码基本上通过调整图像大小将图像放入正方形,但它不保持纵横比。保持纵横比的一种方法是找到缩小图像两个维度中较大者的因子,然后将另一个维度缩小相同的因子。如果您遇到问题,请告诉我。
【讨论】:
感谢 user2891327。虽然这在使用后置摄像头时效果很好,但在使用前置摄像头时,图像仍然会被挤压。奇怪的是,另一组代码似乎也是这种情况 我添加了一些截图以防万一。这是相机拍摄的(注意,它的纵横比为 9:16)而不调整为正方形:i.imgur.com/88SaGO6.png,这是在调整为正方形之后:i.imgur.com/fL8TMWr.png【参考方案3】:swift3版本fumoboy007的代码..
func squareImage(img: UIImage, scaledToSize newSize: CGFloat) -> UIImage
var scaleTransform: CGAffineTransform
var origin: CGPoint
var image = img
if image.size.width > image.size.height
let scaleRatio: CGFloat = newSize / image.size.height
scaleTransform = CGAffineTransform(scaleX: scaleRatio, y: scaleRatio)
origin = CGPoint(x: -(image.size.width - image.size.height) / 2.0, y: 0)
else
let scaleRatio: CGFloat = newSize / image.size.width
scaleTransform = CGAffineTransform(scaleX: scaleRatio, y: scaleRatio)
origin = CGPoint(x: 0, y: -(image.size.height - image.size.width) / 2.0)
let size = CGSize(width: newSize, height: newSize)
if image.size.width > image.size.height
UIGraphicsBeginImageContextWithOptions(size, true, 0)
else
UIGraphicsBeginImageContext(size)
let context: CGContext? = UIGraphicsGetCurrentContext()
context?.concatenate(scaleTransform)
image.draw(at: origin)
image = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
return image
【讨论】:
以上是关于制作 UIImage 的方形裁剪导致图像拉伸的主要内容,如果未能解决你的问题,请参考以下文章