2010-11-12 16 views
18

Como ya sabrá, las instrucciones para el iPhone desalientan la carga de uiimágenes que son mayores que 1024x1024.accediendo a las propiedades de UIImage sin cargar en la memoria la imagen

El tamaño de las imágenes que tendría que cargar varía, y me gustaría comprobar el tamaño de la imagen que estoy a punto de cargar; sin embargo, el uso de la propiedad .size de uiimage requiere que la imagen se sature ... que es exactamente lo que intento evitar.

¿Hay algún error en mi razonamiento o hay una solución para eso?

gracias a todos

+1

Esta es una buena pregunta. Android proporciona un medio para hacer esto, pero no sé de una solución iOS de forma directa. EDITAR: Esto se ha preguntado antes. http://stackoverflow.com/questions/1551300/get-size-of-image-without-loading-in-to-memory – Justin

+0

busqué antes, ¡pero no pude encontrarlo! ¡muchas gracias! – koda

Respuesta

32

A partir de iOS 4.0, el SDK de iOS incluye la CGImageSource... functions (en el marco ImageIO). Es una API muy flexible para consultar metadatos sin cargar la imagen en la memoria. Obtener las dimensiones en píxeles de una imagen debería funcionar como esto (asegúrese de incluir el ImageIO.framework en su objetivo):

#import <ImageIO/ImageIO.h> 

NSURL *imageFileURL = [NSURL fileURLWithPath:...]; 
CGImageSourceRef imageSource = CGImageSourceCreateWithURL((CFURLRef)imageFileURL, NULL); 
if (imageSource == NULL) { 
    // Error loading image 
    ... 
    return; 
} 

CGFloat width = 0.0f, height = 0.0f; 
CFDictionaryRef imageProperties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, NULL); 

CFRelease(imageSource); 

if (imageProperties != NULL) { 

    CFNumberRef widthNum = CFDictionaryGetValue(imageProperties, kCGImagePropertyPixelWidth); 
    if (widthNum != NULL) { 
     CFNumberGetValue(widthNum, kCFNumberCGFloatType, &width); 
    } 

    CFNumberRef heightNum = CFDictionaryGetValue(imageProperties, kCGImagePropertyPixelHeight); 
    if (heightNum != NULL) { 
     CFNumberGetValue(heightNum, kCFNumberCGFloatType, &height); 
    } 

    // Check orientation and flip size if required 
    CFNumberRef orientationNum = CFDictionaryGetValue(imageProperties, kCGImagePropertyOrientation); 
    if (orientationNum != NULL) { 
     int orientation; 
     CFNumberGetValue(orientationNum, kCFNumberIntType, &orientation); 
     if (orientation > 4) { 
      CGFloat temp = width; 
      width = height; 
      height = temp; 
     } 
    } 

    CFRelease(imageProperties); 
} 

NSLog(@"Image dimensions: %.0f x %.0f px", width, height); 

(adaptado de "Programación con cuarzo" por Gelphman y Laden, enumerando 9.5, página 228)

+2

¿Por qué usar 'CGImageSourceCopyPropertiesAtIndex' en lugar de' CGImageSourceCopyProperties'? – jcm

+3

Es muy importante pasar 'kCFNumberCGFloatType' en lugar de' kCFNumberFloatType' al llamar a CFNumberGetValue() ya que las variables 'width' y' height' se declaran como 'CGFloat'. El código anterior funcionará en sistemas de 32 bits, pero los valores contendrán basura en los sistemas de 64 bits. – fjoachim

+0

@fjoachim: Gracias, corregido. –

3

Swift versión 3 de la respuesta:

import Foundation 
import ImageIO 

func sizeForImage(at url: URL) -> CGSize? { 

    guard let imageSource = CGImageSourceCreateWithURL(url as CFURL, nil) 
     , let imageProperties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, nil) as? [AnyHashable: Any] 
     , let pixelWidth = imageProperties[kCGImagePropertyPixelWidth as String] 
     , let pixelHeight = imageProperties[kCGImagePropertyPixelHeight as String] 
     , let orientationNumber = imageProperties[kCGImagePropertyOrientation as String] 
     else { 
      return nil 
    } 

    var width: CGFloat = 0, height: CGFloat = 0, orientation: Int = 0 

    CFNumberGetValue(pixelWidth as! CFNumber, .cgFloatType, &width) 
    CFNumberGetValue(pixelHeight as! CFNumber, .cgFloatType, &height) 
    CFNumberGetValue(orientationNumber as! CFNumber, .intType, &orientation) 

    // Check orientation and flip size if required 
    if orientation > 4 { let temp = width; width = height; height = temp } 

    return CGSize(width: width, height: height) 
} 
Cuestiones relacionadas