008 [iOS圖像]1、iOS中的那些圖片格式

      作一個圖像類相關的APP也有九個多月了(沒事別亂點),大部分時間都是在開發中學習。如今回頭系統性地補一下iOS的圖像處理知識。筆者此段時間也同時在寫畢業論文,可能想到哪裏寫到哪裏。這一系列文章可能包含如下內容(暫時構思):git

  • iOS中圖片的各類格式初探
  • iOS中圖片處理的各類框架淺析
  • iOS圖片處理的那些好用的第三方

iOS中圖片的各類格式初探

UIImage:github

      在全部表明圖片的各類類型中,來自UIKit的 UIImage 應該是開發者接觸最多的高階圖片對象,同時UIImage也提供了各類各樣的方法來處理圖片。UIImage是不可變對象,這意味着開發者不能直接修改圖片的Metadata(what is Metadata?),也不能直接訪問圖片的底層數據格式,好處也有,也就是UIImage是線程安全的。另一點,和UIImage最配對的莫過於UIImageView。算法

      須要注意的是,UIImage不適合承載太大的尺寸。在內存不足的時候,UIImage中的數據可能會被系統清理掉(不是UIImage,而是它包含的數據),而後在再次須要的時候UIImage會從新加載數據,這種步驟可能會帶來一些性能上的影響。開發者最好避免建立大於1024 x 1024 大小的UIImage。大尺寸的圖片除了消耗大量的內存,在使用圖片做爲紋理在OpenGL ES中渲染或者在view或者layer上重畫的時候可能會遇到性能問題。swift

      若是真的須要操做很大的圖片,以Bitmap形式在Graphics context中處理會是不錯的選擇。另一種顯示大圖的方式就是拆成幾張小圖再使用(聽起來手術牀有點複雜?)。緩存

      咱們先看看讀取UIImage的一個方法(Dikey嘗試投入Swift):安全

init?(named name: String) -> UIImage  

  關於這個方法,咱們須要記住的有幾點。第一點就是這個方法是默認會加載圖片到系統緩存的。若是圖片只用到一次,開發者應該用init(contentsOfFile:) 代替。第二點可能你們都知道,就是在Retina上,這個方法默認會在imageName後面加上@2x或者@3x(依據屏幕scale而定)。另外,若是是png文件,那讀取的時候後綴能夠省略。app

 

CGImage:框架

      說到bitmap,那CGImageRef就應該出場了。CGImageRef 就是對bitmap image/bitmap image masks的一種封裝。bitmap包含源圖片每個像素點的信息,因此在底層處理圖片就少不了和它打交道了。CG的前綴還表明着C,而後須要手動釋放內存……底層、複雜固然還有高效。簡單看一個建立方法:      ide

func CGImageCreate(_ width: Int,
                 _ height: Int,
                 _ bitsPerComponent: Int,
                 _ bitsPerPixel: Int,
                 _ bytesPerRow: Int,
                 _ colorspace: CGColorSpace!,
                 _ bitmapInfo: CGBitmapInfo,
                 _ provider: CGDataProvider!,
                 _ decode: UnsafePointer<CGFloat>,
                 _ shouldInterpolate: Bool,
                 _ intent: CGColorRenderingIntent) -> CGImage!

      讓咱們來逐項解析參數:性能

width

寬度

height

高度

bitsPerComponent

每一個像素對應的Componet對應的位寬. 舉例: RGBA-32 格式,須要component須要8bits 

bitsPerPixel

所須要的bits值(和參數名是否是不大匹配?). bitsPerPixel>= bitsPerComponent*bitsPerComponent的bit值

bytesPerRow

每一行佔用的內存

colorspace

色彩空間, Quartz 會持有它,再返回以後可能須要手動釋放

bitmapInfo

CGBitmapInfo 決定了bitmap是否須要保存 alpha 渠道、bitmap的相對像素位置, 色彩份量是 floating或integer相關.

provider

bitmap的數據源. 由Quartz持有; 需手動釋放.

decode

圖片解壓以後的數據。不須要從新映射色值,傳NULL。對於每種空間中的色彩份量,decode array的值都有上下限制。在RGB色域中,decode array一共提供6個entries,分別對應RGB的上下限。當一張圖片被渲染以後,Quartz使用一個線性轉變,將原始的色彩份量值轉成操做色彩空間中的數值。

shouldInterpolate 

是否容許interpolation(插值)。是的話,Quartz會對圖片使用像素平滑算法。假如爲NO,圖片在使用在比本身的分辨率高的設備上時可能會顯示出鋸齒。

intent

當一些顏色不在graphics context的目標色彩空間的色域中的時候,intent(再現意圖)決定了Quartz如何處理這些顏色。rendering intent會使用肯定的方法對色彩映射,進行空間轉換。更詳細的須要參考蘋果文檔:Color Rendering Intents.

      在底層處理bitmap,是一件不容易的事情,須要和了解不少與數字圖像處理相關的概念,這裏暫不深刻討論。Core Graphics是基於C的API,和Objective-C交互多是更直接的方式。這裏有一個很好的UIImage、bitmap互轉的示例 ,也許在Swift中,C混合Objective-C而後橋接至Swift是不錯的方式。

 

CIImage: 

      CIImage表明了Core Image中的一張圖片,注意僅僅是表明,雖然CIImage包含圖片相關的數據,實際上它不是一張圖片。CIImage是不可變類型,意味着線性安全,Core Image 經過CIImage的數據進行惰性渲染,帶來更高效的資源利用。

      什麼是惰性渲染?舉個栗子,對CIImage進行各類操做,並不直接產生渲染效果。只有好比,真正要求生成一張UIImage,這個時候CIImage就懂了。懶懶地提供了一張UIImage,現制的。

      CIImage 之於iOS的做用,有點像是Dota中的全能。蘋果提供了濾鏡、剪切、旋轉等等功能,而實際上以上功能可能均可以用其餘各類方式實現。也許較好的封裝和高效是加分項。

 

ALAsset/PHAsset

      看他們名字就知道他們很像,實際上,他們就是iOS在不一樣時代的兩架馬車,擔當了對Photos中的資源的讀寫中介人。不得不說這幾年apple的精力確實在iOS端比Mac OS X端多得多。Mac端的Photos是在10.10才替換的,而iOS上則更早一點。

      ALAsset中AL表明AssetsLibraryPHAsset中PH表明來自Photos框架。Photos框架中大量出現block,另外在照片讀取的時候,緩存也被各類設計好。更快、更好、更安全這句Swift的廣告詞扔在Photos框架中毫無違和感。不過也有不足的地方,缺點之一是iOS8以後纔出現Photos框架,你要麼扔掉iOS8之前的用戶吧,要麼你維護兩套代碼吧。另一個缺點是Photos框架因爲很新,在初期深刻使用的時候可能會發現各類bug。這兩個不大的缺點意味着在將來,Photos將是對Photos APP中的資源進行操做的不二選擇。

      從新忘記ALAssetPHAsset表明了iOS Photos App中的資源對象:包括圖片、視頻以及iCloud內容。做爲Photos框架中的一員,PHAsset只是進行其中的一個小小環節,獲取真正的圖片還須要配合PHImageManager等等才能讀取、緩存UIImage,利用PHFetchResults管理批量的PHAsset等等。PHAsset的最好展現:iOS8+的Photos。

 

小結:

      實際上,各類各樣的格式,只是恰到好處地表明圖片出如今了各類使用場合。而咱們只有在理解背後的框架以後才能在各類場合對圖片選擇正確的處理方式。這一篇簡單介紹一些平時iOS開發可能會碰到的一些與圖片相關的格式。

     下一章,咱們會去了解一下各類格式它們所在的框架。

相關文章
相關標籤/搜索