【问题标题】:Making square crop of UIImage causing image to stretch制作 UIImage 的方形裁剪导致图像拉伸
【发布时间】: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 中添加了 UIScreenscale 属性。没有必要再检查它了。
  • 你没有裁剪。您正在将整个图像重新绘制到一个较小的区域中。搜索“ios裁剪图片”,你会找到很多解决问题的方法。
  • 谢谢@rmaddy - 我想我正在裁剪和重绘图像(压扁的图像有 8 个垂直平方数,而原始图像超过 11 个)。
  • 你不想画到clipRect。您希望以原始纵横比绘制图像,以便仅在 clipRect 中呈现您想要保留的部分。

标签: ios objective-c uiimage


【解决方案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,因为它没有在其余代码中使用。
  • 嗯……这很奇怪。我可以看一些截图吗?
  • 啊忘了缩放...等一下。
  • 这很好用,无论是前置摄像头还是后置摄像头。谢谢!我只是添加了一些更改,因为 newSizeCGSize 而不是 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
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-10-31
    • 2016-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-07
    相关资源
    最近更新 更多