NSData+ImageContentType
该文件下主要有一个图片文件类型的枚举和两个方法。
- 图片枚举
typedef NS_ENUM(NSInteger, SDImageFormat) {
SDImageFormatUndefined = -1, // 不是图片类型
SDImageFormatJPEG = 0, // JPEG类型图片
SDImageFormatPNG, //PNG类型图片
SDImageFormatGIF, //GIF类型动图
SDImageFormatTIFF, // TIFF类型图片
SDImageFormatWebP, // WebP类型图片
SDImageFormatHEIC //HEIC类型图片
};
我们平常见到的基本是PNG,JPG,JPEG,GiF类型,为此我看了一下这个枚举,怎么没有JPG类型。上网查找才发现,可能是我真的太low了。其实JPEG的文件格式一般有两种文件扩展名.jpg和.jpeg,这两种扩展名的实质是相同的,我们可以把.jpg的文件改名为.jpeg,而对文件本身不会有任何影响。可以看成是两个后缀不改变内容本身,叫法不同而已。
扩展方法1
+ (SDImageFormat)sd_imageFormatForImageData:(nullable NSData *)data {
//没有data则返回未找到图片类型
if (!data) {
return SDImageFormatUndefined;
}
// File signatures table: http://www.garykessler.net/library/file_sigs.html
// uint8_t 是个数据类型,无符号char,占一个字节 8个bit。
uint8_t c;
// 获取data的第一个字节。
[data getBytes:&c length:1];
// 根据第一个字节来判断
switch (c) {
case 0xFF:
return SDImageFormatJPEG;
case 0x89:
return SDImageFormatPNG;
case 0x47:
return SDImageFormatGIF;
case 0x49:
case 0x4D:
return SDImageFormatTIFF;
case 0x52: {
if (data.length >= 12) {
//RIFF....WEBP
NSString *testString = [[NSString alloc] initWithData:[data subdataWithRange:NSMakeRange(0, 12)] encoding:NSASCIIStringEncoding];
if ([testString hasPrefix:@"RIFF"] && [testString hasSuffix:@"WEBP"]) {
return SDImageFormatWebP;
}
}
break;
}
case 0x00: {
if (data.length >= 12) {
//....ftypheic ....ftypheix ....ftyphevc ....ftyphevx
NSString *testString = [[NSString alloc] initWithData:[data subdataWithRange:NSMakeRange(4, 8)] encoding:NSASCIIStringEncoding];
if ([testString isEqualToString:@"ftypheic"]
|| [testString isEqualToString:@"ftypheix"]
|| [testString isEqualToString:@"ftyphevc"]
|| [testString isEqualToString:@"ftyphevx"]) {
return SDImageFormatHEIC;
}
}
break;
}
}
return SDImageFormatUndefined;
}
根据方法名称我们可以知道这个方法的作用就是通过二进制的数据获取图片的contentType。
首先要知道一点,当数据文件都以二级制流的数据传输时,必须有一套定义来规范这个二级制流是什么类型的数据。这就产生了文件头的概念,顾名思义,文件头就在文件的开头位置
看一下图片各类型的文件头。
JPEG (jpg),文件头:FFD8FFE1
PNG (png),文件头:89504E47
GIF (gif),文件头:47494638
TIFF tif;tiff 0x49492A00
TIFF tif;tiff 0x4D4D002A
RAR Archive (rar),文件头:52617221
WebP : 524946462A73010057454250
- (void)getBytes:(void *)buffer length:(NSUInteger)length
这个方法的作用是取出length个字节放入到buffer中。源码中为取出一个字节数据放入到c中,即取出第一个字节作为判断根据。
举个例子
在项目中找一张png图片
UIImage *image = [UIImage imageWithBundle:kBundleName imageName:@"My/grade_privilege"];
NSData *data = UIImagePNGRepresentation(image);
打印一下这个data
<89504e47 0d0a1a0a 0000000d 49484452 0000001e 00000027 08060000 001845f8 c7000000 01735247 4200aece 1ce90000 00097048 59730000 16250000 16250149 5224f000 00001c69 444f5400 00000200 00000000 00001400 00002800 00001400 00001300 0001f42a f3f0cc00 0001c049 44415458 09c495bd 4ec33014 855d10b0 80c4c2d4 2a311212 488cbc03 2c30227e 1e808d15 09c541d9 6042fca9 8f80583a f00eb46f c084441b 419c92be 009dc23d 1017a7b2 4bd408b5 92d5f4e6 9ef3d9d7 d72e6305 3e1b47e9 8c23badb dc97d7ae 885bae90 5d1a9fd9 a0e7b885 77c8416e 01cbd129 3c682f72 11050448 68a40547 0f1a6847 bb5bde72 3fda2710 56561438 9cd78587 c5de10de 4da70956 370043c7 97e7cb42 6e5683f7 dacaf1cb dc5290cc f353b9c6 cfe416de 91e6d5a0 ab33f234 90b4d00f b431240e b9171dfc 2d269f20 9d422ee9 c3218fc6 48bdebc5 b7ba808b f871f5a4 b7a04dad d0232a41 3ef7ba97 2ba23ba3 9866baa7 277221af b0026372 a1605a21 bfcb9c27 31725274 20257ca8 2447c40f 8ca5955c d2583fd2 0abc942f 18b96ecf 8e8ceaca 10a51a8b 63106565 1fec3958 df69ebc1 f32ccde4 f79cfaf2 d0a02f15 ca8ea65a 580226c3 6da395a2 536e5f2d f3a35e21 464771c0 6474dddd a80075f1 85455a3a 0c6fc5c1 e921b07c 52015c04 a5091603 782b0e7d 37011eec 6fcd7bab 5a74a5c3 f0d6c009 c07d15c0 35589a60 31c89a58 35587fa2 e08995ba a94a8d7f 1e4ba54a 870dcd35 a1e394bb 403cd9fe b70b84bc 55651d2f daf90200 00ffffe5 cb5fcf00 00023d49 444154ad 55bf6bd5 401c4f15 05c5828b 4b7d49ae 0a3aa883 54671775 101707d1 b138d459 14412f91 6c0e7690 228576a8 93884307 87fa0f74 50444747 2dcff62e cfa79b93 421b3f9f 34172fe5 12ef491f 1c77f97e 7ee52e77 f78253d9 a7fd71a2 7fa0156c 22553783 5dfed1d3 f8a31f32 b38c1089 ca2ca07f 241b1eda ad6c7ac1 bb6ffc99 557b8b6c ed30806f 068c93fc 65101463 35e1bf07 c518bdfe faea21b3 1a7642aa 1b16a110 897e1a64 c59e0669 a40786ea d98667db 678c13f5 ac414cf2 d727ef7f 1f1f290f e46a795f d85ef46e f7b95eec 0579b929 d0fd72c3 f9cc1e9c 6a23d5df b4f25a0e e0dd1e4c 643b7c7e 4738777c 3f4af5e3 c9445fee c9f5a353 33c53e36 8e592316 4bfdd9a1 9bff7768 f54abd3b eb071c06 e5711bb5 3e91e983 dd33b550 91e5c20a 7887717d cead7adb 8b904b4d 850f262d ebee6198 e6e76b61 aa6e7149 a3647015 47630e9b e42d301e bddf55c3 98b57c8e 9cf24282 c6e8e9d5 9d66a130 b96284f8 6ed72cc8 6b484dad 87979788 2491e6d3 4688f105 97f0b854 219b0ba3 c6d24fbb 38ce1a66 7cd7087b e9e08c4d 3af660e3 04f025e0 bfb65bbe c49acd09 1f0e4e1b 7d2cf37b 36d6398e 53f5c408 c3eceb04 c9a89dc5 3dfb0af5 4d8359fd 66898143 2e351636 cb9ad72f 92eab911 468fd4a5 38d56ff0 bc656a1d fd16b951 a22e1a0e bdbc4249 8268c508 1dfd4fd4 1643a9cf b109a917 f0cc5adb f15af10e c61fc47b 87d147d4 6fbbee6e decdb8b9 66a0f9b0 53472fef 6088bf54 06f5ec7c c57881a9 c62a48bd e6abe552 afb6cdce d7c45a85 5597e60f aa5b4c5e d5538cfb 00000000 49454e44 ae426082>
看第一个字节 89504e47 ,可知,这是一张PNG格式图片。
扩展方法2
+ (nonnull CFStringRef)sd_UTTypeFromSDImageFormat:(SDImageFormat)format;
根据图片格式,返回CFStringRef类型数据。
UIImage+GIF
+ (UIImage *)sd_animatedGIFWithData:(NSData *)data {
if (!data) {
return nil;
}
return [[SDWebImageGIFCoder sharedCoder] decodedImageWithData:data];
}
NSData转UIImage
- (BOOL)isGIF {
return (self.images != nil);
}
判断self.images个数来判断是不是GIF。
UIImage+MultiFormat
类目中添加了一个属性,三个方法。
通过关联对象给image添加图片个数的属性sd_imageLoopCount。
// .h
@property (nonatomic, assign) NSUInteger sd_imageLoopCount;
// .m
- (NSUInteger)sd_imageLoopCount {
// 初始化个数为0
NSUInteger imageLoopCount = 0;
//通过objc_getAssociatedObject获取图片个数。 key 为方法sd_imageLoopCount。
NSNumber *value = objc_getAssociatedObject(self, @selector(sd_imageLoopCount));
if ([value isKindOfClass:[NSNumber class]]) {
imageLoopCount = value.unsignedIntegerValue;
}
return imageLoopCount;
}
- (void)setSd_imageLoopCount:(NSUInteger)sd_imageLoopCount {
NSNumber *value = @(sd_imageLoopCount);
objc_setAssociatedObject(self, @selector(sd_imageLoopCount), value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
// NSData转 UIImage
+ (nullable UIImage *)sd_imageWithData:(nullable NSData *)data {
return [[SDWebImageCodersManager sharedInstance] decodedImageWithData:data];
}
// UIImage转NSData
- (nullable NSData *)sd_imageData {
return [self sd_imageDataAsFormat:SDImageFormatUndefined];
}
// UIImage转NSData
- (nullable NSData *)sd_imageDataAsFormat:(SDImageFormat)imageFormat {
NSData *imageData = nil;
if (self) {
imageData = [[SDWebImageCodersManager sharedInstance] encodedDataWithImage:self format:imageFormat];
}
return imageData;
}
UIImage+WebP
- (NSInteger)sd_webpLoopCount __deprecated_msg("Method deprecated. Use `sd_imageLoopCount` in `UIImage+MultiFormat.h`");
这个方法已经被弃用,现在使用sd_imageLoopCount属性。__deprecated_msg可以用来告诉开发者这个方法已经被弃用了,最好不使用,并可以添加上自己的注释
+ (nullable UIImage *)sd_imageWithWebPData:(nullable NSData *)data {
if (!data) {
return nil;
}
return [[SDWebImageWebPCoder sharedCoder] decodedImageWithData:data];
}
加载WebP类型的图片。
UIImage+ForceDecode
对图片进行转码操作
+ (UIImage *)decodedImageWithImage:(UIImage *)image {
if (!image) {
return nil;
}
NSData *tempData;
return [[SDWebImageCodersManager sharedInstance] decompressedImageWithImage:image data:&tempData options:@{SDWebImageCoderScaleDownLargeImagesKey: @(NO)}];
}
+ (UIImage *)decodedAndScaledDownImageWithImage:(UIImage *)image {
if (!image) {
return nil;
}
NSData *tempData;
return [[SDWebImageCodersManager sharedInstance] decompressedImageWithImage:image data:&tempData options:@{SDWebImageCoderScaleDownLargeImagesKey: @(YES)}];
}
UIView+WebCacheOperation
主要用来对 UIView 的图像下载操作添加、取消和移除
// 取消所有操作,把 operation 添加进 UIView 的关联对象内部
- (void)sd_setImageLoadOperation:(nullable id<SDWebImageOperation>)operation forKey:(nullable NSString *)key {
if (key) {
[self sd_cancelImageLoadOperationWithKey:key];
if (operation) {
SDOperationsDictionary *operationDictionary = [self sd_operationDictionary];
@synchronized (self) {
[operationDictionary setObject:operation forKey:key];
}
}
}
}
// 取消正在进行的下载队列,取消当前的所有操作。
- (void)sd_cancelImageLoadOperationWithKey:(nullable NSString *)key {
// 获取SDWebImageOperation对象
SDOperationsDictionary *operationDictionary = [self sd_operationDictionary];
id<SDWebImageOperation> operation;
@synchronized (self) {
operation = [operationDictionary objectForKey:key];
}
// 检查SDWebImageOperation 对象是否实现了 SDWebImageOperation协议方法 ,如果有则取消对象
if (operation) {
if ([operation conformsToProtocol:@protocol(SDWebImageOperation)]){
[operation cancel];
}
// 移除根据key移除map中的value
@synchronized (self) {
[operationDictionary removeObjectForKey:key];
}
}
}
// 移除关联对象中key对应的value
- (void)sd_removeImageLoadOperationWithKey:(nullable NSString *)key {
if (key) {
SDOperationsDictionary *operationDictionary = [self sd_operationDictionary];
@synchronized (self) {
[operationDictionary removeObjectForKey:key];
}
}
}
网友评论