Obtenga imágenes de dimensiones de files remotamente a través de la URL del file.

Estoy usando la API de Dropbox Core y me estoy estancando mientras busco una forma de get las dimensiones de los files de imágenes. Recibo miniaturas en el dispositivo, pero necesito saber el ancho y la altura de las imágenes para procesar las modificaciones en ellas.

Y definitivamente no quiero download el file completo en el teléfono para verificar sus dimensiones. ¿Hay trucos en los que piensas para conseguirlos? Lo único que tengo en los metadatos es el tamaño del file, que es bastante inútil en mi caso.

Muchas gracias.

Me di count de mi respuesta. Uso una categoría UIImage que download parte del file a través de una URL. Una vez que obtiene suficientes datos para definir el tamaño, detiene la descarga.

Hice algunas testings y descargó aproximadamente 30 kB para get las dimensiones de la image, independientemente del file 300 KB o 10 MB grande, lo cual es realmente rápido.

Se podría usar para cualquier file de image, no solo para la API de Dropbox.

Aquí está el encabezado de la Categoría:

#import <UIKit/UIKit.h> typedef void (^UIImageSizeRequestCompleted) (NSURL* imgURL, CGSize size); @interface UIImage (RemoteSize) + (void) requestSizeFor: (NSURL*) imgURL completion: (UIImageSizeRequestCompleted) completion; @end 

Y aquí está el file fuente:

 #import "UIImage+RemoteSize.h" #import <objc/runtime.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 

Muchas gracias a esta publicación que me ayuda mucho: tamaño de image remota sin descarga

Espero que te ayude también.