El cambio de tamaño de UIImage no funciona correctamente

Así que he intentado descubrir qué estoy haciendo mal por un time y no puedo resolverlo. Lo que trato de lograr es esto:

  1. Tome 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. Muestra esa image 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 file de encabezado ViewController. La salida del logging 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 image de abajo, 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 image se muestre sin distorsiones. Parece que se está recortando mal y se muestra mal a pesar del sistema que dice que la image es, de hecho, un cuadrado.

Abandoné esa solución vocaro.com por otros motivos (esa solución fallaba cuando se usaba con formattings de image atípicos, por ejemplo, CMYK).

De todos modos, ahora utilizo 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, el button UIButton que tiene 60×60 puntos en un dispositivo Retina, esto aplicará esa escala de 2x (o 3x), es decir, una image 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. * * Inspinetworking 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 requinetworking 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 requinetworking 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 requinetworking 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 requinetworking 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 requinetworking 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 requinetworking 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 requinetworking 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 requinetworking 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