2011-01-17 16 views
36

Tengo una aplicación donde estoy mostrando imágenes grandes en un espacio pequeño. Las imágenes son bastante grandes, pero solo las visualizo en marcos de 100x100 píxeles. Mi aplicación está respondiendo lentamente debido al tamaño de las imágenes que estoy usando.Cómo cambiar el tamaño de la imagen mediante programación en Object-C en iphone

Para mejorar el rendimiento, ¿cómo puedo cambiar el tamaño de las imágenes programáticamente usando Objective-C?

+1

Ver http://stackoverflow.com/questions/2658738/the-simplest-way-to- resize-an-uiimage – Costique

+0

Escribí un código para escalar una imagen por un factor de dos al caminar a través de los píxeles y sumar 4 píxeles en uno. Funcionó bastante bien (mejor calidad de imagen que usar la escala del sistema), pero tal vez tenía 50 líneas de código y no era realmente bonita. (Entonces descubrí que no necesitaba escalar la imagen de todos modos.) –

+0

Aquí está el hilo donde se puede encontrar mi algoritmo: http: // stackoverflow.com/questions/6052188/high-quality-scaling-of-uiimage –

Respuesta

87

Encuentra el siguiente código.

- (UIImage *)imageWithImage:(UIImage *)image convertToSize:(CGSize)size { 
    UIGraphicsBeginImageContext(size); 
    [image drawInRect:CGRectMake(0, 0, size.width, size.height)]; 
    UIImage *destImage = UIGraphicsGetImageFromCurrentImageContext();  
    UIGraphicsEndImageContext(); 
    return destImage; 
} 
+2

Esto funcionó en el pasado, pero en iOS5. 0.1 esto está dando como resultado una pérdida de memoria. ¿Alguna otra forma de lograr esto? http://stackoverflow.com/questions/8236837/memory-leak-drawinrect-on-ios5-0-1 – David

+0

¿Sigue siendo un problema con iOS 6.x? – Paaske

+0

Sí, aún da como resultado una pérdida de memoria ... –

0

Dado que el código funcionó perfectamente bien en IOS 4, para la compatibilidad hacia atrás he añadido un cheque para la versión del sistema operativo y para cualquier cosa por debajo de 5,0 el viejo código funcionaría.

- (UIImage *)resizedImage:(CGSize)newSize interpolationQuality:(CGInterpolationQuality)quality { 
    BOOL drawTransposed; 
    CGAffineTransform transform = CGAffineTransformIdentity; 

    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 5.0) { 
     // Apprently in iOS 5 the image is already correctly rotated, so we don't need to rotate it manually 
     drawTransposed = NO; 
    } else {  
     switch (self.imageOrientation) { 
      case UIImageOrientationLeft: 
      case UIImageOrientationLeftMirrored: 
      case UIImageOrientationRight: 
      case UIImageOrientationRightMirrored: 
       drawTransposed = YES; 
       break; 

      default: 
       drawTransposed = NO; 
     } 

     transform = [self transformForOrientation:newSize]; 
    } 

    return [self resizedImage:newSize 
        transform:transform 
       drawTransposed:drawTransposed 
     interpolationQuality:quality]; 
} 
+2

Parece que el código se llama a sí mismo sin detenerse. – Binarian

4

Mi manera preferida de hacerlo es con CGImageSourceCreateThumbnailAtIndex (en el marco ImageIO). El nombre es un poco engañoso.

Aquí hay un fragmento de algún código de una aplicación reciente mía.

CGFloat maxw = // whatever; 
CGFloat maxh = // whatever; 

CGImageSourceRef src = NULL; 
if ([imageSource isKindOfClass:[NSURL class]]) 
    src = CGImageSourceCreateWithURL((__bridge CFURLRef)imageSource, nil); 
else if ([imageSource isKindOfClass:[NSData class]]) 
    src = CGImageSourceCreateWithData((__bridge CFDataRef)imageSource, nil); 

// if at double resolution, double the thumbnail size and use double-resolution image 
CGFloat scale = 1; 
if ([[UIScreen mainScreen] scale] > 1.0) { 
    scale = 2; 
    maxw *= 2; 
    maxh *= 2; 
} 

// load the image at the desired size 
NSDictionary* d = @{ 
        (id)kCGImageSourceShouldAllowFloat: (id)kCFBooleanTrue, 
        (id)kCGImageSourceCreateThumbnailWithTransform: (id)kCFBooleanTrue, 
        (id)kCGImageSourceCreateThumbnailFromImageAlways: (id)kCFBooleanTrue, 
        (id)kCGImageSourceThumbnailMaxPixelSize: @((int)(maxw > maxh ? maxw : maxh)) 
        }; 
CGImageRef imref = CGImageSourceCreateThumbnailAtIndex(src, 0, (__bridge CFDictionaryRef)d); 
if (NULL != src) 
    CFRelease(src); 
UIImage* im = [UIImage imageWithCGImage:imref scale:scale orientation:UIImageOrientationUp]; 
if (NULL != imref) 
    CFRelease(imref); 
0

Puede usar esto.

[m_Image.layer setMinificationFilter:kCAFilterTrilinear];

+0

esto se utiliza para UIImageView y no para UIImage – vinceville

2

Si está utilizando una imagen en diferentes tamaños y cambiar el tamaño cada vez que se degradará el rendimiento de su aplicación. La solución es no cambiar el tamaño de ellos simplemente use el botón en lugar de la vista de imagen. y simplemente configure la imagen en el botón, cambiará el tamaño automáticamente y obtendrá un gran rendimiento.

También cambiaba el tamaño de las imágenes mientras las configuraba en la celda, pero mi aplicación se volvió lenta. Utilicé el botón en lugar de la vista de imagen (sin cambiar el tamaño de las imágenes programaticamente el botón está haciendo este trabajo) y funciona perfectamente bien.

5

Este código es solo para cambiar la escala de la imagen no para cambiar el tamaño Debe establecer CGSize como el ancho de su imagen y alto para que la imagen no se estire y se acomode en el medio.

- (UIImage *)imageWithImage:(UIImage *)image scaledToFillSize:(CGSize)size 
{ 
    CGFloat scale = MAX(size.width/image.size.width, size.height/image.size.height); 
    CGFloat width = image.size.width * scale; 
    CGFloat height = image.size.height * scale; 
    CGRect imageRect = CGRectMake((size.width - width)/2.0f, 
            (size.height - height)/2.0f, 
            width, 
            height); 

    UIGraphicsBeginImageContextWithOptions(size, NO, 0); 
    [image drawInRect:imageRect]; 
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 
    return newImage; 
} 
+0

Esto funciona perfectamente para mí muchas gracias. –

+0

Disfruta de tu codificación @NishadArora :) –

1
-(UIImage *)scaleImage:(UIImage *)image toSize:.  (CGSize)targetSize 
    { 
//If scaleFactor is not touched, no scaling will occur 
    CGFloat scaleFactor = 1.0; 

//Deciding which factor to use to scale the image (factor = targetSize/imageSize) 
if (image.size.width > targetSize.width || 
    image.size.height > targetSize.height || image.size.width == image.size.height) 
    if (!((scaleFactor = (targetSize.width/
    image.size.width)) > (targetSize.height/
     image.size.height))) //scale to fit width, or 
     scaleFactor = targetSize.height/image.size.height; // scale to fit heigth. 
0

Este hilo es viejo, pero es lo que me sacó cuando se trata de resolver este problema. Una vez que la imagen se escala, no se mostraba bien en mi contenedor a pesar de que desactivaba el diseño automático. La forma más fácil para mí de resolver esto para mostrar en una fila de la mesa, era pintar la imagen sobre un fondo blanco que tenía un tamaño fijo.

Función de ayuda

+(UIImage*)scaleMaintainAspectRatio:(UIImage*)sourceImage :(float)i_width :(float)i_height 
{ 
float newHeight = 0.0; 
float newWidth = 0.0; 

float oldWidth = sourceImage.size.width; 
float widthScaleFactor = i_width/oldWidth; 

float oldHeight = sourceImage.size.height; 
float heightScaleFactor = i_height/oldHeight; 
if (heightScaleFactor > widthScaleFactor) { 
    newHeight = oldHeight * widthScaleFactor; 
    newWidth = sourceImage.size.width * widthScaleFactor; 
} else { 
    newHeight = sourceImage.size.height * heightScaleFactor; 
    newWidth = oldWidth * heightScaleFactor; 
} 

// return image in white rect 
float cxPad = i_width - newWidth; 
float cyPad = i_height - newHeight; 
if (cyPad > 0) { 
    cyPad = cyPad/2.0; 
} 
if (cxPad > 0) { 
    cxPad = cxPad/2.0; 
} 

CGSize size = CGSizeMake(i_width, i_height); 
UIGraphicsBeginImageContextWithOptions(CGSizeMake(size.width, size.height), YES, 0.0); 
[[UIColor whiteColor] setFill]; 
UIRectFill(CGRectMake(0, 0, size.width, size.height)); 
[sourceImage drawInRect:CGRectMake((int)cxPad, (int)cyPad, newWidth, newHeight)]; 
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); 
UIGraphicsEndImageContext(); 
return newImage; 

// will return scaled image at actual size, not in white rect 
// UIGraphicsBeginImageContext(CGSizeMake(newWidth, newHeight)); 
// [sourceImage drawInRect:CGRectMake(0, 0, newWidth, newHeight)]; 
// UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); 
// UIGraphicsEndImageContext(); 
// return newImage; 
} 

me llamaron a este como esto de mi mesa vista cellForRowAtIndexPath

PFFile *childsPicture = [object objectForKey:@"picture"]; 
[childsPicture getDataInBackgroundWithBlock:^(NSData *imageData, NSError *error) { 
    if (!error) { 
     UIImage *largePicture = [UIImage imageWithData:imageData]; 
     UIImage *scaledPicture = [Utility scaleMaintainAspectRatio:largePicture :70.0 :70.0 ]; 
     PFImageView *thumbnailImageView = (PFImageView*)[cell viewWithTag:100]; 
     thumbnailImageView.image = scaledPicture; 
     [self.tableView reloadData]; 
    } 
}]; 
Cuestiones relacionadas