从NSData或UIImage中查找图像类型

psc*_*ang 65 iphone uiimage persist nsdata ios

我正在从第三方提供的URL加载图像.URL上没有文件扩展名(或文件名)(因为它是一个模糊的URL).我可以从中获取数据(以NSData的形式)并将其加载到UIImage中并显示它.

我想将此数据保存到文件中.但是,我不知道数据的格式是什么(PNG,JPG,BMP)?我认为它是JPG(因为它是来自网络的图像)但是有一种程序化的方法可以找到它吗?我查看了StackOverflow和文档,但未能找到任何内容.

TIA.


编辑:我真的需要文件扩展名吗?我将它持久化到外部存储(Amazon S3),但考虑到它总是在iOS或浏览器的上下文中使用(两者在没有扩展的情况下解释数据似乎都很好)也许这不是问题.

wl.*_*wl. 142

如果您有图像文件的NSData,那么您可以通过查看第一个字节来猜测内容类型:

+ (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;
}
Run Code Online (Sandbox Code Playgroud)

  • 在识别UIImage对象的情况下,这对我没有帮助.要从UIImage中提取NSData,我需要使用UIImagePNGRepresentation()或UIImageJPEGRepresentation()来自动转换imageData. (5认同)
  • 是否有任何等效的解决方案来识别其他类型的文件类型...如rtf,mov,mp3? (4认同)
  • 伟大的技巧人.真有帮助!! 保持良好的工作. (2认同)
  • 有没有人知道pdf,word(doc,docx),excel(xls,xlsx),powerpoint(ppt,pptx),text,rtf等字节. (2认同)

aka*_*kyy 26

改进wl.的答案,这是一种更加扩展和精确的方法来预测基于签名的图像的MIME类型.代码很大程度上受到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

}
Run Code Online (Sandbox Code Playgroud)

上述方法可识别以下图像类型:

  • 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实例获取此类信息,因为无法访问其封装的位图数据.

  • 好的清单,谢谢.我在使用iOS11中使用的新.heic图像类型时遇到了问题.你能否更新你的答案以包含这种新类型? (2认同)

cco*_*oom 11

@Tai Le的Swift 3解决方案是将整个数据分配到字节数组中.如果图像较大,则可能导致崩溃.此解决方案只分配单个字节:

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
    }
}
Run Code Online (Sandbox Code Playgroud)


Dav*_*ong 8

如果您从URL检索图像,那么可能您可以检查HTTP响应标头.Content-Type标题是否包含任何有用的内容?(我想它会因为浏览器可能能够正确显示图像,并且只有在适当设置了内容类型时才能这样做)


ooO*_*lly 6

接受答案的另一种选择是使用 检查图像的 UTI image I/O frameWork。您可以从 UTI 中获取图像类型。尝试这个:

CGImageSourceRef imgSrc = CGImageSourceCreateWithData((CFDataRef)data, NULL);
NSString *uti = (NSString*)CGImageSourceGetType(imgSrc);
NSLog(@"%@",uti);
Run Code Online (Sandbox Code Playgroud)

例如,GIF 图像的 UTI 是“com.compuserve.gif”,PNG 图像的 UTI 是“public.png”。但是您无法从无法image I/O frameWork识别的图像中获取 UTI。


Tai*_* Le 5

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
    }
}
Run Code Online (Sandbox Code Playgroud)