SDWebImage源码阅读(三)UIImage+GIF
UIImage+GIF 是UIImage 类的一个GIF 分类,在之前的版本里面这个分类是用了处理GIF 动态图片的但是会有内存暴增的bug。在当前 '4.0.0-beta2' 的版本里GIF 动态图片处理放在了UIImage+MultiFormat 这个分类里面,而当前这个GIF 的分类的功能只是将动态图片作为静态图片来处理,如果是静态图片的NSData 数据则转化为静态UIImage 直接返回,如果是动态图片的NSData 数据,则把图像的第1帧图像转换化为静态UIImage 返回。
首先看UIImage+GIF.h 文件:
1 @interface UIImage (GIF) 2 3 /** 4 * Compatibility method - creates an animated UIImage from an NSData, it will only contain the 1st frame image 5 */ 6 + (UIImage *)sd_animatedGIFWithData:(NSData *)data; 7 8 /** 9 * Checks if an UIImage instance is a GIF. Will use the `images` array 10 */ 11 - (BOOL)isGIF; 12 13 @end
定义了一个实例方法和一个类方法:
1 + (UIImage *)sd_animatedGIFWithData:(NSData *)data;
兼容的方法创建一个动画UIImage 从一个NSData,它仅仅只包含第一帧图像。
判断一个UIImage 实例是否是GIF 图片:
1 - (BOOL)isGIF;
1 - (BOOL)isGIF { 2 return (self.images != nil); 3 }
检查一个UIImage 的实例是否是GIF,将使用“images” 数组判断。
UIImage+GIF.m 文件:
主要研究上面类方法的实现。
学习研究之前先做一些拓展:
size_t 类型:
size_t 类型定义在cstddef 头文件中,该文件是C标准库的头文件stddef.h 的C++ 版。它是一个与机器相关的unsigned类型,其大小足以保证存储内存中对象的大小。
例如:bitset 的size 操作返回bitset对象中二进制位中的个数,返回值类型是size_t。
size_t 是标准C库中定义的,应为unsigned int,在64位系统中为 long unsigned int。
使用:
实现方式:
在C++ 中,设计 size_t 就是为了适应多个平台的。size_t 的引入增强了程序在不同平台上的可移植性。
size_t 是针对系统定制的一种数据类型,一般是整型,因为 C/C++ 标准只定义最低的位数,而不是必需的固定位数。而且在内存里,对数的高位对齐存储还是低位对齐存储各系统都不一样。为了提高代码的可移植性,就有必要定义这样的数据类型。一般这种类型都会定义到它具体占几位内存等。当然,有些是编译器或系统已经给定义好的。
经测试发现,在32位系统中size_t是4字节的,而在64位系统中,size_t 是8字节的,这样利用该类型可以增强程序的可移植性。
详细解释:
在编译的过程中size_t类型的a 值会被编译他的补码。所以在使用size_t 类型数据的过程中尤其要注意,特别是在逻辑表达式中使用到该类型,稍不注意可能带来很严重的后果。
注:正数的补码:与原码相同;负数的补码:符号位为1,其余位为该数绝对值的原码按位取反,然后整个数加1。
参考链接:http://blog.csdn.net/JIEJINQUANIL/article/details/50981834
http://jeremybai.github.io/blog/2014/09/10/size-t
http://baike.baidu.com/link?url=WhKafqypjk2GpAfTxbeWLNEQIqW3bjODmV5faNTtZUcPPCn1Y7MDOa05UR4DOstvaVcbGeOXqUcKCRJ6eIz4ba
http://blog.csdn.net/zhanghaotian2011/article/details/7974891
http://www.cnblogs.com/kaituorensheng/p/3239446.html
http://blog.csdn.net/bigloomy/article/details/6563870
下面看 + (UIImage *)sd_animatedGIFWithData:(NSData *)data; 方法实现:
1 + (UIImage *)sd_animatedGIFWithData:(NSData *)data { 2 if (!data) { 3 return nil; 4 } 5 6 CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL); 7 8 size_t count = CGImageSourceGetCount(source); 9 10 UIImage *staticImage; 11 12 if (count <= 1) { 13 staticImage = [[UIImage alloc] initWithData:data]; 14 } else { 15 // we will only retrieve the 1st frame. the full GIF support is available via the FLAnimatedImageView category. 16 // this here is only code to allow drawing animated images as static ones 17 #if SD_WATCH 18 CGFloat scale = 1; 19 scale = [WKInterfaceDevice currentDevice].screenScale; 20 #elif SD_UIKIT 21 CGFloat scale = 1; 22 scale = [UIScreen mainScreen].scale; 23 #endif 24 25 CGImageRef CGImage = CGImageSourceCreateImageAtIndex(source, 0, NULL); 26 #if SD_UIKIT || SD_WATCH 27 UIImage *frameImage = [UIImage imageWithCGImage:CGImage scale:scale orientation:UIImageOrientationUp]; 28 staticImage = [UIImage animatedImageWithImages:@[frameImage] duration:0.0f]; 29 #elif SD_MAC 30 staticImage = [[UIImage alloc] initWithCGImage:CGImage size:NSZeroSize]; 31 #endif 32 CGImageRelease(CGImage); 33 } 34 35 CFRelease(source); 36 37 return staticImage; 38 }
这里主要使用了 ImageIO 框架下的 <ImageIO/CGImageSource.h>,并在 UIImage+GIF.m 文件开始通过 #import <ImageIO/ImageIO.h>,引入ImageIO 框架。
1.判断传入的data 如果是nil 则直接返回nil。
2.使用CGImageSource.h 的:CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL),创建一个CGImageSourceRef 对象source。
1 /* Create an image source reading from `data'. The `options' dictionary 2 * may be used to request additional creation options; see the list of keys 3 * above for more information. */ 4 5 IMAGEIO_EXTERN CGImageSourceRef __nullable CGImageSourceCreateWithData(CFDataRef __nonnull data, CFDictionaryRef __nullable options) IMAGEIO_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_4_0);
3.使用CGImageSource.h 的:CGImageSourceGetCount(source),获得source 里面的图片数量count。
1 /* Return the number of images (not including thumbnails) in the image 2 * source `isrc'. */ 3 4 IMAGEIO_EXTERN size_t CGImageSourceGetCount(CGImageSourceRef __nonnull isrc) IMAGEIO_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_4_0);
4.创建一个UIImage 实例staticImage。(从名字里面能大概猜出创建该实例的用意)
5.如果count 小于等于1,即表示该data 数据是一个静态图片的NSData 数据,则把data 转化为UIImage 并赋值给staticImage。
6.如果count 大于1,即表示该data 数据是一个动态图片的NSData 数据。如果当前是WATCH 平台开发通过:
1 CGFloat scale = 1; 2 scale = [WKInterfaceDevice currentDevice].screenScale;
获取当前设备的screenScale,如果是iOS/TV 平台开发(包含UIKit 框架)通过:
1 CGFloat scale = 1; 2 scale = [UIScreen mainScreen].scale;
获得当前屏幕的scale,并赋值给float 类型的scale 变量,用于控制返回的动态图片的第一帧图像的大小。
7.使用CGImageSource.h 的:CGImageSourceCreateImageAtIndex(source, 0, NULL),获得source 里面index 为0 时的CGImageRef 实例CGImage。
1 /* Return the image at `index' in the image source `isrc'. The index is 2 * zero-based. The `options' dictionary may be used to request additional 3 * creation options; see the list of keys above for more information. */ 4 5 IMAGEIO_EXTERN CGImageRef __nullable CGImageSourceCreateImageAtIndex(CGImageSourceRef __nonnull isrc, size_t index, CFDictionaryRef __nullable options) IMAGEIO_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_4_0);
8.如果是iOS/TV/WATCH 平台开发,根据上面获取的CGImage 和scale 做参数,使用:
1 + (UIImage *)imageWithCGImage:(CGImageRef)cgImage scale:(CGFloat)scale orientation:(UIImageOrientation)orientation NS_AVAILABLE_IOS(4_0);
创建一个UIImage 实例frameImage。
9.把frameImage 放在一个NSArray 里面作参数,使用:
1 + (nullable UIImage *)animatedImageWithImages:(NSArray<UIImage *> *)images duration:(NSTimeInterval)duration NS_AVAILABLE_IOS(5_0);
创建一个images 为一张图片,duration 为0.0f的动态图片并赋值给staticImage。如果是MAC 平台开发,依然CGImage 作参数,使用:
1 [[UIImage alloc] initWithCGImage:CGImage size:NSZeroSize];
创建一个UIImage 实例赋值给staticImage。
10.使用CGImage.h 的CGImageRelease(CGImage) 释放CGImage。
1 /* Equivalent to `CFRelease(image)'. */ 2 3 CG_EXTERN void CGImageRelease(CGImageRef cg_nullable image) 4 CG_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0);
11.使用CFBase.h 的CFRelease(source) 释放source。
1 CF_EXPORT 2 void CFRelease(CFTypeRef cf);
12.返回staticImage。
END
参考链接:http://www.jianshu.com/p/d3e9e3d0a778
转载于:https://www.cnblogs.com/chmhml/p/6797045.html
SDWebImage源码阅读(三)UIImage+GIF相关推荐
- 24 UsageEnvironment使用环境抽象基类——Live555源码阅读(三)UsageEnvironment
24 UsageEnvironment使用环境抽象基类--Live555源码阅读(三)UsageEnvironment 24 UsageEnvironment使用环境抽象基类--Live555源码阅读 ...
- mybatis源码阅读(三):mybatis初始化(下)mapper解析
转载自 mybatis源码阅读(三):mybatis初始化(下)mapper解析 MyBatis 的真正强大在于它的映射语句,也是它的魔力所在.由于它的异常强大,映射器的 XML 文件就显得相对简单. ...
- SDWebImage源码阅读(九)SDWebImageDownloader
这篇学习 SDWebImageDownloader 这个类. 首先依然是看 SDWebImageDownloader.h: SDWebImageDownloaderOptions 1 typedef ...
- Struts2源码阅读(三)_DispatcherConfigurationProvider
首先强调一下struts2的线程程安全,在Struts2中大量采用ThreadLocal线程局部变量的方法来保证线程的安全,像Dispatcher等都是通过ThreadLocal来保存变量值,使得每个 ...
- SpringMVC源码阅读(三)
先理一下Bean的初始化路线 org.springframework.beans.factory.support.AbstractBeanDefinitionReader public int loa ...
- 源码阅读:SDWebImage(十九)——UIImage+ForceDecode/UIImage+GIF/UIImage+MultiFormat
该文章阅读的SDWebImage的版本为4.3.3. 由于这几个分类都是UIImage的分类,并且内容相对较少,就写在一篇文章中. 1.UIImage+ForceDecode 这个分类为UIImage ...
- 源码阅读:SDWebImage(六)——SDWebImageCoderHelper
该文章阅读的SDWebImage的版本为4.3.3. 这个类提供了四个方法,这四个方法可分为两类,一类是动图处理,一类是图像方向处理. 1.私有函数 先来看一下这个类里的两个函数 /**这个函数是计算 ...
- 源码阅读:SDWebImage(五)——SDWebImageFrame
该文章阅读的SDWebImage的版本为4.3.3. 根据SDWebImage作者的描述,这个类是用来帮助创建动图的. 1.接口文件 属性 /**当前帧的图像*/ @property (nonatom ...
- 源码阅读:SDWebImage(二十)——UIButton+WebCache
该文章阅读的SDWebImage的版本为4.3.3. 这个分类提供了为UIButton设置网络图像的快捷方法. 1.公共方法 1.1.设置image的方法 /**获取当前图像链接地址*/ - (nul ...
最新文章
- 知乎 高级操作系统_知乎高赞:Linux!为何他一人就写出这么强的系统,中国却做不出来?...
- malloc 和alloc及calloc的区别
- 什么是 SAP C/4HANA Foundation
- promehteus 监控超时_05 . Prometheus监控Nginx
- Visual Studio 清单(manifest)导致的问题
- STM32的2.02固件库提供的启动文件详解 stm32f10x_vector.s
- python3文档字符串_python3基础:字符串、文本文件
- ArcGIS 道路线数据处理与拓扑操作
- LC.234.Palindrome Linked List
- java多线程编程--模拟龟兔赛跑过程
- Abaqus有限元分析软件介绍
- 网页页面缩小放大的快捷键
- 大司、小司、外包公司
- python求单词长度_python 统计单词平均长度,统计a出现的次数
- 新显卡出世,谈谈与深度学习有关的显卡架构和相关技术
- 一.正则表达式转换为有限状态自动机:正则表达式转NFA
- 30系显卡安装tensorflow-gpu1.15
- 抢先看! Lumion 10 正式发布之核心功能预览
- 基于STM32F4的智能门锁系统
- 服务器怎么使用无线网卡,无线上网卡怎么用
热门文章
- 日志服务接入方式之Unity 3D篇
- LINUX_egrep及扩展正则表达式
- sql2005/sql2000 向表中循环插入100万条记录
- 【联盟】三星大容量MLC FLASH 换代信息(小心现在自己计划的产品哦)
- 大山深处,有一所希望学校
- 经验之谈——送给年轻的职场人
- Fully decentralized NFT system towards Metaverse: Next generation Seatlab business model
- 为什么一定要好好睡觉?
- 剑桥大学eap入学测试准备!!!救命稻草
- 虚拟打印机开发日志(一):使用x64 WIN7编译环境编译的完整步骤