[轉] 為何圖片經過OSS縮略之后尺寸變大了?

摘要:OSS提供了基本的圖片處理功能和圖片格式之間的轉換功能,在實際使用過程中,很多用戶使用OSS將原圖縮略之后輸出,在這個過程中也出現了很多用戶詢問為何縮略之后圖片尺寸變大,本文主要通過一些示例解釋了這種現象出現的原因和排查方法。

簡介

OSS提供了基本的圖片處理功能和圖片格式之間的轉換功能,在實際使用過程中,很多用戶使用OSS將原圖縮略之后輸出,在這個過程中也出現了很多用戶詢問為何縮略之后圖片尺寸變大,如這個例子:

原圖:http://batchtest.oss-cn-hangzhou.aliyuncs.com/example1.png

處理之后:http://batchtest.oss-cn-hangzhou.aliyuncs.com/example1.png?x-oss-process=image/resize,w_600

原圖經過OSS從640x427 縮放到 600x400之后size反而變大了很多,這是為什么呢?

下面我們結合不同圖片格式的一些特點分析一下為什么會出現這樣的情況。

格式對比

圖片目前是一種多種編碼格式并存的情況。目前在網絡上廣泛使用的主流格式有JPEG、PNG和WEBP三種,其他的類似BMP、GIF、TIFF等使用較少,這里暫時不討論。

JPEG作為一種最常見的圖片格式,出現的最早,幾乎已經成為網絡上的標準格式。但是在實際使用上有一個最大的問題,那就是不支持透明通道。

PNG是一種無損壓縮的圖片格式,最大的優勢是支持模式多,可以支持RGB、灰度、索引等各種格式,同時可以自由選擇疊加透明通道或者指定透明背景顏色,因此在圖片質量要求較高的時候或者需要支持透明通道的時候PNG是最好的選擇。

WEBP是Google大力推廣的一種圖片格式。WEBP作為一種現代圖片格式,不僅運用了很多新的壓縮方式,達到在同等效果下比JPEG減小很多尺寸,而且支持透明通道、無損壓縮等之前只有PNG才支持的一些特性,因此在很多方面也得到了廣泛的運用。

三種格式的功能對比如下:

image.png

尺寸影響因素

對于同一張片來說,使用JPEG和WEBP,尺寸影響因素除了圖片長寬之外,最主要就是壓縮的質量參數。但是對于PNG來說,影響的因素非常多。

PNG的是無損壓縮,基本原理是首先對圖片使用差分編碼,然后對編碼之后的數據使用LZ77+Huffman編碼進行壓縮。因此PNG圖片的大小受到以下這些因素的影響:

  • 圖片內容:因為重復性內容多的PNG圖片會導致無法充分的壓縮,因此文件大小會很大。
  • 位深:PNG支持16bit和8bit的類型。
  • 色彩空間:PNG支持24bit的真彩色、8bit的灰度、8bit的索引圖像等類型,因此視覺效果相同的圖片文件大小會非常懸殊。
  • 透明通道:帶透明通道的PNG圖片會比不帶的多出很多像素,另外,如果僅僅指定透明背景色對圖片文件大小幾乎無影響。

下面會用結合實際遇到的一些例子來說明這些因素如何影響圖片文件大小。

例子1

首先我們分析最開頭遇到的這個例子。

原圖:http://batchtest.oss-cn-hangzhou.aliyuncs.com/example1.png

處理之后:http://batchtest.oss-cn-hangzhou.aliyuncs.com/example1.png?x-oss-process=image/resize,w_600

可見原圖大小為127K,縮放之后為335K。

這種問題調查首先要確定原圖和縮放之后的一些詳細信息,這里我們使用ImageMagicK這個工具集中的identify命令來查看對應的信息。工具官網見https://www.imagemagick.org/script/index.php

這里使用的命令是identify -verbose xxx.png。

原圖的信息為:

 Format: PNG (Portable Network Graphics)
  Mime type: image/png
  Class: PseudoClass
  Geometry: 640x427+0+0
  Units: Undefined
  Type: Palette
  Endianess: Undefined
  Colorspace: sRGB
  Depth: 8-bit
  Channel depth:
    red: 8-bit
    green: 8-bit
    blue: 8-bit

再看處理之后的圖片信息:

Format: PNG (Portable Network Graphics)
  Mime type: image/png
  Class: DirectClass
  Geometry: 600x400+0+0
  Units: Undefined
  Type: TrueColor
  Endianess: Undefined
  Colorspace: sRGB
  Depth: 8-bit
  Channel depth:
    red: 8-bit
    green: 8-bit
    blue: 8-bit

這里可以看出區別,那就是原圖的Type為Palette,處理之后的圖片為TrueColor,這就是最大的差別,因為原圖為索引類型,處理之后的圖片為RGB真彩色,因此需要編碼的像素點個數是索引類型的三倍,因此導致圖片變大。

這種類型是最常見的圖片變大的原因,造成一種原因一個很重要的因素是使用了PNG優化工具如ImageAlpha等,這些工具會將真彩色的PNG圖片降采樣到256種顏色然后壓縮成索引類型以減少圖片大小,這是一個有損的過程。但是在縮放過程中,縮略的過程會根據原像素計算出新的像素值,因此縮放算法會導致結果圖片生成的顏色數目超過256種從而無法壓縮成索引圖像。

為了確定這一點,我們也可以使用identify工具來查看顏色數目:

$ identify -verbose -unique http://batchtest.oss-cn-hangzhou.aliyuncs.com/example1.png?x-oss-process=image/resize,w_600  |grep Colors
  Colorspace: sRGB
  Colors: 27080
$ identify -verbose -unique http://batchtest.oss-cn-hangzhou.aliyuncs.com/example1.png  |grep Colors
  Colorspace: sRGB
  Colors: 256

可見顏色數目由256增長到了27080個。

例子2

原圖:http://batchtest.oss-cn-hangzhou.aliyuncs.com/example2.png

處理之后:http://batchtest.oss-cn-hangzhou.aliyuncs.com/example2.png?x-oss-process=image/resize,w_600

原圖大小為283K,處理之后大小為335K。

首先還是按照上面一個例子的方法,檢查一下圖片格式信息。

這是原圖的:

  Format: PNG (Portable Network Graphics)
  Mime type: image/png
  Class: DirectClass
  Geometry: 640x427+0+0
  Units: Undefined
  Type: Palette
  Endianess: Undefined
  Colorspace: sRGB
  Depth: 8-bit
  Channel depth:
    red: 8-bit
    green: 8-bit
    blue: 8-bit

這是處理之后的結果:

  Format: PNG (Portable Network Graphics)
  Mime type: image/png
  Class: DirectClass
  Geometry: 600x400+0+0
  Units: Undefined
  Type: TrueColor
  Endianess: Undefined
  Colorspace: sRGB
  Depth: 8-bit
  Channel depth:
    red: 8-bit
    green: 8-bit
    blue: 8-bit

可見,兩者的壓縮類型是完全一致的,那是什么原因導致的問題呢?

這里需要使用另外一個工具,pngthermal,鏈接見https://encode.ru/threads/1725-pngthermal-pseudo-thermal-view-of-PNG-compression-efficiency

這個工具主要的功能是將PNG圖片不同部分的壓縮率使用可視化的方式展現出來,亮度越高的地方壓縮率越低,我們針對兩張圖片用該工具分析的結果如下,上為原圖,下為處理后圖片:


image.png
image.png

可見同樣視覺效果的圖片,壓縮率差別很大,說明處理前的圖片細節上重復較多,一般來說都是由于顏色數目導致的。為了確定這一點,使用上個例子的工具檢查顏色數目,可以同樣確定原圖為256種顏色,處理后變成了27080種顏色。

其實本示例中的原圖就是上一個例子的原圖強制轉換為RGB真彩色空間之后生成的。因為顏色只有256種,因此可供壓縮的重復性信息較多,導致了處理后的圖片比原圖還大。

實際應用中,有很多美工生成的素材圖片使用的顏色并不多,因此導致壓縮率比較高,縮放之后就會出現類似的情況。

例子3

原圖:http://batchtest.oss-cn-hangzhou.aliyuncs.com/example3.png

處理之后:http://batchtest.oss-cn-hangzhou.aliyuncs.com/example3.png?x-oss-process=image/format,webp

這里的示例是一個PNG轉WEBP,原圖大小為760字節,處理之后變成了1.3K。

首先還是使用identify工具查看兩者的差別。

這是原圖的:

  Format: PNG (Portable Network Graphics)
  Mime type: image/png
  Class: DirectClass
  Geometry: 92x34+0+0
  Units: Undefined
  Type: GrayscaleAlpha
  Endianess: Undefined
  Colorspace: sRGB
  Depth: 8-bit
  Channel depth:
    gray: 8-bit
    alpha: 8-bit

這是處理之后的:

  Format: PAM (Common 2-dimensional bitmap format)
  Mime type: image/x-portable-pixmap
  Class: DirectClass
  Geometry: 92x34+0+0
  Units: Undefined
  Type: PaletteAlpha
  Base type: TrueColor
  Endianess: Undefined
  Colorspace: sRGB
  Depth: 8-bit
  Channel depth:
    red: 8-bit
    green: 8-bit
    blue: 8-bit
    alpha: 8-bit

這里可以看出一個非常明顯的區別,原圖是灰度圖帶上了透明通道,而處理之后的圖片是RGB再帶上透明通道。

原因是Webp并不支持灰度圖帶上透明通道這種類型,帶上透明通道就將格式固定成了RGBA格式。因此導致了要保存的數據變大。

總結

從上文的例子可以看出,影響圖片文件大小的因素很多,這里僅簡單的列舉了幾個在應用中經常遇到的因素。

  • 例子1:索引類型PNG縮略之后變成RGB類型PNG,像素增多導致文件變大。
  • 例子2:顏色數目較小的PNG圖片縮略之后顏色數目變多,壓縮率下降導致文件變大。
  • 例子3:帶透明通道的灰度PNG轉換成WEBP之后變成RGBA格式,像素增多導致文件變大。

可以看到大部分和預期結果不符合的都是PNG格式的圖片。

一般來說,同樣視覺效果的圖片文件大小,webp<jpeg<png。但是PNG支持的編碼類型非常的靈活,可以根據實際應用的需求自由調整,網上也有很多優化PNG圖片大小的工具,因此往往出現圖片處理之后破壞了優化效果,導致處理之后反而文件變大的情況。因此這里建議使用PNG圖片上有體積大小要求的場景把體積優化放在最后一步,最好保存多份不同分辨率的PNG素材以供調用,不要對圖片處理之后的圖片文件大小有強預期。如果碰到了圖片文件大小上的問題,也可以使用本文介紹的工具自己手動進行分析。

這里最后再補充一個Google給出的圖片使用格式的建議作為結束:

image.png

文章出處:https://yq.aliyun.com/articles/74634

另:

JPG轉PNG文件大小通常會增加5倍以上,這是因為JPG是有損壓縮,而PNG是無損壓縮。JPG轉為PNG圖片的質量不會有變化,但大小會增加很多;而PNG轉JPG,會損失掉透明的部分(因為JPG不支持圖片的透明),但文件大小會減少很多,根據不同的壓縮比,可以達到10倍的壓縮比。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。