Encontrar el tipo de image de NSData o UIImage

Estoy cargando una image de una URL proporcionada por un tercero. No hay una extensión de file (o nombre de file para el caso) en la URL (ya que es una URL oscurecida). Puedo tomar los datos de este (en forma de NSData) y cargarlos en un UIImage y mostrarlos bien.

Quiero mantener estos datos en un file. Sin embargo, no sé en qué formatting están los datos (PNG, JPG, BMP)? Supongo que es JPG (ya que es una image de la web), pero ¿hay una forma programática de averiguarlo a ciencia cierta? He mirado alnetworkingedor de StackOverflow y en la documentation y no he podido encontrar nada.

TIA.


Edit: ¿Realmente necesito la extensión de file? Lo estoy persistiendo en un almacenamiento externo (Amazon S3), pero teniendo en count que siempre se usará en el context de iOS o un browser (ambos parecen estar bien interpretando los datos sin una extensión), tal vez esto no sea un problema .

Si tiene NSData para el file de image, puede adivinar el tipo de contenido mirando el primer byte:

+ (NSString *)contentTypeForImageData:(NSData *)data { uint8_t c; [data getBytes:&c length:1]; switch (c) { case 0xFF: return @"image/jpeg"; case 0x89: return @"image/png"; case 0x47: return @"image/gif"; case 0x49: case 0x4D: return @"image/tiff"; } return nil; } 

Al mejorar la respuesta de wl , aquí hay una manera mucho más extensa y precisa de pnetworkingecir el tipo MIME de la image en function de la firma. El código se inspiró en gran medida en php's ext / standard / image.c .

 - (NSString *)mimeTypeByGuessingFromData:(NSData *)data { char bytes[12] = {0}; [data getBytes:&bytes length:12]; const char bmp[2] = {'B', 'M'}; const char gif[3] = {'G', 'I', 'F'}; const char swf[3] = {'F', 'W', 'S'}; const char swc[3] = {'C', 'W', 'S'}; const char jpg[3] = {0xff, 0xd8, 0xff}; const char psd[4] = {'8', 'B', 'P', 'S'}; const char iff[4] = {'F', 'O', 'R', 'M'}; const char webp[4] = {'R', 'I', 'F', 'F'}; const char ico[4] = {0x00, 0x00, 0x01, 0x00}; const char tif_ii[4] = {'I','I', 0x2A, 0x00}; const char tif_mm[4] = {'M','M', 0x00, 0x2A}; const char png[8] = {0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a}; const char jp2[12] = {0x00, 0x00, 0x00, 0x0c, 0x6a, 0x50, 0x20, 0x20, 0x0d, 0x0a, 0x87, 0x0a}; if (!memcmp(bytes, bmp, 2)) { return @"image/x-ms-bmp"; } else if (!memcmp(bytes, gif, 3)) { return @"image/gif"; } else if (!memcmp(bytes, jpg, 3)) { return @"image/jpeg"; } else if (!memcmp(bytes, psd, 4)) { return @"image/psd"; } else if (!memcmp(bytes, iff, 4)) { return @"image/iff"; } else if (!memcmp(bytes, webp, 4)) { return @"image/webp"; } else if (!memcmp(bytes, ico, 4)) { return @"image/vnd.microsoft.icon"; } else if (!memcmp(bytes, tif_ii, 4) || !memcmp(bytes, tif_mm, 4)) { return @"image/tiff"; } else if (!memcmp(bytes, png, 8)) { return @"image/png"; } else if (!memcmp(bytes, jp2, 12)) { return @"image/jp2"; } return @"application/octet-stream"; // default type } 

El método anterior reconoce los siguientes types de imágenes:

  • image/x-ms-bmp (bmp)
  • image/gif (gif)
  • image/jpeg (jpg, jpeg)
  • image/psd (psd)
  • image/iff (iff)
  • image/webp (webp)
  • image/vnd.microsoft.icon (ico)
  • image/tiff (tif, tiff)
  • image/png (png)
  • image/jp2 (jp2)

Desafortunadamente, no hay una manera simple de get este tipo de información de una instancia de UIImage , porque no se puede acceder a sus datos de bitmap encapsulados.

Si está recuperando la image de una URL, es probable que pueda inspeccionar los encabezados de respuesta HTTP. ¿ Content-Type encabezado Content-Type contiene algo útil? (Me imagino que sería, ya que un browser probablemente sería capaz de mostrar la image correctamente, y solo podría hacerlo si el tipo de contenido estuviera configurado adecuadamente)

Versión Swift3:

 let data: Data = UIImagePNGRepresentation(yourImage)! extension Data { var format: String { let array = [UInt8](self) let ext: String switch (array[0]) { case 0xFF: ext = "jpg" case 0x89: ext = "png" case 0x47: ext = "gif" case 0x49, 0x4D : ext = "tiff" default: ext = "unknown" } return ext } } 

La solución de @Tai Le para Swift 3 es asignar datos completos a la matriz de bytes. Si una image es grande, puede provocar un locking. Esta solución solo asigna un solo byte:

 import Foundation public extension Data { var fileExtension: String { var values = [UInt8](repeating:0, count:1) self.copyBytes(to: &values, count: 1) let ext: String switch (values[0]) { case 0xFF: ext = ".jpg" case 0x89: ext = ".png" case 0x47: ext = ".gif" case 0x49, 0x4D : ext = ".tiff" default: ext = ".png" } return ext } } 

Si realmente le importa a usted, creo que tendrá que examinar el bytestream. Un JPEG comenzará con los bytes FF D8. Un PNG comenzará con 89 50 4E 47 0D 0A 1A 0A. No sé si BMP tiene un encabezado similar, pero no creo que sea muy probable que te encuentres con los de la web en 2010.

¿Pero realmente te importa? ¿No puedes simplemente tratarlo como una image desconocida y dejar que Cocoa Touch haga el trabajo?

Implemente una verificación de firma para cada formatting de image conocido. Aquí hay una function rápida de Objective-C que hace eso para los datos de PNG:

 // Verify that NSData contains PNG data by checking the signature - (BOOL) isPNGData:(NSData*)data { // Verify that the PNG file signature matches static const unsigned char png_sign[8] = {137, 80, 78, 71, 13, 10, 26, 10}; unsigned char sig[8] = {0, 0, 0, 0, 0, 0, 0, 0}; if ([data length] <= 8) { return FALSE; } [data getBytes:&sig length:8]; BOOL same = (memcmp(sig, png_sign, 8) == 0); return same; } 

Hice una biblioteca para verificar el tipo de image de NSData:

https://github.com/sweetmandm/ImageFormatInspector

Una alternativa de respuesta aceptada es comprobar la UTI de la image I/O frameWork con Image image I/O frameWork . Puede lograr el formulario de tipo de image UTI. testing esto:

 CGImageSourceRef imgSrc = CGImageSourceCreateWithData((CFDataRef)data, NULL); NSString *uti = (NSString*)CGImageSourceGetType(imgSrc); NSLog(@"%@",uti); 

Por ejemplo, una UTI de una image GIF es "com.compuserve.gif" y la UTI de una image PNG es "public.png". PERO no puede lograr UTI a partir de la image en la que no se reconoce image I/O frameWork .