SDWebImage源码解读之获取图片格式

更多原创文章,请访问:https://takioo.cn

首先解释一下涉及到的一些基本概念和方法:

  • 什么是文件头?
  • 如何根据文件头判断图片格式?

1.什么是文件头

我们知道文件有很多类型,那如何判断文件究竟是属于哪种类型,这时候就需要利用文件头携带的信息去进行判断。

文件头:位于文件开头的一段承担一定任务的数据,一般都在开头的部分。
例如,用十六进制编辑器查看一张gif格式的图片的文件头如下(部分数据):

<47494638 39619001 2c01f672 007b4f27 866952a6 8839a58e 
55b59d7d cbb439c3 af49e8dc 1ee9de2d faec1feb e026ece1
 ...
965a6ec9 65975e7e 09669862 8e496699 66d21408 003b>

47494638 即为gif图片格式的文件头标识。

2.根据文件头判断图片格式

图片格式 文件头
JPEG (jpg) FFD8FFE1
PNG (png) 89504E47
GIF (gif) 47494638
TIFF(tiff) 49492A00 或 4D4D002A
WebP 524946462A73010057454250

重点来解释一下webp这种特殊格式,它是由是由12个字节组成的文件头,把这些字节通过ASCII编码,我们会得到如下内容:

SDWebImage源码解读之获取图片格式_第1张图片

3.源码解读

先贴下源码:

+ (NSString *)sd_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";
        case 0x52:
            // R as RIFF for WEBP
            if ([data length] < 12) {
                return nil;
            }

            NSString *testString = [[NSString alloc] initWithData:[data subdataWithRange:NSMakeRange(0, 12)] encoding:NSASCIIStringEncoding];
            if ([testString hasPrefix:@"RIFF"] && [testString hasSuffix:@"WEBP"]) {
                return @"image/webp";
            }

            return nil;
    }
    return nil;
}

现在来看源码的话,就简单易懂了。

  1. 获取二进制数据开头一个字节长度的数据(只需比对文件头的第一个字节数据即可)
[data getBytes:&c length:1];
  1. 根据文件头判断图片格式,
    即,如果第一个字节为FF,就可以判断该文件是一张格式为jpeg的图片,依此论推。

  2. 针对webp这种特殊格式,先判断data的字节长度是否 > 12,如果不大于12,说明不是webp格式;
    如果 > 12,进而将十六进制转为文本字符串,如果该字符串开头是RIFF,并且结尾是WEBP,就判定该文件类型为webp格式的图片。

你可能感兴趣的:(iOS)