SDWebImage源码解读 之 NSData+ImageContentType
第一篇
前言
从今天开始,我将开启一段源码解读的旅途了。在这里先暂时不透露具体解读的源码到底是哪些?因为也可能随着解读的进行会更改计划。但能够肯定的是,这一系列之中肯定会有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语言中的头文件读起来很像,但这两个东西其实根本没有一点关系:头文件是一种包含功能函数,数据接口声明的载体文件;而文件头则是直接位于文件中的一段数据,是文件的一部分
说的简单一点就是,当文件都使用二进制流作为传输时,需要制定一套规范,用来区分该文件到底是什么类型的。 文件头有很多个,我们在这里就介绍一些主流的且跟图片相关的文件头。
- JPEG (jpg),文件头:FFD8FFE1
- PNG (png),文件头:89504E47
- GIF (gif),文件头:47494638
- TIFF tif;tiff 0x49492A00
- TIFF tif;tiff 0x4D4D002A
- RAR Archive (rar),文件头:52617221
- WebP : 524946462A73010057454250
可以看出来我们通过每个文件头的第一个字节就能判断出是什么类型。但是值得注意的是52开头的。这个要做特别的判断。
WebP这种格式很特别。是由12个字节组成的文件头,我们如果把这些字节通过ASCII编码后会得到下边这样一张表格:

+ (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的更多相关文章
- SDWebImage源码解读之SDWebImageDownloaderOperation
第七篇 前言 本篇文章主要讲解下载操作的相关知识,SDWebImageDownloaderOperation的主要任务是把一张图片从服务器下载到内存中.下载数据并不难,如何对下载这一系列的任务进行设计 ...
- SDWebImage源码解读 之 UIImage+GIF
第二篇 前言 本篇是和GIF相关的一个UIImage的分类.主要提供了三个方法: + (UIImage *)sd_animatedGIFNamed:(NSString *)name ----- 根据名 ...
- SDWebImage源码解读 之 SDWebImageCompat
第三篇 前言 本篇主要解读SDWebImage的配置文件.正如compat的定义,该配置文件主要是兼容Apple的其他设备.也许我们真实的开发平台只有一个,但考虑各个平台的兼容性,对于框架有着很重要的 ...
- SDWebImage源码解读_之SDWebImageDecoder
第四篇 前言 首先,我们要弄明白一个问题? 为什么要对UIImage进行解码呢?难道不能直接使用吗? 其实不解码也是可以使用的,假如说我们通过imageNamed:来加载image,系统默认会在主线程 ...
- SDWebImage源码解读之SDWebImageCache(上)
第五篇 前言 本篇主要讲解图片缓存类的知识,虽然只涉及了图片方面的缓存的设计,但思想同样适用于别的方面的设计.在架构上来说,缓存算是存储设计的一部分.我们把各种不同的存储内容按照功能进行切割后,图片缓 ...
- SDWebImage源码解读之SDWebImageCache(下)
第六篇 前言 我们在SDWebImageCache(上)中了解了这个缓存类大概的功能是什么?那么接下来就要看看这些功能是如何实现的? 再次强调,不管是图片的缓存还是其他各种不同形式的缓存,在原理上都极 ...
- SDWebImage源码解读之SDWebImageDownloader
SDWebImage源码解读之SDWebImageDownloader 第八篇 前言 SDWebImageDownloader这个类非常简单,作者的设计思路也很清晰,但是我想在这说点题外话. 如果有人 ...
- SDWebImage源码解读之SDWebImageManager
第九篇 前言 SDWebImageManager是SDWebImage中最核心的类了,但是源代码确是非常简单的.之所以能做到这一点,都归功于功能的良好分类. 有了SDWebImageManager这个 ...
- SDWebImage源码解读之SDWebImagePrefetcher
> 第十篇 ## 前言 我们先看看`SDWebImage`主文件的组成模块: -微信公众平台开发-消息处理
系列目录 前言 Senparc.Weixin.MP SDK提供了MessageHandler消息处理类 在作者的Wiki中也详细说明了如何定义这个类,下面我们来演示,消息的回复,及效果 了解Messa ...
- 11、Struts2 的文件上传和下载
文件上传 表单准备 要想使用 HTML 表单上传一个或多个文件 须把 HTML 表单的 enctype 属性设置为 multipart/form-data 须把 HTML 表单的method 属性设置 ...
- AFNetworking 3.0 源码解读(七)之 AFAutoPurgingImageCache
这篇我们就要介绍AFAutoPurgingImageCache这个类了.这个类给了我们临时管理图片内存的能力. 前言 假如说我们要写一个通用的网络框架,除了必备的请求数据的方法外,必须提供一个下载器来 ...
- 设计模式之创建类模式大PK
创建类模式大PK 创建类模式包括工厂方法模式.建造者模式.抽象工厂模式.单例模式和原型模式,他们能够提供对象的创建和管理职责.其 ...
- css元素水平居中和垂直居中的方式
关于居中的问题,一直处于疑惑不解的状态,知道的几种方法好像也不是每一次都会起到作用,所以更加迷惑.主要是不清楚该 在什么情况下采用哪种解决方法,所以,整理了一些方法,梳理一下思路,做一个总结. 1. ...
- .NET同步与异步之相关背景知识(六)
在之前的五篇随笔中,已经介绍了.NET 类库中实现并行的常见方式及其基本用法,当然.这些基本用法远远不能覆盖所有,也只能作为一个引子出现在这里.以下是前五篇随笔的目录: .NET 同步与异步之封装成T ...
- 访问者模式(visitorpattern)
/** * 访问者模式 * @author TMAC-J * 在客户端和元素之间添加一个访问者 * 当你需要添加一些和元素关系不大的需求时,可以直接放在访问者里面 * 或者是元素之间有一些公共的代码块 ...
- jquery.each()
$(selector).each(function(index,element)) index - 选择器的 index 位置 element - 当前的元素(也可使用 "this" ...
- 【初码干货】在Window Server 2016中使用Web Deploy方式发布.NET Web应用的重新梳理
在学习和工作的过程中,发现很多同事.朋友,在做.NET Web应用发布的时候,依然在走 生成-复制到服务器 这样的方式,稍微高级一点的,就是先发布到本地,再上传到服务器 这种方式不仅效率低下,而且不易 ...