El cambio de tamaño de UIImage no funciona correctamente

Así que he estado tratando de averiguar qué estoy haciendo mal desde hace un tiempo y no puedo resolverlo. Lo que bash lograr es esto:

  1. Toma una foto con UIImagePickerController
  2. Tome la foto resultante y recorte la parte superior e inferior para que se convierta en un cuadrado (similar a Instagram)
  3. Muestre esa imagen dentro de un UIButton

Por alguna razón, cada vez que tomo la foto termina distorsionada dentro del UIButton y parece que el recorte no funcionó correctamente. Esto es lo que hago. Dentro del método didFinishPickingMediaWithInfo tengo el siguiente código:

 - (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]; } 

Incluiré el método resizeAndRotatePhoto momentáneamente pero el resultado está debajo. Además, en el código anterior, @property (strong) (UIImage *)userImage; se define en el archivo de encabezado ViewController. La salida de registro también da como resultado:

 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 

Como puede ver en la imagen a continuación, termina distorsionada.
formulario con botón

En cuanto al método resizeAndRotate, aquí está:

 - (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]; } 

En este punto, no tengo idea de cómo hacer que esta imagen se muestre sin distorsiones. Parece estar recortándolo mal y mostrándolo mal a pesar de que el sistema dice que la imagen es de hecho un cuadrado.

Abandoné esa solución de vocaro.com por otros motivos (esa solución fallaría cuando se utilizara con formatos de imagen atípicos, por ejemplo, CMYK).

De todos modos, ahora uso el método imageByScalingAspectFillSize de la siguiente categoría UIImage para hacer mis miniaturas cuadradas.

Por cierto, esto aplica automáticamente la escala de la pantalla principal del dispositivo (por ejemplo, botón UIButton que es 60×60 puntos en un dispositivo Retina, esto aplicará esa escala de 2x (o 3x), es decir, una imagen de 120×120 o 180×180).

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