美文网首页Graphics
iOS ImageIO 的使用- CGImageSource图像

iOS ImageIO 的使用- CGImageSource图像

作者: 啦啦啦的小马蹄 | 来源:发表于2021-01-11 19:04 被阅读0次

    这里只讲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
               }
        }
    
    Apple官方文档:文档地址ImageIOGuide
    ImageIO的使用之CGImageDestination图像编码

    相关文章

      网友评论

        本文标题:iOS ImageIO 的使用- CGImageSource图像

        本文链接:https://www.haomeiwen.com/subject/dsshoktx.html