iOS ImageIO 的使用- CGImageSource圖像解碼

這里只講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:如果原圖中縮略圖不存在,是否根據原圖創(chuàng)建縮略圖
kCGImageSourceCreateThumbnailFromImageAlways:是否始終根據原圖創(chuàng)建縮略圖,即使原圖中存在縮略圖
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()
    //這里用本地網絡請求下載圖片,多張圖片加載時請使用多線程優(yōu)化,不做過多闡述
    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會在拿到所有數據后觸發(fā)
    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圖像編碼
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容