【转】JPG打包压缩后比原来尺寸还大
【轉】JPG打包壓縮后比原來尺寸還大
作者:劉源
鏈接:https://www.zhihu.com/question/40371280/answer/86262934
來源:知乎
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
想用jpg的話,直接使用WWW加載jpg文件本身。加載好之后,WWW.texture 就是你要的貼圖。
————————————————————————————————————
題主之前就是這個方法,后來為什么要改呢。對于題主的這種情況,即使與當前工作流不符,我也會認為有必要單寫流程。優化項目時,由于內存、安裝包大小的原因改資源結構是常有的事,有時候甚至要寫專用的導出工具。
另外,AssetBundle開壓縮不一定是壞事,個人目前實際項目中,Android上實測開壓縮更快;而PC和IOS都是不壓縮更快... 目前認為Android設備讀寫存儲過慢。
————————————————————————————————————
擴展閱讀:為什么Unity不支持jpg
為了滿足實時渲染的需要,Unity會將你的圖片預先編碼為特定的顯卡格式,常見的格式有DXT、ETC、PVRTC等。這些格式一般數據非常整齊,顯卡會直接在顯存中保持壓縮格式,實時讀取像素。對于各個目標平臺,Unity有相應的支持格式列表可以手動選擇(各平臺不一樣)。
這種編碼速度挺慢的。首次打開一個工程時,Unity主要就是在做各種圖片的編碼,從jpg、psd等原始格式轉換為顯卡格式。大工程可達半個小時甚至更久。
常用的顯卡壓縮格式一般為4bps,就是0.5字節每像素。另外這些顯卡壓縮格式,一般未經過數學壓縮,可以被zip等壓縮算法再次壓縮。
* 1280*720 RGB原始圖片(RGB24):2.63M
* DXT1/ETC壓縮: 0.43M (另外,PVRTC只支持1024這種2的冪尺寸的)
* AssetBundle開壓縮模式(Unity使用LZMA算法,類似zip):上面數字的70%(照片)到25%(UI圖集)。
jpg由于計算量大,所以不是一種顯卡能支持的編碼格式。Unity中,WWW可以加載jpg等格式的原始文件,獲得RGB24這類未壓縮的貼圖。Unity幫你進行了jpg解碼,但是不負責重新編碼。
1. jpg算法 - 顯卡不支持的算法
很遺憾,jpg并不是一種顯卡支持的格式。
顯卡壓縮主要是為了解決顯存限制的問題。顯存是非常有限的,一張 2k*2k的圖片不壓縮的情況下高達12M,512M的顯存只能放42張,所以壓縮格式總是在顯存中直接存儲而不會解壓的。顯卡支持的格式,必須解碼快,非常快,能夠硬件直接從壓縮格式中任意讀像素。
jpg有很高的壓縮比,1:20左右不會有明顯的質量損失,你還可以往1:50甚至更高壓。但是他的計算量過大。jpg的設計目標是實時整體解壓縮,而不是實時隨機訪問。一方面jpg使用8x8的數據塊作為編碼單元,數據塊過大;另一方面jpg使用了塊變換編碼,然后還對數字進行了壓縮,擠掉了所有水分。讀取單個像素都需要解壓、反變換64個數據。
由于數字進行了壓縮,zip對jpg是沒有效果的。
jpg圖片被等分成8x8的塊,每塊的64個像素首先變換到頻率域(離散余弦變換),然后降低高頻質量甚至丟棄一些過小的數據(稱為量化),最后將剩下的數據壓縮成一個串。精髓就在于,圖片的主要信息來自于低頻數據,高頻數據精度下降一些一般看不出來。jpg這條路子也是當前視頻編碼的基石之一。解碼任何一個像素時,都需要讀取對應塊的全部數據流,解壓縮到頻率域,然后再反編碼到64個像素,這樣才能讀出一個像素。可以想象其計算量。
2. 顯卡支持的壓縮格式
DXT、ETC、PVRTC的算法可以認為是步步進化的。這篇文章介紹了更早的蠻荒時代(DreamCast那個時代)的實時解壓算法,有興趣可以看看。
我們以最簡單的 DXT1 為例。DXT1認為不透明圖片可用 4x4的小塊糊弄一下人的眼睛,每個4x4小塊只有2個顏色,以及他們的兩個中間色.... 一共就4個顏色!還特么有倆個是插值的,不知道你們感覺怎么樣。解碼非常直接,讀號,兩個顏色插值,結束。
這個簡單的算法獲得了極大的成功,隨后被微軟買了,變成DirectX的御用格式。而且后面的算法都是這類思想:
* 數據塊小
* 不做塊變換,只用簡單的插值、加減(jpg是64個數的變換) --- 極大減少計算量
* 不做數學壓縮,所以定長,可以直接尋址 --- 再次減少計算量,以及數據依賴性
由于不做數學壓縮,所以這類圖片都可以被zip等算法大幅度再次壓縮。
順便一提,這類算法的編碼比較耗時,而且結果不唯一。以DXT1為例,我們有16個像素,現在要挑兩個顏色,以及他們連線上的2個中間色代替這16個像素,哪兩個顏色最合適呢?顯然計算量就上來了,選擇也很多。
最后,jpeg和顯卡壓縮算法都是有損壓縮。就畫質來說,jpeg遠遠勝出。jpeg在1:10時幾乎看不出與原圖的差異,1:20時仍有極好的效果;而顯卡貼圖壓縮1:6左右就有明顯畫面損失。實際觀察,美術一般能接受寫實模型紋理的壓縮,同時一般難以接受UI壓縮的效果,特別是銳利的斜線和弧線,條狀物,或者半透明漸變都容易出現瑕疵。對于題主的情況,看起來很像背景圖之類的,確實可以考慮使用jpeg。 @劉源 的答案已經覆蓋了原因。簡單來說就是AssetBundle里的格式是為了讓顯卡能用,jpg是為了讓空間更小。?
補充一點,最近的情況其實在改變,D3D12支持用jpeg作為紋理格式,雖然(應該)還沒有驅動支持了這一點。GPU,尤其是移動GPU,是可以硬件解碼jpeg的,但沒回饋給programmable pipeline的texture sampler。把這條路打通就能直接都jpeg。 ------------------------------------------------------------------ 總結: JPG 優點:文件小,磁盤占用少。 缺點:1,壓縮算法太復雜,解壓費時,不被GPU硬件解壓支持;2,解壓時(后)占用內存比其它格式(ETC,PVRTC)內存占用大。 ETC格式或PVRTC格式雖然文件大一些,多占用了一些存儲空間,但其解壓是被GPU直接支持的硬件瞬間解壓,而且解壓后占用內存也比JPG小得多。 綜合來看,不應該使用JPG格式。posted on 2017-06-20 11:02 時空觀察者9號 閱讀(...) 評論(...) 編輯 收藏
總結
以上是生活随笔為你收集整理的【转】JPG打包压缩后比原来尺寸还大的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Memcpy, blockcopy的进一
- 下一篇: U3D屏幕坐标,世界坐标,像素坐标之间的