2011-08-23 3 views
5

Utilizzando Obj-c/Cocoa-touch, sto cercando di ottenere le dimensioni dell'immagine di un elenco di immagini ma non voglio scaricarle. C'è un modo semplice per farlo? Ho trovato alcune soluzioni in altre lingue come this SO question ma sto cercando un modo più semplice.Dimensione immagine remota senza download

Grazie

+0

dimensioni dell'immagine (larghezza/altezza)? o dimensione del file immagine? – progrmr

+0

Dimensioni immagine – jonzz

risposta

0

Se si desidera ottenere solo la dimensione del file immagine è possibile utilizzare un NSURLConnection per richiedere solo le intestazioni dal server HTTP (senza scaricare il file immagine) e quindi estrarre il Content-Length: dalle intestazioni per ottenere le dimensioni del file. Utilizzare il metodo expectedContentLength nella classe NSURLResponse, vedere the doc per ulteriori dettagli. Non è ancora facile.

+0

Per farlo posso utilizzare ASIHTTPRequest. Intendevo le dimensioni dell'immagine e non le dimensioni, mi dispiace – jonzz

7

Ecco una categoria UIImage che uso per questo. È basato su fastimage. Un avvertimento importante è che NSURLConnectionDelegate è impostato sullo stesso NSURL e ciò potrebbe causare interferenze in determinate situazioni. Questo non è ancora completo (gli URL dei file sono ignorati per esempio ...) ma puoi vedere dove sta andando.

Intestazione:

#import <UIKit/UIKit.h> 

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

@interface UIImage (RemoteSize) 

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

@end 

Fonte:

#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

Grande! Grazie mille ! – BoilingLime