从NSData或UIImage中查找图像types
我从第三方提供的URL加载图像。 URL上没有文件扩展名(或文件名)(因为它是一个模糊的URL)。 我可以从这个数据(以NSData的forms),并加载到一个UIImage,并显示它很好。
我想将这些数据保存到一个文件中。 但是,我不知道数据格式是什么(PNG,JPG,BMP)? 我认为它是JPG(因为它是一个来自networking的图像),但有没有一个编程的方式来找出肯定? 我查看过周围的StackOverflow和文档,一直没能find任何东西。
TIA。
编辑:我真的需要文件扩展名? 我坚持到外部存储(亚马逊S3),但考虑到它将始终用于iOS或浏览器的环境中(这两者在解释数据时都没有扩展名,似乎很好),但这可能不是问题。
如果您有图像文件的NSData,那么您可以通过查看第一个字节来猜测内容types:
+ (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; }
根据wl。的答案改进,这里有一个更加扩展和精确的方法来预测基于签名的图像的MIMEtypes。 代码很大程度上受到了PHP的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 }
上述方法可识别以下图像types:
-
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)
不幸的是,没有简单的方法从UIImage
实例获取这种信息,因为它的封装的位图数据不能被访问。
如果您从URL中检索图像,那么大概您可以检查HTTP响应标头。 Content-Type
头是否包含有用的东西? (我想可能是因为浏览器可能能够正确显示图像,而且只能这样做,如果内容types被适当地设置)
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 } }
@Tai Le的Swift 3的解决scheme是将整个数据分配到字节数组中。 如果图像大,可能会导致崩溃。 这个解决scheme只分配单个字节:
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 } }
如果真的对你很重要,我相信你必须检查字节stream。 JPEG将以字节FF D8开始。 一个PNG将以89 50 4E 47 0D 0A 1A 0A开始。 我不知道BMP是否有类似的标题,但我不认为你有可能在2010年遇到networking上的那些人。
但这对你真的很重要吗? 你不能把它当作一个未知的形象,让cocoa触摸做这个工作吗?
对每个已知的图像格式执行签名检查。 下面是一个快速的Objective-C函数,可以为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; }
我做了一个库来检查NSData的图像types:
接受的答案的替代scheme是使用image I/O frameWork
检查图像的UTI。 你可以实现图像types的formsUTI。 尝试这个:
CGImageSourceRef imgSrc = CGImageSourceCreateWithData((CFDataRef)data, NULL); NSString *uti = (NSString*)CGImageSourceGetType(imgSrc); NSLog(@"%@",uti);
例如,GIF图像的UTI是“com.compuserve.gif”,而PNG图像的UTI是“public.png”,但是您无法从image I/O frameWork
无法识别的image I/O frameWork
获得UTI。