引言:GIF图像格式是常见的一种动态图片格式,无论是在Web端还是在移动端都经常遇到,但是考虑目前iOS还无法原生展现GIF图片,而对于GIF的原生支持暂时也没有像JPG、PNG等图像格式支持得这么全面,因此本文从图片的合成与分解角度来为大家讲解GIF的知识,结合ImageIO框架可以更方便地实现GIF图片的合成与分解。
本文选自《iOS动画——核心技术与案例实战》。
GIF在iOS中的使用场景
GIF在iOS中的使用场景有以下三个方面。
(1)GIF图片分解为单帧图片。
(2)一系列单帧图片合成GIF图片。
(3)iOS系统上展示GIF动画效果。
在GIF的合成和分解方面将会接触到iOS图像处理核心框架ImageIO,作为iOS系统中图像处理的核心框架,它为我们提供了各种丰富的API,本文将要实现的GIF分解与合成功能,通过ImageIO就可以很方便地实现。GIF动画展示效果将结合UIImageView和定时器,利用逐帧展示的方式为大家呈现GIF动画效果。
GIF分解单帧图片
1 GIF图片分解过程
GIF分解为单帧图片的过程如下。
整个过程划分为5个模块、4个过程,分别如下。
(1)本地读取GIF图片,将其转换为NSdata数据类型。
(2)将NSData作为ImageIO模块的输入。
(3)获取ImageIO的输出数据:UIImage。
(4)将获取到的UIImage数据存储为JPG或者PNG格式保存到本地。
在整个GIF图片分解的过程中,ImageIO是处理过程的核心部分。它负责对GIF文件格式进行解析,并将解析之后的数据转换为一帧帧图片输出。幸运的是我们并不是“轮子”的创造者,而是只要使用轮子即可。所以在本书中我们不去研究GIF分解合成算法的具体实现方式,而是将注意力聚焦在如何使用ImageIO框架实现需要的功能上。
2 GIF图片分解代码实现
在正式分析代码之前,先来看看整个工程的文件结构,如图。
源文件使用的是plane.gif文件。ViewController.swift文件中的viewDidLoad()方法中包含了GIF图片分解为单帧图片并保存到本地的所有代码。下面就结合“GIF分解为单帧图片的过程”来实现这一功能。
功能模块一:读取GIF文件并将之转换为NSdata类型。
1 let gifPath:NSString = Bundle.main.path(forResource: "plane", ofType: "gif")! as NSString
2 let gifData:Data = try! Data(contentsOf: URL(fileURLWithPath: gifPath as String))
代码第1行通过path方法获取文件名为plane、文件格式为gif的文件地址。第2行获取文件信息并加载到gifData(NSData类型)变量中。至此已经完成整个处理流程的第一个环节。
功能模块二:利用ImageIO框架,遍历所有GIF子帧。需要注意的是使用ImageIO必须把读取到的NSdata数据转换为ImageIO可以处理的数据类型,这里使用CGImageSourceRef实现。其相应功能模块的处理流程如下所示。
1 let gifDataSource:CGImageSource =
CGImageSourceCreateWithData(gifData as CFData, nil)!
2 let gifImageCount:Int = CGImageSourceGetCount(gifDataSource)
3 for i in 0...gifImageCount-1{
let imageref:CGImage? =CGImageSourceCreateImageAtIndex(gifDataSource, i, nil)
let image:UIImage = UIImage(cgImage: imageref!,scale:UIScreen.main.scale,orientation:UIImageOrientation.up )
}
下面是GIF数据处理流程中ImageIO部分功能描述。代码第1行实现将GIF原始数据类型NSdata转换为ImageIO可以直接处理的数据类型CGImageSourceRef。第2行获取当前GIF图片的分帧个数。我们知道GIF图片都是由一帧帧图片组成的,那么这一行就是为了获取构成GIF图片的张数。第3行对CGImageSource数据按照图片的序号进行遍历,将遍历出的结果使用UIImage系统方法将之转换为UIImage。
这里重点为大家介绍两种方法。
CGImageSourceCreateImageAtIndex方法的作用是返回GIF中其中某一帧图像的CGImage类型数据。该方法有三个参数,参数1为GIF原始数据,参数2 为GIF子帧中的序号(该序号从0开始),参数3为GIF数据提取的一些选择参数,因为这里不是很常用,所以设置为nil。
public func CGImageSourceCreateImageAtIndex(_ isrc: CGImageSource, _ index: Int, _ options: CFDictionary?) -> CGImage?
以下为UIImage类的方法,这个方法用于实例化UIImage实例对象。该方法有三个参数,参数1为需要构建UIImage的内容,注意这里的内容是CGImage类型,参数2为手机物理像素与手机和手机显示分辨率的换算系数,参数3表明构建的UIImage的图像方向。通过这个方法就可以在某种手机分辨率下构建指定方向的图像,当然图像的类型是UIImage类型。
public init(CGImage cgImage: CGImage, scale: CGFloat, orientation: UIImageOrientation)
通过上述两步已经获取了UIImage,然而UIImage并不是通常我们看到的图像格式,此图像格式最大的特点是无法存储为本地可以查看的图片格式,因此如果需要将图像保存在本地,就需要在这之前将已经得到的UIImage数据类型转换为PNG或者JPG类型的图像数据,然后才能把图像存储到本地。
下面是完整的GIF图像分解保存代码:
override func viewDidLoad() {
1 super.viewDidLoad()
2 let gifPath:NSString = Bundle.main.path(forResource:"plane", ofType: "gif")! as NSString
3 let gifData:Data = try! Data(contentsOf:URL(fileURLWithPath: gifPath as String))
4 let gifDataSource:CGImageSource =CGImageSourceCreateWithData(gifData as CFData, nil)!
5 let gifImageCount:Int =CGImageSourceGetCount(gifDataSource)
6 for i in 0...gifImageCount-1{
7 let imageref:CGImage? =CGImageSourceCreateImageAtIndex(gifDataSource, i, nil)
8 let image:UIImage = UIImage(cgImage: imageref!,scale:UIScreen.main.scale,orientation:UIImageOrientation.up )
9 let imageData:Data = UIImagePNGRepresentation(image)!
10 var docs=NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
11 let documentsDirectory = docs[0] as String
12 let imagePath = documentsDirectory+"/\(i)"+".png"
13 try? imageData .write(to: URL(fileURLWithPath:imagePath), options: [.atomic])
14 print("\(imagePath)")
}
}
代码第1行使用UIImagePNGRepresentation方法将UIImage数据类型存储为PNG格式的data数据类型,第2行代码和第3行代码获取应用的Document目录,第4行调用write方法将图片写入到本地文件中。如果大家想查看最终写入的效果,可以在最后一行添加print信息,将文件写入路径打印出来,观察图像写入是否成功。
3 GIF图片分解最终实现效果
通过上述代码中的最后一行print(“(imagePath)”)可以获取图片最终保存的路径。进入该路径下可以看到下图所示的图片最终分解结果。
根据上下图,在Mac系统下,利用系统图片的查看工具来查看GIF图片的分帧结果,对比图中内容,可以看出GIF图片分解的结果是正确的。
序列图像合成GIF图像
1 GIF图片合成思路
多帧图像合成GIF的过程和GIF分解多帧图像的过程互逆,GIF图片分解过程倒过来推,就是GIF图像合成的过程。这里将上面分解的67张序列单帧图像作为需要处理的输入源进行讲述。
从功能上来说,GIF图片的合成分为以下三个主要部分。
(1)加载待处理的67张原始数据源。
(2)在Document目录下构建GIF文件。
(3)设置GIF文件属性,利用ImageIO编码GIF文件。
2 GIF图片合成代码实现
如下代码是根据GIF构建的三个主要步骤进行编写的。第一部分代码的功能是将67张PNG图片读取到NSMutableArray数组中。代码第1行初始化可变数组,第2行遍历67张本地图片,第3行按照图片的命名规律,构建67张图片名称,第4行加载本地图片。最后一行将读取的图片依次加载到images可变数组中。
// Part1:读取67张png图片
1 let images:NSMutableArray = NSMutableArray()
2 for i in 0...66{// 遍历本地67张图片
3 let imagePath = "\(i).png" // 构建图片名称
4 let image:UIImage = UIImage(named: imagePath)!//
5 images.addObject(image)// 将图片添加到数组中}
代码第二部分的功能是构建在Document目录下的GIF文件路径。具体实现如下所示。
// Part2:在Document目录创建gif文件
1 var docs=NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
2 let documentsDirectory = docs[0] as String
3 let gifPath = documentsDirectory+"/plane.gif"
4 print("\(gifPath)")
5 let url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, gifPath as CFString!,CFURLPathStyle.cfurlposixPathStyle, false)
6 let destion = CGImageDestinationCreateWithURL(url!, kUTTypeGIF, images.count, nil)
代码1一行和第2行获取Document路径地址,第3行代码通过字符串拼接时组成完整的Document路径下plane.gif文件路径。为了方便查看GIF文件所在路径,第4行代码将GIF文件路径打印出来。第5行代码将plane.gif文件路径由string类型转换为URL类型。最后一行代码是ImageIO中构建GIF图片非常重要的方法,我们重点来分析该方法的作用和功能。
public func CGImageDestinationCreateWithURL(_ url: CFURL, _ type: CFString, _ count: Int, _ options: CFDictionary?) -> CGImageDestination?
CGImageDestinationCreateWithURL方法的作用是创建一个图片的目标对象,为了便于大家理解,这里把图片目标对象比喻为一个集合体。
CGImageDestination结构
集合体中描述了构成当前图片目标对象的一系列参数,如图片的URL地址、图片类型、图片帧数、配置参数等。本代码中将plane.gif的本地文件路径作为参数1传递给这个图片目标对象,参数2描述了图片的类型为GIF图片,参数3表明当前GIF图片构成的帧数,参数4暂时给它一个空值。
到目前为止,待处理图片源已经加载到代码中,GIF图片Destination也已经完成构建,下面就需要使用ImageIO框架把多帧PNG图片编码到GIF图片中,其处理流程如下。
具体实现代码如下:
// Part3:设置gif图片属性,利用67张png图片构建gif
1 let cgimagePropertiesDic = [kCGImagePropertyGIFDelayTime as String:0.1]//设置每帧之间播放时间
2 let cgimagePropertiesDestDic =[kCGImagePropertyGIFDictionary as String:cgimagePropertiesDic];
3 for cgimage in images{
4 CGImageDestinationAddImage(destion!, (cgimage as AnyObject).cgImage!!,cgimagePropertiesDestDic as CFDictionary?);}// 依次为gif图像对象添加每一帧元素
5 let gifPropertiesDic:NSMutableDictionary =NSMutableDictionary()
6 gifPropertiesDic.setValue(kCGImagePropertyColorModelRGB,forKey: kCGImagePropertyColorModel as String)
7 gifPropertiesDic.setValue(16, forKey:kCGImagePropertyDepth as String)// 设置图像的颜色深度
8 gifPropertiesDic.setValue(1, forKey:kCGImagePropertyGIFLoopCount as String)// 设置Gif执行次数
9 let gifDictionaryDestDic = [kCGImagePropertyGIFDictionary as String:gifPropertiesDic]
10 CGImageDestinationSetProperties(destion!,gifDictionaryDestDic as CFDictionary?);//为gif图像设置属性
11 CGImageDestinationFinalize(destion!);
代码第1行设置GIF图片属性,设置当前GIF中每帧图片展示时间间隔为0.1s。代码第2行构建一个GIF图片属性字典,字典使用GIF每帧之间的时间间隔初始化。代码第4行使用遍历的方法将已经准备好的图片快速追加到GIF图片的Destination中。代码第5行初始化一个可变字典对象,该字典对象主要用于设置GIF图片中每帧图片属性。第6行设置图片彩色空间格式为RGB(Red Green Blue三基色)类型。第7行设置图片颜色深度。一般来说黑白图像也称为二值图像,颜色深度为1,表示2的一次方,即两种颜色:黑和白。灰度图像一般颜色深度为8,表示2的8次方,共计256种颜色,即从黑色到白色的渐变过程有256种。对于彩色图片来说一般有16位深度和32位深度之说,这里设置为16位深度彩色图片。代码第8行设置GIF图片执行的次数,这里设置为执行一次。代码第9行和第10行负责将以上图片设置的各种属性添加到GIF的Destination目标中。最后一行完成GIF的Destination目标文件构建。
可以打印出当前GIF图片的路径,在该路径下可以看到最终生成的GIF图片。
Gif图像展示
iOS原生并不支持直接显示GIF图片,由前面的分析可知,GIF图片由一帧帧的单帧图片构成,所以只要实现GIF图片的分解,接下来就是多组图片显示的问题了。为大家介绍另外一种图片展现形式,即基于UIImageView展现GIF多帧图片。
经过对GIF图片展示思路的分析可以知道,在iOS下展现GIF分为两步:第一步分解GIF图片为单帧图片,第二步在iOS下展现多帧图片。UIImageView是一个用来展现图片的UI组件,不过它还有一些动画属性可以用来进行逐帧动画展现。
考虑到第一步GIF图片已经分解,所以这里把分解之后的67张图片先加载进来。
UIImageView多帧图像展示具体实现代码如下。
1 var images:[UIImage] = []
2 for i in 0...66{// 遍历本地67张图片
3 let imagePath = "\(i).png" // 构建图片名称
4 let image:UIImage = UIImage(named: imagePath)!
5 images.append(image)// 将图片添加到数组中
}
6 let imageView = UIImageView()
7 imageView.frame = self.view.bounds
8 imageView.contentMode = UIViewContentMode.Center
9 self.view.addSubview(imageView)
10 imageView.animationImages = images
11 imageView.animationDuration = 5
12 imageView.animationRepeatCount = 1
13 imageView.startAnimating()
代码第1行初始化一个子元素为UIImage类型的数组对象。第2行到第5行通过for循环将67张图片依次加载到当前数组中。第6行实例化一个UIImageView实例对象。第7行和第8行设置UIImageView实例对象的frame位置属性以及图片的拉伸方式,这里设置为居中显示。第9行将UIImageView添加到self.view图层上。第10行将初始化加载的67张图片添加到UIImageView实例的animationImages上,相当于设置UIImageView的内容。第11行设置UIImageView图片动画播放周期。第12行设置动画重复次数。最后一行启动UIImageView多帧图片展示动画。
本文选自《iOS动画——核心技术与案例实战》,点此链接可在博文视点官网查看此书。
相关推荐
本篇将详细介绍如何在iOS应用中实现GIF动画的显示。 一、GIF格式介绍 GIF(Graphics Interchange Format)是一种无损压缩的图像文件格式,支持透明度和多帧动画。与静态图片格式JPEG和PNG相比,GIF特别适合存储简单...
本文将详细讲解如何在iOS应用中实现GIF动画的播放,并以“AnimatedGifExample”为例,阐述相关的编程知识点。 首先,我们需要了解GIF图片格式。GIF是一种支持动画的位图格式,通过在单个文件中存储一系列连续的图像...
UIKit提供了UIImageView、UIView等类,通过它们可以实现静态图片的展示以及简单的动画效果。然而,原生的UIImageView并不支持直接播放GIF。 3. **第三方库的使用**: 由于原生UIKit不支持GIF播放,开发者通常会...
demo实现了iOS中6种动画效果的实现。 直线动画效果、爆炸点赞动画效果、心跳(放大缩小)动画效果、上下浮动效果、图片序列gif效果和直线+Gif效果。 博客地址为:...
通过解析gif数据并逐帧绘制,可以实现更复杂的动画效果。 5. 性能优化:由于gif动画可能会消耗大量内存和CPU资源,所以在处理大量或高分辨率的gif时需要注意性能优化。可以考虑预加载策略、降低图像质量或者使用更...
GIF是一种支持多帧的图像格式,通过连续播放一系列帧来实现动画效果。在iOS中,系统默认并不支持直接显示GIF动画,所以我们需要自定义解决方案。 一种常见方法是使用第三方库,如`FLAnimatedImage`。`...
IOS中利用UIImageView控件实现gif图片动画显示,借助ImageIO接口达到gif图片拆分效果,然后使用UIImageView动画接口播放一组图片达到动画效果; 最后将单个gif图片动画播放接口封装成UIView类,达到多个gif图片错开...
下面我们将详细探讨如何在iOS中实现启动图加载GIF动画。 首先,我们需要理解GIF图片格式。GIF是一种支持多帧图像的文件格式,通过连续播放这些帧,可以创建出动画效果。在iOS平台上,我们可以使用第三方库来处理和...
合成的GIF可以在模拟器或真机上进行测试,确保动画效果正确且流畅。如果遇到问题,如图片显示不完整或动画速度不正确,需要检查帧的顺序、时间间隔以及编码过程。 通过以上步骤和知识点,开发者能够在iOS应用中...
在iOS开发中,实现Gif动画的播放是一个常见的需求,特别是在多媒体应用中。Gif是一种支持多帧图像的格式,可以用来创建简单的动画效果。在本教程中,我们将重点讨论如何使用Swift语言来处理和播放Gif动画。我们将...
在移动应用和网页开发中,GIF...开发者需要根据项目需求和目标平台,选择最佳方案,并进行细致的优化,以实现流畅、高效的GIF动画展示。通过不断学习和实践,你可以更好地掌握这一技能,为用户提供更优质的互动体验。
它能够识别GIF格式,并将GIF转换为一系列静态帧,从而实现动画效果。 6. **UIButton+WebCache分类**:同样扩展了UIButton,使其也能利用`SDWebImage`加载网络图片。 7. **SDWebImagePrefetcher**:预加载图片工具...
6. **跨平台兼容**:由于“GIF动画全操作支持库”可能是一个跨平台的库,因此它可以应用于多种操作系统,如Windows、Linux、macOS等,也可能支持移动平台如Android和iOS。 7. **API接口**:提供清晰、简洁的编程...
这为跨平台开发提供了便利,无论是在Windows、Linux还是Mac OS,或者是Android、iOS等移动系统,都能实现一致的GIF动画展示效果。 控件的核心特性可能包括: 1. **高效解码**:优化的算法使得GIF文件能快速高效...
本教程将详细讲解如何在iOS应用中完美实现GIF动画。 首先,我们要了解GIF图片的特性。GIF是一种支持透明度和循环播放的动画格式,由一系列帧组成,每帧可以有不同的持续时间,通过连续播放这些帧来形成动画效果。在...
在iOS开发中,显示GIF动态图是一项常见的需求,特别是在社交、游戏以及各种有动画效果的应用中。然而,iOS的原生UIKit并不直接支持GIF的播放,因此我们需要通过一些额外的技术来实现这一功能。本篇文章将详细讲解...
本资源包提供了一种方法,通过源代码来创建一个动态的UIImages对象,从而实现在iOS应用中播放GIF动画。这个过程涉及到多个知识点,我们将详细探讨。 首先,了解`UIImage`类。`UIImage`是苹果提供的一个核心图像类,...
这个压缩包文件“从GIF动画创建一个动态UIImages 对象”提供了关于如何在iOS应用中实现这一功能的源码示例。接下来,我们将详细讨论如何在iOS应用中创建动态的UIImages对象,以及与之相关的技术点。 首先,我们要...
GIF是一种基于LZW压缩算法的无损图像格式,支持多帧动画,每帧之间可以设置不同的延迟时间,组合起来形成动态效果。 2. **原生UIKit的局限性** iOS的UIKit框架不包含直接处理GIF的API,因此需要借助第三方库来...
苹果的UIKit框架提供了强大的动画支持,开发者可以通过Core Animation或者CAAnimation类来创建各种复杂的动画效果,包括我们这里关注的折叠动画。折叠动画通常用于模拟真实世界中的纸张或物体折叠的过程,使用户界面...