【问题标题】:UIImage resizing not working properlyUIImage 调整大小无法正常工作
【发布时间】:2012-05-16 11:48:36
【问题描述】:

所以我一直试图找出我做错了一段时间,但我无法弄清楚。我想要完成的是:

  1. 与UIImagePickerController合影
  2. 拍摄生成的照片并裁剪顶部和底部,使其变成正方形(类似于 Instagram)
  3. 在UIButton 中显示该图像

由于某种原因,每次我拍摄照片时,它都会在 UIButton 内失真,并且看起来好像裁剪无法正常工作。这就是我所做的。在didFinishPickingMediaWithInfo 方法中,我有以下代码:

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    //Copy the image to the userImage variable
    [picker dismissModalViewControllerAnimated:YES];
    userImage = nil;

    //Rotate & resize image
    userImage = [self resizeAndRotatePhoto:(UIImage *)[info objectForKey:UIImagePickerControllerOriginalImage]];
    NSLog(@"Userimage size, width: %f , height: %f", userImage.size.width , userImage.size.height);

    //Update the image form field with the image and set the image in the controller
    NSLog(@"Button size is height: %f , width: %f" , userImageAvatarButton.frame.size.height , userImageAvatarButton.frame.size.width);
   [userImageAvatarButton.layer setMasksToBounds:YES];
   [userImageAvatarButton.layer setCornerRadius:3.0];
   [userImageAvatarButton setImage:userImage forState:UIControlStateNormal];
}

我将暂时包含 resizeAndRotatePhoto 方法,但结果如下。此外,在上面的代码中,@property (strong) (UIImage *)userImage; 定义在 ViewController 的头文件中。日志输出还导致:

2012-05-07 17:38:07.995 NewApp[10666:707] Userimage size, width: 1936.000000 , height: 1936.000000
2012-05-07 17:38:08.000 NewApp[10666:707] Button size is height: 60.000000 , width: 60.000000

如下图所示,它最终被扭曲了。

至于resizeAndRotate方法,这里是:

- (UIImage *)resizeAndRotatePhoto:(UIImage *)source
{
if( source.imageOrientation == UIImageOrientationRight )
{
    source = [self rotateImage:source byDegrees:90];
}
if( userImage.imageOrientation == UIImageOrientationLeft)
{
    source = [self rotateImage:source byDegrees:-90];
}

CGFloat x,y;
CGFloat size;
if( source.size.width > source.size.height ){
    size = source.size.height;
    x = (source.size.width - source.size.height)/2;
    y = 0;
}
else {
    size = source.size.width;
    x = 0;
    y = (source.size.height - source.size.width)/2;
}


CGImageRef imageRef = CGImageCreateWithImageInRect([source CGImage], CGRectMake(x,y,size,size) );
return [UIImage imageWithCGImage:imageRef];
}

此时我不知道如何让这张图片显示不失真。尽管系统说图像确实是正方形,但它似乎裁剪错误并显示错误。

【问题讨论】:

    标签: objective-c ios cocoa-touch ios5 ios4


    【解决方案1】:

    出于其他原因,我放弃了 vocaro.com 解决方案(该解决方案在与非典型图像格式(例如 CMYK)一起使用时会崩溃)。

    无论如何,我现在使用以下UIImage 类别的imageByScalingAspectFillSize 方法来制作我的方形缩略图。

    顺便说一下,这会自动应用设备主屏幕的比例(例如,UIButton 按钮在 Retina 设备上是 60x60 点,这将应用 2x(或 3x)的比例,即 120x120或 180x180 图片)。

    UIImage+SimpleResize.h:

    /*  UIImage+SimpleResize.h
     *
     *  Modified by Robert Ryan on 5/19/11.
     */
    
    @import UIKit;
    
    /** Image resizing category.
     *
     *  Modified by Robert Ryan on 5/19/11.
     *
     *  Inspired by http://ofcodeandmen.poltras.com/2008/10/30/undocumented-uiimage-resizing/
     *  but adjusted to support AspectFill and AspectFit modes.
     */
    
    @interface UIImage (SimpleResize)
    
    /** Resize the image to be the required size, stretching it as needed.
     *
     * @param size         The new size of the image.
     * @param contentMode  The `UIViewContentMode` to be applied when resizing image.
     *                     Either `UIViewContentModeScaleToFill`, `UIViewContentModeScaleAspectFill`, or
     *                     `UIViewContentModeScaleAspectFit`.
     *
     * @return             Return `UIImage` of resized image.
     */
    
    - (UIImage * _Nullable)imageByScalingToSize:(CGSize)size contentMode:(UIViewContentMode)contentMode;
    
    /** Resize the image to be the required size, stretching it as needed.
     *
     * @param size         The new size of the image.
     * @param contentMode  The `UIViewContentMode` to be applied when resizing image.
     *                     Either `UIViewContentModeScaleToFill`, `UIViewContentModeScaleAspectFill`, or
     *                     `UIViewContentModeScaleAspectFit`.
     * @param scale        The scale factor to apply to the bitmap. If you specify a value of 0.0, the scale factor is set to the scale factor of the device’s main screen.
     *
     * @return             Return `UIImage` of resized image.
     */
    
    - (UIImage * _Nullable)imageByScalingToSize:(CGSize)size contentMode:(UIViewContentMode)contentMode scale:(CGFloat)scale;
    
    /** Crop the image to be the required size.
     *
     * @param bounds       The bounds to which the new image should be cropped.
     *
     * @return             Cropped `UIImage`.
     */
    
    - (UIImage * _Nullable)imageByCroppingToBounds:(CGRect)bounds;
    
    /** Crop the image to be the required size.
     *
     * @param bounds       The bounds to which the new image should be cropped.
     * @param scale        The scale factor to apply to the bitmap. If you specify a value of 0.0, the scale factor is set to the scale factor of the device’s main screen.
     *
     * @return             Cropped `UIImage`.
     */
    
    - (UIImage * _Nullable)imageByCroppingToBounds:(CGRect)bounds scale:(CGFloat)scale;
    
    /** Resize the image to fill the rectange of the specified size, preserving the aspect ratio, trimming if needed.
     *
     * @param size    The new size of the image.
     *
     * @return        Return `UIImage` of resized image.
     */
    
    - (UIImage * _Nullable)imageByScalingAspectFillSize:(CGSize)size;
    
    /** Resize the image to fill the rectange of the specified size, preserving the aspect ratio, trimming if needed.
     *
     * @param size    The new size of the image.
     * @param scale   The scale factor to apply to the bitmap. If you specify a value of 0.0, the scale factor is set to the scale factor of the device’s main screen.
     *
     * @return        Return `UIImage` of resized image.
     */
    
    - (UIImage * _Nullable)imageByScalingAspectFillSize:(CGSize)size scale:(CGFloat)scale;
    
    /** Resize the image to be the required size, stretching it as needed.
     *
     * @param size    The new size of the image.
     *
     * @return        Resized `UIImage` of resized image.
     */
    
    - (UIImage * _Nullable)imageByScalingToFillSize:(CGSize)size;
    
    /** Resize the image to be the required size, stretching it as needed.
     *
     * @param size    The new size of the image.
     * @param scale   The scale factor to apply to the bitmap. If you specify a value of 0.0, the scale factor is set to the scale factor of the device’s main screen.
     *
     * @return        Resized `UIImage` of resized image.
     */
    
    - (UIImage * _Nullable)imageByScalingToFillSize:(CGSize)size scale:(CGFloat)scale;
    
    /** Resize the image to fit within the required size, preserving the aspect ratio, with no trimming taking place.
     *
     * @param size    The new size of the image.
     *
     * @return        Return `UIImage` of resized image.
     */
    
    - (UIImage * _Nullable)imageByScalingAspectFitSize:(CGSize)size;
    
    /** Resize the image to fit within the required size, preserving the aspect ratio, with no trimming taking place.
     *
     * @param size    The new size of the image.
     * @param scale   The scale factor to apply to the bitmap. If you specify a value of 0.0, the scale factor is set to the scale factor of the device’s main screen.
     *
     * @return        Return `UIImage` of resized image.
     */
    
    - (UIImage * _Nullable)imageByScalingAspectFitSize:(CGSize)size scale:(CGFloat)scale;
    
    @end
    

    UIImage+SimpleResize.m:

    //  UIImage+SimpleResize.m
    //
    //  Created by Robert Ryan on 5/19/11.
    
    #import "UIImage+SimpleResize.h"
    
    @implementation UIImage (SimpleResize)
    
    - (UIImage *)imageByScalingToSize:(CGSize)size contentMode:(UIViewContentMode)contentMode {
        return [self imageByScalingToSize:size contentMode:contentMode scale:0];
    }
    
    - (UIImage *)imageByScalingToSize:(CGSize)size contentMode:(UIViewContentMode)contentMode scale:(CGFloat)scale {
        if (contentMode == UIViewContentModeScaleToFill) {
            return [self imageByScalingToFillSize:size];
        }
        else if ((contentMode == UIViewContentModeScaleAspectFill) ||
                 (contentMode == UIViewContentModeScaleAspectFit)) {
            CGFloat horizontalRatio   = self.size.width  / size.width;
            CGFloat verticalRatio     = self.size.height / size.height;
            CGFloat ratio;
    
            if (contentMode == UIViewContentModeScaleAspectFill)
                ratio = MIN(horizontalRatio, verticalRatio);
            else
                ratio = MAX(horizontalRatio, verticalRatio);
    
            CGSize  sizeForAspectScale = CGSizeMake(self.size.width / ratio, self.size.height / ratio);
    
            UIImage *image = [self imageByScalingToFillSize:sizeForAspectScale scale:scale];
    
            // if we're doing aspect fill, then the image still needs to be cropped
    
            if (contentMode == UIViewContentModeScaleAspectFill) {
                CGRect  subRect = CGRectMake(floor((sizeForAspectScale.width - size.width) / 2.0),
                                             floor((sizeForAspectScale.height - size.height) / 2.0),
                                             size.width,
                                             size.height);
                image = [image imageByCroppingToBounds:subRect];
            }
    
            return image;
        }
    
        return nil;
    }
    
    - (UIImage *)imageByCroppingToBounds:(CGRect)bounds {
        return [self imageByCroppingToBounds:bounds scale:0];
    }
    
    - (UIImage *)imageByCroppingToBounds:(CGRect)bounds scale:(CGFloat)scale {
        if (scale == 0) {
            scale = [[UIScreen mainScreen] scale];
        }
        CGRect rect = CGRectMake(bounds.origin.x * scale, bounds.origin.y * scale, bounds.size.width * scale, bounds.size.height * scale);
        CGImageRef imageRef = CGImageCreateWithImageInRect([self CGImage], rect);
        UIImage *croppedImage = [UIImage imageWithCGImage:imageRef scale:scale orientation:self.imageOrientation];
        CGImageRelease(imageRef);
        return croppedImage;
    }
    
    - (UIImage *)imageByScalingToFillSize:(CGSize)size {
        return [self imageByScalingToFillSize:size scale:0];
    }
    
    - (UIImage *)imageByScalingToFillSize:(CGSize)size scale:(CGFloat)scale {
        UIGraphicsBeginImageContextWithOptions(size, false, scale);
        [self drawInRect:CGRectMake(0, 0, size.width, size.height)];
        UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
    
        return image;
    }
    
    - (UIImage *)imageByScalingAspectFillSize:(CGSize)size {
        return [self imageByScalingAspectFillSize:size scale:0];
    }
    
    - (UIImage *)imageByScalingAspectFillSize:(CGSize)size scale:(CGFloat)scale {
        return [self imageByScalingToSize:size contentMode:UIViewContentModeScaleAspectFill scale:scale];
    }
    
    - (UIImage *)imageByScalingAspectFitSize:(CGSize)size {
        return [self imageByScalingAspectFitSize:size scale:0];
    }
    
    - (UIImage *)imageByScalingAspectFitSize:(CGSize)size scale:(CGFloat)scale {
        return [self imageByScalingToSize:size contentMode:UIViewContentModeScaleAspectFit scale:scale];
    }
    
    @end
    

    【讨论】:

    • 谢谢。经过数小时的挫折和在线搜索,尝试了近 20 种建议的解决方案,这是唯一有效的解决方案。非常感谢。
    • 是的。也节省了我几个小时的工作时间。我很欣赏这个类别!
    猜你喜欢
    • 1970-01-01
    • 2023-03-16
    • 2019-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-24
    • 1970-01-01
    • 2014-04-03
    相关资源
    最近更新 更多