#0 關於Image Resizing Techniques

縮圖技術

這是在使用Xcode做照片牆時出現的問題,透過點擊request去取得url的照片並排列成照片牆顯示在第二頁,出現的第一個問題是collectionview卡死,大致如下:

原先點擊request,照片牆幾乎顯示不出來,或是需要等很久,顯示後滑動collectionview又幾乎滑不動,嚴重lag,所以開始去找方法,找方法前會先猜問題是什麼,如果程式沒有回報錯誤,卻在跑模擬器出現這樣的狀況,那是不是因為照片太大,因為每頁大致要顯示8 * 4 = 32張照片,每張照片若是800 * 600,約150 kb,這樣每頁要耗費4800 KB ≃ 4.6 MB。

於是參考了別人的做法,加大存取時的Cache,或以NSCache暫存已讀過的圖片,結果發現還是不行,滑動該頁仍是卡死的狀況,轉念一想4.6 Mb在4G網路發達的現今應該不是什麼問題,以網路上查到的各縣市4G平均速率在52 Mbps ~ 77Mbps間,除以 8後是6.5 MB/s ~ 9.625 MB/s,那其實每頁也僅需花一秒就下載完成,便瞭解問題並不出在圖片大小,後來知道是出在線程(執行緒)的安排。

在線程安排前,也想過了是不是collectionview與tableview的機制不同,由於較常使用tableview,知道tableview有dequeReusableCell,即是在滑動到下方時,移除上方顯示的cell,但不對,collectionview也是如此編寫的。

簡單說一下解決辦法,在主線程生成collectionview,但把讀取圖片放到較後面去處理,先生成collectionview,圖片慢慢顯示,雖然顯示的圖片先後順序不同,呈現東一塊、西一塊,這同樣是線程安排的事,當然啦!有辦法讓圖片按照順序顯示。

不過這篇文章的重點要放在image resizing,在collectionview無法滑動時也試了image resizing,印象中是參考了stackoverflow編寫,但回頭翻文章卻是在Medium找到,先寫了一個func downsample,如下:

其實也沒想太多就直接拿來用,於是

let image = downsample(imageAt: astro.url, to: CGSize(width: 200, height: 200), scale: 0.8)

可以簡單看出func downsample用以改變圖片寬高及大小。

當然有了func downsample就拿去跑跑看,結果照片牆顯示沒有快多少,resizing image後還有些糊,甚至糊到這麼小的格子都能看出畫質不佳。

後來還找到了另篇文章,裡面詳述了image resizing techniques有幾種方法,每種方法可能有不同優點與效率,如下:

文章開頭也有說要編寫一個downsample的func,
downsample要放在DispatchQueue.global(qos: .userInitiated)去執行,
cell.showImg.image = image則要放在DispatchQueue.main去執行,
這跟找到collectionview難以滑動的我的解決辦法是一樣的,試著重申一次:

  1. 先生成collectionview
  2. 圖片在後臺下載,載完多少就顯示多少在view上

resizing image techniques也是將圖片賦值丟到主線程,resizing丟次線程,如下:

文章作者測試後,推崇方法1跟方法2,即是Drawing to a UIGraphicsImageRendererDrawing to a Core Graphics Context,而我原先找到的方法類似第三種Creating a Thumbnail with Image I/O,那畫質不佳的原因推估是跟形成thumbnail有關。

方法2導入了CoreGraphics,方法3導入了ImageIO,這其實也不一定,因為原先thumbnail的做法是為了collectionview才形成縮圖,後面的方法,文章作者只測試顯示單張圖下,有效運用資源的方法,呈現如下:

在collectionview裡

於是collectionview我就不改了,但是恰好可以用在DetailViewController上,所以就試了試,嗯,真的有快ㄧ點欸!

不確定這關於使用者體驗是否能用UI Test做,下次再來試試。

在tableview裡

只是,到這邊還有個問題,在解析JSON文件時,DURL裡面竟然有影片檔,而不是照片檔,這相當令人頭疼,有機會再來解決吧。

我只做了初步的解,因為解析時沒辦法解出URL,所以先設定為String再讓它轉成URL,這導致某些照片無法顯示,因為他是影片嘛,不知道有沒有抓影片縮圖的辦法就是,這樣便可以使用if else來做流程控制了。

--

--

Chun-Li 春麗

Do not go gentle into that good night, Old age should burn and rave at close of day; Rage, rage, against the dying of the light.