UIImage调整大小不正常

Nic*_*ill 8 cocoa-touch objective-c ios4 ios ios5

所以我一直试图弄清楚我现在做错了一段时间,我无法弄明白.我想要完成的是:

  1. 拍张照片 UIImagePickerController
  2. 拍摄照片并从顶部和底部裁剪,使其成为正方形(类似于Instagram)
  3. 在a中显示该图像 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];
}
Run Code Online (Sandbox Code Playgroud)

我将暂时包含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
Run Code Online (Sandbox Code Playgroud)

正如您在下图中看到的那样,它最终会失真.
形式与按钮

至于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];
}
Run Code Online (Sandbox Code Playgroud)

在这一点上,我不知道如何使这个图像显示未失真.尽管系统说图像确实是一个正方形,但它似乎正在裁剪错误并显示错误.

Rob*_*Rob 9

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

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

顺便说一下,这会自动应用设备主屏幕的比例(例如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
Run Code Online (Sandbox Code Playgroud)

的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
Run Code Online (Sandbox Code Playgroud)

  • 谢谢.经过几个小时的挫折和在线搜索接近20个提议的解决方案,这是唯一有效的解决方案.非常感谢. (2认同)