2012-05-08 21 views
6

Así que he estado tratando de averiguar qué estoy haciendo mal desde hace un tiempo y no puedo resolverlo. Lo que estoy tratando de lograr es la siguiente:El cambio de tamaño de UIImage no funciona correctamente

  1. tomar una foto con UIImagePickerController
  2. Tome la foto resultante y recortar la parte superior e inferior por lo que se convierte en un cuadrado (similar a Instagram)
  3. de visualización que imagen dentro de un UIButton

Por alguna razón, cada vez que tome la foto que termina distorsionada dentro del UIButton y parece como si el cultivo no funcionaba 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]; 
} 

voy a incluir el método resizeAndRotatePhoto momentáneamente pero el resultado está por 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 ve en la imagen siguiente, termina distorsionada.
form with button

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 obtener esta imagen para aparecer 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.

Respuesta

9

Abandoné esa solución de vocaro.com por otros motivos (esa solución fallará cuando se utilice 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, UIButton botón que es 60x60 puntos en un dispositivo Retina, esto aplicará esa escala de 2x (o 3x), es decir, 120x120 o Imagen 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 
+2

Gracias. Después de horas y horas de frustración y búsqueda en línea, probando cerca de 20 soluciones propuestas, esta es la ÚNICA solución que ha funcionado. Muchas gracias. – thephatp

+1

yup. me ahorró horas de trabajo también. Aprecio la categoría! – kevinl

Cuestiones relacionadas