2011-08-23 11 views
5

Usando Obj-c/Cocoa-touch, estoy tratando de obtener el tamaño de imagen de una lista de imágenes pero no quiero descargarlas. ¿Hay alguna manera fácil de hacerlo? Encontré algunas soluciones en otros idiomas como this SO question pero estoy buscando una manera más fácil.Tamaño de imagen remota sin descargar

Gracias

+0

dimensiones de imagen (ancho/alto)? o el tamaño del archivo de imagen? – progrmr

+0

Dimensiones de la imagen – jonzz

Respuesta

0

Si desea obtener sólo el tamaño del archivo de imagen que puede utilizar un NSURLConnection para solicitar sólo los encabezados del servidor HTTP (sin necesidad de descargar el archivo de imagen) y luego extraer el Content-Length: de los encabezados para obtener el tamaño del archivo. Utilice el método expectedContentLength en la clase NSURLResponse, consulte the doc para obtener más detalles. Todavía no es fácil.

+0

Para hacer eso, puedo usar ASIHTTPRequest. Quise decir las dimensiones de la imagen y no el tamaño, lo siento – jonzz

7

Aquí hay una categoría de UIImage que utilizo para esto. Se basa en fastimage. Una advertencia importante es que NSURLConnectionDelegate está configurado en el NSURL y esto puede causar conflictos en ciertas situaciones. Esto aún no está completo (por ejemplo, se ignoran las URL de los archivos ...) pero puede ver hacia dónde se dirige.

Header:

#import <UIKit/UIKit.h> 

typedef void (^UIImageSizeRequestCompleted) (NSURL* imgURL, CGSize size); 

@interface UIImage (RemoteSize) 

+ (void) requestSizeFor: (NSURL*) imgURL completion: (UIImageSizeRequestCompleted) completion; 

@end 

Fuente:

#import "UIImage+RemoteSize.h" 

#import <objc/runtime.h> 

static char *kSizeRequestDataKey = "NSURL.sizeRequestData"; 
static char *kSizeRequestTypeKey = "NSURL.sizeRequestType"; 
static char *kSizeRequestCompletionKey = "NSURL.sizeRequestCompletion"; 

typedef uint32_t dword; 

@interface NSURL (RemoteSize) 
@property (nonatomic, strong) NSMutableData* sizeRequestData; 
@property (nonatomic, strong) NSString* sizeRequestType; 
@property (nonatomic, copy) UIImageSizeRequestCompleted sizeRequestCompletion; 
@end 

@implementation NSURL (RemoteSize) 

- (void) setSizeRequestCompletion: (UIImageSizeRequestCompleted) block { 
    objc_setAssociatedObject(self, &kSizeRequestCompletionKey, block, OBJC_ASSOCIATION_COPY); 
} 

- (UIImageSizeRequestCompleted) sizeRequestCompletion { 
    return objc_getAssociatedObject(self, &kSizeRequestCompletionKey); 
} 

- (void) setSizeRequestData:(NSMutableData *)sizeRequestData { 
    objc_setAssociatedObject(self, &kSizeRequestDataKey, sizeRequestData, OBJC_ASSOCIATION_RETAIN); 
} 

- (NSMutableData*) sizeRequestData { 
    return objc_getAssociatedObject(self, &kSizeRequestDataKey); 
} 

- (void) setSizeRequestType:(NSString *)sizeRequestType { 
    objc_setAssociatedObject(self, &kSizeRequestTypeKey, sizeRequestType, OBJC_ASSOCIATION_RETAIN); 
} 

- (NSString*) sizeRequestType { 
    return objc_getAssociatedObject(self, &kSizeRequestTypeKey); 
} 

#pragma mark - NSURLConnectionDelegate 
- (void) connection: (NSURLConnection*) connection didReceiveResponse:(NSURLResponse *)response { 
    [self.sizeRequestData setLength: 0]; //Redirected => reset data 
} 

- (void) connection: (NSURLConnection*) connection didReceiveData:(NSData *)data { 
    NSMutableData* receivedData = self.sizeRequestData; 

    if(!receivedData) { 
     receivedData = [NSMutableData data]; 
     self.sizeRequestData = receivedData; 
    } 

    [receivedData appendData: data]; 

    //Parse metadata 
    const unsigned char* cString = [receivedData bytes]; 
    const NSInteger length = [receivedData length]; 

    const char pngSignature[8] = {137, 80, 78, 71, 13, 10, 26, 10}; 
    const char bmpSignature[2] = {66, 77}; 
    const char gifSignature[2] = {71, 73}; 
    const char jpgSignature[2] = {255, 216}; 

    if(!self.sizeRequestType) { 
     if(memcmp(pngSignature, cString, 8) == 0) { 
      self.sizeRequestType = @"PNG"; 
     } 
     else if(memcmp(bmpSignature, cString, 2) == 0) { 
      self.sizeRequestType = @"BMP"; 
     } 
     else if(memcmp(jpgSignature, cString, 2) == 0) { 
      self.sizeRequestType = @"JPG"; 
     } 
     else if(memcmp(gifSignature, cString, 2) == 0) { 
      self.sizeRequestType = @"GIF"; 
     } 
    } 

    if([self.sizeRequestType isEqualToString: @"PNG"]) { 
     char type[5]; 
     int offset = 8; 

     dword chunkSize = 0; 
     int chunkSizeSize = sizeof(chunkSize); 

     if(offset+chunkSizeSize > length) 
      return; 

     memcpy(&chunkSize, cString+offset, chunkSizeSize); 
     chunkSize = OSSwapInt32(chunkSize); 
     offset += chunkSizeSize; 

     if(offset + chunkSize > length) 
      return; 

     memcpy(&type, cString+offset, 4); type[4]='\0'; 
     offset += 4; 

     if(strcmp(type, "IHDR") == 0) { //Should always be first 
      dword width = 0, height = 0; 
      memcpy(&width, cString+offset, 4); 
      offset += 4; 
      width = OSSwapInt32(width); 

      memcpy(&height, cString+offset, 4); 
      offset += 4; 
      height = OSSwapInt32(height); 

      if(self.sizeRequestCompletion) { 
       self.sizeRequestCompletion(self, CGSizeMake(width, height)); 
      } 

      self.sizeRequestCompletion = nil; 

      [connection cancel]; 
     } 
    } 
    else if([self.sizeRequestType isEqualToString: @"BMP"]) { 
     int offset = 18; 
     dword width = 0, height = 0; 
     memcpy(&width, cString+offset, 4); 
     offset += 4; 

     memcpy(&height, cString+offset, 4); 
     offset += 4; 

     if(self.sizeRequestCompletion) { 
      self.sizeRequestCompletion(self, CGSizeMake(width, height)); 
     } 

     self.sizeRequestCompletion = nil; 

     [connection cancel]; 
    } 
    else if([self.sizeRequestType isEqualToString: @"JPG"]) { 
     int offset = 4; 
     dword block_length = cString[offset]*256 + cString[offset+1]; 

     while (offset<length) { 
      offset += block_length; 

      if(offset >= length) 
       break; 
      if(cString[offset] != 0xFF) 
       break; 
      if(cString[offset+1] == 0xC0 || 
       cString[offset+1] == 0xC1 || 
       cString[offset+1] == 0xC2 || 
       cString[offset+1] == 0xC3 || 
       cString[offset+1] == 0xC5 || 
       cString[offset+1] == 0xC6 || 
       cString[offset+1] == 0xC7 || 
       cString[offset+1] == 0xC9 || 
       cString[offset+1] == 0xCA || 
       cString[offset+1] == 0xCB || 
       cString[offset+1] == 0xCD || 
       cString[offset+1] == 0xCE || 
       cString[offset+1] == 0xCF) { 

       dword width = 0, height = 0; 

       height = cString[offset+5]*256 + cString[offset+6]; 
       width = cString[offset+7]*256 + cString[offset+8]; 

       if(self.sizeRequestCompletion) { 
        self.sizeRequestCompletion(self, CGSizeMake(width, height)); 
       } 

       self.sizeRequestCompletion = nil; 

       [connection cancel]; 

      } 
      else { 
       offset += 2; 
       block_length = cString[offset]*256 + cString[offset+1]; 
      } 

     } 
    } 
    else if([self.sizeRequestType isEqualToString: @"GIF"]) { 
     int offset = 6; 
     dword width = 0, height = 0; 
     memcpy(&width, cString+offset, 2); 
     offset += 2; 

     memcpy(&height, cString+offset, 2); 
     offset += 2; 

     if(self.sizeRequestCompletion) { 
      self.sizeRequestCompletion(self, CGSizeMake(width, height)); 
     } 

     self.sizeRequestCompletion = nil; 

     [connection cancel]; 
    } 
} 

- (void) connection: (NSURLConnection*) connection didFailWithError:(NSError *)error { 
    if(self.sizeRequestCompletion) 
     self.sizeRequestCompletion(self, CGSizeZero); 
} 

- (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse { 
    return cachedResponse; 
} 

- (void) connectionDidFinishLoading: (NSURLConnection *)connection { 
    // Basically, we failed to obtain the image size using metadata and the 
    // entire image was downloaded... 

    if(!self.sizeRequestData.length) { 
     self.sizeRequestData = nil; 
    } 
    else { 
     //Try parse to UIImage 
     UIImage* image = [UIImage imageWithData: self.sizeRequestData]; 

     if(self.sizeRequestCompletion && image) { 
      self.sizeRequestCompletion(self, [image size]); 
      return; 
     } 
    } 

    self.sizeRequestCompletion(self, CGSizeZero); 
} 

@end 

@implementation UIImage (RemoteSize) 

+ (void) requestSizeFor: (NSURL*) imgURL completion: (UIImageSizeRequestCompleted) completion { 

    if([imgURL isFileURL]) { 
     //Load from file stream 
    } 
    else { 
     imgURL.sizeRequestCompletion = completion; 

     NSURLRequest* request = [NSURLRequest requestWithURL: imgURL]; 
     NSURLConnection* conn = [NSURLConnection connectionWithRequest: request delegate: imgURL]; 
     [conn scheduleInRunLoop: [NSRunLoop mainRunLoop] forMode: NSDefaultRunLoopMode]; 
     [conn start]; 
    } 
} 

@end 
+0

¡Genial! Muchas gracias ! – BoilingLime

Cuestiones relacionadas