SDWebImage源码解读 之 NSData+ImageContentType

时间:2022-04-06 01:57:09

第一篇

前言

从今天开始,我将开启一段源码解读的旅途了。在这里先暂时不透露具体解读的源码到底是哪些?因为也可能随着解读的进行会更改计划。但能够肯定的是,这一系列之中肯定会有Swift版本的代码。

说说我的目的。想成为一名好的程序员,肯定绕不开模仿这条路。之所以做出这么一个决定,也是想提高自己写框架的能力,逻辑思维能力,扩展知识面。同时也能够给那些想了解这些框架的同学一些基本的解释。何乐而不为呢?

解读方法

对于框架的源码解读,我个人的习惯是先看头文件,先从头文件最简单的开始解读,也就是说首先看不依赖外部文件的类。

这就说明了一个问题,我们在写代码的时候,import头文件也是需要经过慎重考虑的。应该导入什么头文件应该让别的开发者很明白该类具体依赖那些外部文件。

NSData (ImageContentType)

很明显这是一个NSData的分类,我们都知道分类一般是用来扩展一些方法的。我们看看它扩展了什么方法?

/**
* Compute the content type for an image data
*
* @param data the input data
*
* @return the content type as string (i.e. image/jpeg, image/gif)
*/
+ (NSString *)sd_contentTypeForImageData:(NSData *)data;

好,看这个方法,就应该明白了,目的是根据二进制的数据获取图片的contentType。因此,我们在这里就要插入一段contentType的介绍了。

文件头

文件头是位于文件开头的一段承担一定任务的数据,一般都在开头的部分。

别看这个文件头和C语言中的头文件读起来很像,但这两个东西其实根本没有一点关系:头文件是一种包含功能函数,数据接口声明的载体文件;而文件头则是直接位于文件中的一段数据,是文件的一部分

说的简单一点就是,当文件都使用二进制流作为传输时,需要制定一套规范,用来区分该文件到底是什么类型的。 文件头有很多个,我们在这里就介绍一些主流的且跟图片相关的文件头。

  1. JPEG (jpg),文件头:FFD8FFE1
  2. PNG (png),文件头:89504E47
  3. GIF (gif),文件头:47494638
  4. TIFF tif;tiff 0x49492A00
  5. TIFF tif;tiff 0x4D4D002A
  6. RAR Archive (rar),文件头:52617221
  7. WebP : 524946462A73010057454250

可以看出来我们通过每个文件头的第一个字节就能判断出是什么类型。但是值得注意的是52开头的。这个要做特别的判断。

WebP这种格式很特别。是由12个字节组成的文件头,我们如果把这些字节通过ASCII编码后会得到下边这样一张表格:

SDWebImage源码解读 之 NSData+ImageContentType

+ (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;
}

现在再看上边方法的实现,我们就明白了。其中jpeg/png/gif/tiff 是最好判断的。当第一个字节为52时,如果长度<12 我们就认定为不是图片。因此返回nil。我们通过数据截取后获得testString,如果testString头部包含RIFF且尾部也包含WEBP,那么就认定该图片格式为webp。

演示

为了更好的演示webp,我们用代码打印出结果来看看。

首先我们获得一个webp图片:google@2x.webp

 NSString *path = [[NSBundle mainBundle] pathForResource:@"google@2x" ofType:@"webp"];
NSData *data = [NSData dataWithContentsOfFile:path];
NSString *contentType = [NSData sd_contentTypeForImageData:data];
NSLog(@"-----%@------%@", contentType, data);

我们看下打印结果:

-----image/webp------<52494646 72370000 57454250 56503858 0a000000 10000000 190200bd 0000414c 50484711 00000187 40906d33 83cd9ff7 778888a4 b3e53068 db4650c2 9f747a77 ff1822fa 9f927ff8 9224460e c3301c46 86216224 932431e6 1f5edfb6 6dd76d6c db56c195 20884bfb ffaf959d c214d01a 39e6f521 a2ffe95b b6edbaad 6ddb2a20 c03b40e4 ffffdade fbb0500b 2ddb2146 8c8788fe a7feff26 7ecae76a 9f2e77a3 fd9ce513 3ffc8fdd a7d286ec b65aa2d3 b3f6c735 44ef3ad6 ac879cce 21fafd58 929e6eac 53ccce25 e9c33bb8 d779b52f 438ccf59 9fdcc1bd ee7871ac f284be4f fad40eee 75c77b63 93b5d1ca 27de1de5 6c4376cf a28fece0 5e77bc36 3659b94a 64311e75 c8562dfa bc0eee75 c75b4393 efb32636 c3d165a7 167d5807 f7bae3a5 aecaf72b a1e28f21 1bb5e893 3ab8d71d 2f5da67c 9ba7472f 36d93892 3ea6a58e 30a6e39d 53e56b71

其中52494646 72370000 57454250正好占用了12字节。那么也正好符合了我们上边解释的webp文件头。

NSData (ImageContentTypeDeprecated)

这个分类有一个东西值得我们学习。

+ (NSString *)contentTypeForImageData:(NSData *)data __deprecated_msg("Use `sd_contentTypeForImageData:`");

这个__deprecated_msg可以告诉开发者该方法不建议使用。这就有使用场景了。当我们在写框架或者类的时候,如果功能相同,但是想使用心得方法名的时候,使用__deprecated_msg给予其他开发者一个提示。这远远比我们直接删除旧的更专业。

总结

这是SDWebImage源码解读的第一篇,我们解读的目的是发现代码中我们不知道的细节和知识。尽可能的想象出使用场景。在解读完之后,需要做一个所有知识点的总结。我们应该尽量去揣摩作者驾驭代码的思想。也许当我们抓住这些知识点并使用时,我们写出的代码跟别人就有了不同的感觉。

SDWebImage源码解读 之 NSData+ImageContentType的更多相关文章

  1. SDWebImage源码解读之SDWebImageDownloaderOperation

    第七篇 前言 本篇文章主要讲解下载操作的相关知识,SDWebImageDownloaderOperation的主要任务是把一张图片从服务器下载到内存中.下载数据并不难,如何对下载这一系列的任务进行设计 ...

  2. SDWebImage源码解读 之 UIImage&plus;GIF

    第二篇 前言 本篇是和GIF相关的一个UIImage的分类.主要提供了三个方法: + (UIImage *)sd_animatedGIFNamed:(NSString *)name ----- 根据名 ...

  3. SDWebImage源码解读 之 SDWebImageCompat

    第三篇 前言 本篇主要解读SDWebImage的配置文件.正如compat的定义,该配置文件主要是兼容Apple的其他设备.也许我们真实的开发平台只有一个,但考虑各个平台的兼容性,对于框架有着很重要的 ...

  4. SDWebImage源码解读&lowbar;之SDWebImageDecoder

    第四篇 前言 首先,我们要弄明白一个问题? 为什么要对UIImage进行解码呢?难道不能直接使用吗? 其实不解码也是可以使用的,假如说我们通过imageNamed:来加载image,系统默认会在主线程 ...

  5. SDWebImage源码解读之SDWebImageCache&lpar;上&rpar;

    第五篇 前言 本篇主要讲解图片缓存类的知识,虽然只涉及了图片方面的缓存的设计,但思想同样适用于别的方面的设计.在架构上来说,缓存算是存储设计的一部分.我们把各种不同的存储内容按照功能进行切割后,图片缓 ...

  6. SDWebImage源码解读之SDWebImageCache&lpar;下&rpar;

    第六篇 前言 我们在SDWebImageCache(上)中了解了这个缓存类大概的功能是什么?那么接下来就要看看这些功能是如何实现的? 再次强调,不管是图片的缓存还是其他各种不同形式的缓存,在原理上都极 ...

  7. SDWebImage源码解读之SDWebImageDownloader

    SDWebImage源码解读之SDWebImageDownloader 第八篇 前言 SDWebImageDownloader这个类非常简单,作者的设计思路也很清晰,但是我想在这说点题外话. 如果有人 ...

  8. SDWebImage源码解读之SDWebImageManager

    第九篇 前言 SDWebImageManager是SDWebImage中最核心的类了,但是源代码确是非常简单的.之所以能做到这一点,都归功于功能的良好分类. 有了SDWebImageManager这个 ...

  9. SDWebImage源码解读之SDWebImagePrefetcher

    > 第十篇 ## 前言 我们先看看`SDWebImage`主文件的组成模块: ![](http://images2015.cnblogs.com/blog/637318/201701/63731 ...

随机推荐

  1. 5805 NanoApe Loves Sequence(想法题)

    传送门 NanoApe Loves Sequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/131072 K ( ...

  2. kafka0&period;9&period;0及0&period;10&period;0配置属性

    问题导读1.borker包含哪些属性?2.Producer包含哪些属性?3.Consumer如何配置?borker(0.9.0及0.10.0)配置Kafka日志本身是由多个日志段组成(log segm ...

  3. 《Head First Java》——认识变量

    对象的引用 Book b = new Book(); Book c = new Book(); Book d = c;                   // 声明新的Book引用变量,但不创建新的 ...

  4. centos nc命令安装

    yum install nc.x86_64 nc命令的参数 参数 作用-i 设置数据报传送时间间隔-l 以服务器方式运行-k 重复接收并处理某个端口上的所有连接,必须与-l选项一起使用-n 使用ip地 ...

  5. Myeclipse常用快捷键

    转自:http://zjxbw.blog.51cto.com/2808787/543792 Ctrl+Shift+L    显示所有快捷键 Ctrl+K      参照选中的词(Word)快速定位到下 ...

  6. 【翻译】hololens入门

      欢迎!我们很高兴您发现这里并做好了全息投影奇幻之旅的准备.本页面的全部内容都经由我们的工程师团队精心打造,因此这会让人觉得本页面是由软件工程师制作(别忘了,我们是全息投影技术的缔造者,而不是网页制 ...

  7. typedef 类型重命名 和 &num;define 宏定义&lpar;1&rpar;

    http://www.blogjava.net/jasmine214--love/archive/2010/11/29/339307.html 在现实生活中,信息的概念可能是长度,数量和面积等.在C语 ...

  8. &lbrack;WebStrom&rsqb; Change default cmd to Cygwin

    GO to setting, search Terminal: Change shell path : C:\cygwin\bin\bash.exe --login -i    (to the loc ...

  9. j2ee分布式架构 dubbo &plus; springmvc &plus; mybatis &plus; ehcache &plus; redis 分布式架构

    介绍 <modules>        <!-- jeesz 工具jar -->        <module>jeesz-utils</module> ...

  10. 网络数据传输安全及SSH与HTTPS工作原理

    本节内容 网络数据传输安全概述 数据加密算法分类 SSH工作原理 HTTPS工作原理 参考资料 个人一直在努力推动git在公司内部的普及和使用,前些日子在公司内部做了一次分享课,给大家介绍了下项目发布 ...