这里只讲ImageIO中CGImageSource常见的三种使用方式,一种是进行图片格式解码读取(包括原始图片和生成缩略图),另一种是获取图片的相关信息(如:定位,拍摄设备,分辨率等),最后一种是渐进式加载。
基本知识
CGImageSource:解码-读取图片数据类
//查看支持解码的type类型
let mySourceTypes : CFArray = CGImageSourceCopyTypeIdentifiers();
print(mySourceTypes);
ps.支持格式过多,我删了一部分日志
(
"public.jpeg",
"public.png",
"com.compuserve.gif",
"com.canon.tif-raw-image",
"com.adobe.raw-image",
"com.dxo.raw-image",
"com.konicaminolta.raw-image",
"com.olympus.sr-raw-image",
"com.microsoft.ico",
"com.microsoft.bmp",
...
"com.apple.icns",
"com.adobe.photoshop-image",
"com.microsoft.cur",
"com.truevision.tga-image",
"com.ilm.openexr-image",
"org.webmproject.webp",
"public.radiance",
"public.pbm",
"public.mpo-image",
"public.pvr",
"com.microsoft.dds"
)
CGImageDestination:编码-写入数据类,写入数据类放在另一篇文章中
//查看支持编码的type类型
let myDestinationTypes : CFArray = CGImageDestinationCopyTypeIdentifiers();
print(myDestinationTypes);
ImageSourceOption 键值
kCGImageSourceTypeIdentifierHint:设置预设的图片格式,格式参照UTType.h
kCGImageSourceShouldAllowFloat:如果文件格式支持,是否应将图像作为浮点CGImageRef返回
kCGImageSourceShouldCache:是否应以解码形式缓存图像
kCGImageSourceCreateThumbnailFromImageIfAbsent:如果原图中缩略图不存在,是否根据原图创建缩略图
kCGImageSourceCreateThumbnailFromImageAlways:是否始终根据原图创建缩略图,即使原图中存在缩略图
kCGImageSourceThumbnailMaxPixelSize:缩略图最大尺寸,CFNumber格式
kCGImageSourceCreateThumbnailWithTransform:缩略图是否根据原图像的方向和像素纵横比进行旋转和缩放
一.导入图片数据,进行图片格式解码
正如前文基础知识中CGImageSource支持解码的图片数据类型,是不是除了png,jpg很多格式都没见过。有一些格式图片没有办法通过UIImage(named:String)来进行加载,这里就需要通过CGImageSource进行格式转换成CGImage进行加载
func createImageFromSource()-> CGImage?{
let myOptions = [kCGImageSourceShouldCache : kCFBooleanTrue,kCGImageSourceShouldAllowFloat : kCFBooleanTrue] as CFDictionary;
//这里我放了一张png图片在工程中
guard let imgPath = Bundle.main.path(forResource: "IMG_0868", ofType: ".PNG")else{
return nil
}
guard let myImageSource = CGImageSourceCreateWithURL(URL(fileURLWithPath: imgPath) as CFURL, myOptions) else {
print(stderr, "Image source is NULL.");
return nil
}
//通过CGImageSourceCreateImageAtIndex函数生成cgimage格式数据
guard let myImage = CGImageSourceCreateImageAtIndex(myImageSource,0,nil)else {
print(stderr, "Image not created from image source.");
return nil
};
return myImage;
}
二.通过原图获取缩略图
func createThumbnailFromSource()-> CGImage?{
let myOptions = [kCGImageSourceShouldCache : kCFBooleanTrue,kCGImageSourceShouldAllowFloat : kCFBooleanTrue] as CFDictionary;
//这里我放了一张png图片在工程中
guard let imgPath = Bundle.main.path(forResource: "IMG_0868", ofType: ".PNG")else{
return nil
}
guard let myImageSource = CGImageSourceCreateWithURL(URL(fileURLWithPath: imgPath) as CFURL, myOptions) else {
print(stderr, "Image source is NULL.");
return nil
}
let thumbnailOptions = [kCGImageSourceCreateThumbnailWithTransform : kCFBooleanTrue,kCGImageSourceCreateThumbnailFromImageIfAbsent : kCFBooleanTrue, kCGImageSourceThumbnailMaxPixelSize : 200] as CFDictionary;
// 生成缩略图
guard let thumbnailImage = CGImageSourceCreateThumbnailAtIndex(myImageSource,0,thumbnailOptions)else {
print(stderr, "Image not created from image source.");
return nil
};
return thumbnailImage;
}
三.获取图片的相关信息
图片视频等文件其实都是一个压缩包,里面包含很多信息,通过指定的格式解压才有了我们看到的效果。图片中就包含定位、拍摄设备、拍摄日期以及大小等等。通过CGImageSourceCopyPropertiesAtIndex就可以拿到这些信息,具体需要用到什么信息再自行加工。CGImageProperties详细对照表
func getPropertiesFromImgSource() -> [String:Any]? {
// Create the dictionary
let myOptions : CFDictionary = [kCGImageSourceShouldCache : kCFBooleanTrue,kCGImageSourceShouldAllowFloat : kCFBooleanTrue] as CFDictionary;
// Create an image source from the URL.
guard let imgPath = Bundle.main.path(forResource: "IMG_0851", ofType: ".HEIC")else{
return nil
}
guard let myImageSource = CGImageSourceCreateWithURL(URL(fileURLWithPath: imgPath) as CFURL, myOptions) else {
print(stderr, "Image source is NULL.");
return nil
}
guard let props : NSDictionary = CGImageSourceCopyPropertiesAtIndex(myImageSource, 0, nil)else{
return nil
}
print(props)
//需要返回数据自行进行加工
return nil
}
打印内容
{
ColorModel = RGB;
DPIHeight = 72;
DPIWidth = 72;
Depth = 8;
Orientation = 1;
PixelHeight = 3024;
PixelWidth = 4032;
PrimaryImage = 1;
ProfileName = "Display P3";
"{Exif}" = {
...
};
"{GPS}" = {
...
};
"{MakerApple}" = {
...
};
"{TIFF}" = {
...
};
}
四.逐步加载图片
在某些时候加载一张比较大的或者质量比较高的图片,下载时间比较长。会影响用户体验,通过CGImageSourceUpdateData逐步更新图片数据就会使体验变得更好一些。
//用来接收请求返回的data
var imgData = Data()
//这里用本地网络请求下载图片,多张图片加载时请使用多线程优化,不做过多阐述
func createCreFromSource(){
let session = URLSession(configuration: URLSessionConfiguration.default, delegate: self, delegateQueue: nil)
let task = session.dataTask(with: URL(string: "http://localhost:8181/download?fileName=IMG_1438.JPG")!)
task.resume()
}
//通过URLSessionDataDelegate实现,不要用block,block会在拿到所有数据后触发
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
//拼接接收到的data数据
imgData.append(data)
let imageOptions = [kCGImageSourceShouldCache : kCFBooleanTrue,kCGImageSourceShouldAllowFloat : kCFBooleanTrue] as CFDictionary
let incrementSource = CGImageSourceCreateIncremental(nil)
CGImageSourceUpdateData(incrementSource, self.imgData as CFData, dataTask.countOfBytesExpectedToReceive == self.imgData.count)
let status = CGImageSourceGetStatus(incrementSource)
switch status {
case .statusComplete,.statusIncomplete:
if let cgImage = CGImageSourceCreateImageAtIndex(incrementSource, 0, imageOptions){
DispatchQueue.main.async {
//用到orientation因为测试图片旋转了90度,在查找原因
self.imgView.image = UIImage(cgImage: cgImage, scale: 1.0, orientation: UIImage.Orientation.right)
}
}
default:
break
}
}