用 picture + source + img 替代本來的 JavaScript 替換

目前我在 blog 上使用 Imgur 的圖檔主要是用 WebP 格式,然後針對不支援 WebP 的瀏覽器 (主要就是蘋果家的 Safari) 是用 JavaScript 換回 JPEG 格式...

昨天早上看到「AVIF has landed」這篇,提醒我有 <picture> 這個原生支援的方式可以用,翻了一下 Can I Use 上面的支援程度,看起來除了 IE11 以外幾乎都支援了 (參考「Picture element」),而且 IE11 應該也會因為語法的關係走到正確的 JPEG fallback,大概是這樣:

<picture>
    <source type="image/webp" srcset="https://i.imgur.com/xxxxxx.webp" />
    <img src="https://i.imgur.com/xxxxxx.jpg" alt="" />
</picture>

換完後來觀察看看...

Chrome 85 支援 AVIF

看到「How to Use AVIF: The New Next-Gen Image Compression Format」這篇在推銷用 AVIF 取代 JPEGWebP

首先是跑去 Can I Use 翻,發現 Google Chrome 85 之後支援了,另外在「Issue 960620: Support AVIF」這邊可以看到對應的 ticket,以及「AVIF Image Decode」這邊有狀態:

Enabled by default (tracking bug) in:
Chrome for desktop release 85

現在的 stabel channel 是 84,所以是下個 release 就會有了。以 Google Chrome 的市占率來說,推出來等於是支援度直接過半... 這點也的確有人批評,不過又是另外一個話題了。

對於不支援 AVIF 的瀏覽器,也有對應的 polyfill 可以上 (用 javascript 去補功能),不過因為是透過 AV1 codec,能夠向下支援的版本還是不多,除非連 AV1 都透過 polyfill 支援:「AVIF (AV1 Still Image File Format) polyfill for the browser」。

另外在寫「WebP 的檔案大小未必比 JPEG 小...」這篇時有提過 AVIF 其實也不是完美的,畢竟是從 video codec 演化來的演算法,對於演算法判斷不重要的部位會掉比較多細節...

Travis CI 推出 20.04 的環境了

看到 Travis CI 推出 Ubuntu 20.04 的測試環境公告,嚇了一跳:「Ubuntu 20.04 (Focal Fossa) build environment is available!」。

要知道當年是在 2017 年七月才支援 Ubuntu 14.04 (參考「Travis CI 總算要把 Trusty 當作預設環境了...」這篇),在 2018 年十一月才支援 Ubuntu 16.04 (參考「Travis CI 居然記得要支援 16.04 了...」這篇),然後 18.04 上線乾脆不公告了 (翻了一下社群的討論「Ubuntu 18.04.1 LTS (Bionic Beaver)」,是在 2019 年的七月左右支援的)...

這次 20.04 出來還不到半年居然支援了!

避開人臉辨識系統的演算法

Hacker News Daily 上看到的專案,針對現在很多演算法可以抓出照片上的人臉進行防禦:「Image "Cloaking" for Personal Privacy」。

這算是 Evasion 的應用,這個專案想要提供演算法,可以在照片上「隱形」,使得演算法偵測不到「人臉」,程式碼可以在 Shawn-Shan/fawkes 這邊翻到,可以看到是在 Python 上用 TensorFlowKeras 實做出來的。

不過會覺得比較有趣的反而不是裡面的方法,而是這篇論文的六個作者:

Shawn Shan†, PhD Student
Emily Wenger†, PhD Student
Jiayun Zhang, Visiting Student
Huiying Li, PhD Student
Haitao Zheng, Professor
Ben Y. Zhao, Professor

† Project co-leaders and co-first authors

從名字上來看五個是華人,而且一路搜下來會發現掛在最後一位的 Ben Y. Zhao 教授在 Quora 上常常回答問題,而且這些問題 (與回答) 還蠻有趣的,可以自己搜看看...

WebP 的檔案大小未必比 JPEG 小...

在「Is WebP really better than JPEG?」這邊發現在差不多的條件需求下,WebP 壓出來的檔案大小未必會比 JPEG 小。

先講結論:提供服務的人可以先確認自家的 JPEG 壓縮是不是有先用 MozJPEG (壓縮率更好),然後再考慮要不要支援 WebP。

Google 在推 WebP 這個格式的時候,宣稱失真壓縮的部份可以比 JPEG 小 25%~34%:(出自「A new image format for the Web」)

WebP lossless images are 26% smaller in size compared to PNGs. WebP lossy images are 25-34% smaller than comparable JPEG images at equivalent SSIM quality index.

但作者發現 Google 之所以可以達到 25%~34% 這個數字,是因為比較的對象是 Independent JPEG Group 所釋出的 cjpeg,而如果拿 MozJPEG 相比的話應該得不到這個結果,另外也把 AV1 的 AVIF 拉進來一起測試了:

I think Google’s result of 25-34% smaller files is mostly caused by the fact that they compared their WebP encoder to the JPEG reference implementation, Independent JPEG Group’s cjpeg, not Mozilla’s improved MozJPEG encoder. I decided to run some tests to see how cjpeg, MozJPEG and WebP compare. I also tested the new AVIF format, based on the open AV1 video codec. AVIF support is already in Firefox behind a flag and should be coming soon to Chrome if this ticket is to be believed.

這邊作者測試用的圖集是 Kodak Lossless True Color Image Suite,測試的結果發現 WebP 的確比 libjpeg (cjpeg) 好一些,但沒有像 Google 講的那麼多 (這邊就不知道是不是現在的 libjpeg 又有改善),而 WebP 與 MozJPEG 相比的話就沒有明顯優勢了:

WebP seems to have about 10% better compression compared to libjpeg in most cases, except with 1500px images where the compression is about equal.

However, when compared to MozJPEG, WebP only performs better with small 500px images. With other image sizes the compression is equal or worse.

I think MozJPEG is the clear winner here with consistently about 10% better compression than libjpeg.

另外也提到了 AVIF 的壓縮率很好,不過要注意演算法會把非重點部位的細節吃掉:

I think AVIF is a really exciting development and compared to WebP it seems like a true next-generation codec with about 30% better compression ratio compared to libjpeg. Only concern I have is the excessive blurring of low detail areas. It remains to be seen if this can be improved when more advanced tooling becomes available.

對網頁的應用來說,WebP 另外一個痛點是在 Safari 上的支援度,在 caniuse.com 的「WebP image format」這邊可以看到目前各瀏覽器都支援了,就剩下 Safari 還不支援,所以目前在 iOS 上得降回 JPEG:

不過這點之後也改變了,在 iOS 14 beta 裡的 Safari 可以看到支援 WebP 了:「Safari 14 Beta Release Notes」。

Media
New Features
Added WebP image support.

所以這個狀況變得有點微妙了...

產生模糊縮圖的 BlurHash

先從一張圖片算出大約 20~30 bytes 的字串,就可以在 API response 時快速產生出一個很模糊但是有有代表性的縮圖 (或是在 HTML 裡面放,用 javascript 產生):「BlurHash」。

從官方給的範例比較快理解:

以及:

另外也提供了展現在 app 上的效果:

有支援一些程式語言,不過看起來行動平台上的支援都是比較新的語言 (Swift & Kotlin),如果不是用這些語言而想用 BlurHash 的話就得自己整了...

另外在 Hacker News 上有翻到先前的討論:「BlurHash: Algorithm to generate compact representation of an image placeholder」,開頭就看到其他軟體的作法:

For comparison, Instagram sends ~200 byte base64 thumbnails in its API responses. It's a low-res JPEG with a fixed header to save a bit more space. This is also used to blur sensitive images. You can get even better results with webp.

這個方法就避開另外再弄一包 library 進去,用現成的 library 就會動了...

用 OpenCV 與類神經網路放大圖片

在「Deep Learning based Super Resolution with OpenCV」這邊看到 OpenCV 支援這些類神經網路的演算法了,而且有預先訓練好的模型資料可以下載來用。

傳統放大的方法包括 bicubic 與 nearest neighbor,速度很快但是效果就普普通通,而 NN 類的方法的效果遠超過傳統方式,不過速度慢不少。

文章裡面有提到可以指定不同的 NN 模型:

The first parameter is the name of the model. You can choose between: “edsr”, “fsrcnn”, “lapsrn”, “espcn”. It is very important that this model is the correct one for the model you specified in ‘sr.readModel()’. See the Model section on the bottom of the page for the specifications of each model.

拿這些模型名字搜了一下資料,在「Super-resolution benchmarking」這邊可以看到比較,主要是在講 EDSR 很棒,然後 ESPCN 很快?

不過看起來可以直接拿來用在不少地方了...

HTTP/1.1 與 HTTP/2 的最佳化技巧

這篇在討論,無論是 HTTP/1.1 時代,或是 HTTP/2 時代下 (裡面還包括了 HTTP/2 的 Server Push),各種讓下載速度最佳化的技巧以及造成的複雜度:「Performance testing HTTP/1.1 vs HTTP/2 vs HTTP/2 + Server Push for REST APIs」。

文章裡其中一個提到的是各類「打包」的技巧,也就是 JavaScript 的 bundle,或是 CSS 的 Image sprites,甚至是 API 的合併,像是很多人會考慮的 GraphQL

雖然在 HTTP/2 年代我們常說可以省下來,但這並不代表「打包」在 HTTP/2 情境下沒有效果,只是改善的幅度比較少,所以這個最佳化的技巧比起 HTTP/1.1 年代,可以放到後面一點再做,先把人力放到其他地方。但如果團隊工具已經熟悉打包技巧的話 (可能是以前就已經做好了),其實繼續使用沒有太大問題...

另外是 Server Push 的情境,意外的反而可以提昇不少速度,看起來主要是少了請求的時間,所以快不少。

再來是跨網域時 CORS 的問題,在 Flash 的年代是一個 crossdomain.xml 解決,但現在的解法是多一個 OPTIONS request,反而造成很大的效能問題... 文章裡提到現在看起來有個 Draft 在發展與 Flash 類似的機制:「Origin Policy」。

作者在測試完後得到的結論其實跟蠻多「直覺」相反的:

  • If speed is the overriding requirement, keep using compound documents.
  • If a simpler, elegant API is the most important, having smaller-scoped, many endpoints is definitely viable.
  • Caching only makes a bit of difference.
  • Optimizations benefit the server more than the client.

Chrome 將不會在 HTTPS 頁面上載入 HTTP 資源...

現在 Google Chrome 的穩定版是 77,到了十二月會推出的 79 的時候,就會有一連串的避免 HTTPS 頁面使用 HTTP 資源的措施:「No More Mixed Messages About HTTPS」。

首先是 79 的時候會有新的界面,讓使用者可以修改阻擋類的設定。

到了 80 的時候會試著將 HTTP 的影音 <audio><video> 升級到 HTTPS 連線,如果 HTTPS 讀不到的話就當作讀取失敗。但圖片 <img> 的部份則是會讀進來,只是安全性上會顯示 Not Secure。

到了 81 就是這系列的最終階段,包括 <img> 也會一使用 80 時影音的邏輯,沒辦法在 HTTPS 上讀到就當作讀取失敗。

把 Docker Image 轉成 VM Image

看到「ottomatica/slim」這個專案:

slim will build a micro-vm from a Dockerfile. Slim works by building and extracting a rootfs from a Dockerfile, and then merging that filesystem with a small minimal kernel that runs in RAM.

This results in a real VM that can boot instantly, while using very limited resources. If done properly, slim can allow you to design and build immutable unikernels for running services, or build tiny and embedded development environments.

從 screenshot 可以看到會產生 ISO Image:

產生的 ISO Image 可以透過 HyperKit (在 macOS 時) 或是 VirtualBox 跑起來。

實際用途不知道多大,算是一種嘗試?