https://blog.ibireme.com/2015/11/02/ios_image_tips/ios
如何把 GIF 動圖保存到相冊?git
iOS 的相冊是支持保存 GIF 和 APNG 動圖的,只是不能直接播放。用 [ALAssetsLibrary writeImageDataToSavedPhotosAlbum:metadata:completionBlock] 能夠直接把 APNG、GIF 的數據寫入相冊。若是圖省事直接用 UIImageWriteToSavedPhotosAlbum() 寫相冊,那麼圖像會被強制轉碼爲 PNG。github
將 UIImage 保存到磁盤,用什麼方式最好?瀏覽器
目前來講,保存 UIImage 有三種方式:1.直接用 NSKeyedArchiver 把 UIImage 序列化保存,2.用 UIImagePNGRepresentation() 先把圖片轉爲 PNG 保存,3.用 UIImageJPEGRepresentation() 把圖片壓縮成 JPEG 保存。緩存
實際上,NSKeyedArchiver 是調用了 UIImagePNGRepresentation 進行序列化的,用它來保存圖片是消耗最大的。蘋果對 JPEG 有硬編碼和硬解碼,保存成 JPEG 會大大縮減編碼解碼時間,也能減少文件體積。因此若是圖片不包含透明像素時,UIImageJPEGRepresentation(0.9) 是最佳的圖片保存方式,其次是 UIImagePNGRepresentation()。網絡
UIImage 緩存是怎麼回事?ide
經過 imageNamed 建立 UIImage 時,系統實際上只是在 Bundle 內查找到文件名,而後把這個文件名放到 UIImage 裏返回,並無進行實際的文件讀取和解碼。當 UIImage 第一次顯示到屏幕上時,其內部的解碼方法纔會被調用,同時解碼結果會保存到一個全局緩存去。據我觀察,在圖片解碼後,App 第一次退到後臺和收到內存警告時,該圖片的緩存纔會被清空,其餘狀況下緩存會一直存在。函數
我要是用 imageWithData 能不能避免緩存呢?編碼
不能。經過數據建立 UIImage 時,UIImage 底層是調用 ImageIO 的 CGImageSourceCreateWithData() 方法。該方法有個參數叫 ShouldCache,在 64 位的設備上,這個參數是默認開啓的。這個圖片也是一樣在第一次顯示到屏幕時纔會被解碼,隨後解碼數據被緩存到 CGImage 內部。與 imageNamed 建立的圖片不一樣,若是這個圖片被釋放掉,其內部的解碼數據也會被馬上釋放。rest
怎麼能避免緩存呢?
1. 手動調用 CGImageSourceCreateWithData() 來建立圖片,並把 ShouldCache 和 ShouldCacheImmediately 關掉。這麼作會致使每次圖片顯示到屏幕時,解碼方法都會被調用,形成很大的 CPU 佔用。
2. 把圖片用 CGContextDrawImage() 繪製到畫布上,而後把畫布的數據取出來看成圖片。這也是常見的網絡圖片庫的作法。
我能直接取到圖片解碼後的數據,而不是經過畫布取到嗎?
1.CGImageSourceCreateWithData(data) 建立 ImageSource。
2.CGImageSourceCreateImageAtIndex(source) 建立一個未解碼的 CGImage。
3.CGImageGetDataProvider(image) 獲取這個圖片的數據源。
4.CGDataProviderCopyData(provider) 從數據源獲取直接解碼的數據。
ImageIO 解碼發生在最後一步,這樣得到的數據是沒有通過顏色類型轉換的原生數據(好比灰度圖像)。
如何判斷一個文件的圖片類型?
經過讀取文件或數據的頭幾個字節而後和對應圖片格式標準進行比對。我在這裏寫了一個簡單的函數,能很快速的判斷圖片格式。
怎樣像瀏覽器那樣邊下載邊顯示圖片?
首先,圖片自己有 3 種常見的編碼方式:
第一種是 baseline,即逐行掃描。默認狀況下,JPEG、PNG、GIF 都是這種保存方式。
第二種是 interlaced,即隔行掃描。PNG 和 GIF 在保存時能夠選擇這種格式。
第三種是 progressive,即漸進式。JPEG 在保存時能夠選擇這種方式。
在下載圖片時,首先用 CGImageSourceCreateIncremental(NULL) 建立一個空的圖片源,隨後在得到新數據時調用
CGImageSourceUpdateData(data, false) 來更新圖片源,最後在用 CGImageSourceCreateImageAtIndex() 建立圖片來顯示。
你能夠用 PINRemoteImage 或者我寫的 YYWebImage 來實現這個效果。SDWebImage 並無用 Incremental 方式解碼,因此顯示效果不好。