android 图片压缩,bitmap压缩总结
1.?? ?圖片壓縮相關概念
在android開發中,圖片加載到內存中通常需要占用大量的內存,導致app性能過度消耗,嚴重的話可能會導致OOM異常,所以對圖片進行優化就尤為重要。
android圖片壓縮的格式可以通過以下一張圖進行概括,這張圖摘自官方API文檔:
?
對于各個參數的含義,通過以下一張表格總結一下
| ALPHA_8 | 每個像素存儲為單個半透明(alpha)通道,占用1字節內存,用來存儲遮罩非常有用 |
| ARGB_4444 | ?每個像素占用2字節存儲空間,由于在這個配置下的圖片質量比較差,官方建議使用ARGB_8888,官方已提示ARGB_4444不推薦使用 |
| ARGB_8888? | ?每個像素占用4字節存儲空間,每個通道(A,R,G,B)都以8位精度進行存儲,這種格式下圖片質量最佳,官方推薦盡可能使用這種格式存儲 |
| HARDWARE | ?? ?一種特殊的存儲格式,當位圖僅僅存儲在圖形內存中時,位圖始終保持不變 |
| RGBA_F16 | ? ?每個像素存儲在8個字節上,很少用 |
| RGB_565?? | 每個像素存儲在2個字節上,沒有透明度,只包括了紅,綠,藍三個通道,當使用不需要透明度圖片時,可以使用該格式存儲 |
android圖片加載到內存,bitmap所占內存的大小可以由下列公式進行計算:
bitmap所占內存 = 圖片分辨率 * 一個像素所占的字節數
上述公式其實是不嚴謹的,對于從SD卡,assests目錄或者網絡中加載圖片所占用的內存,是可以通過上述的公式計算出來的。但是如果圖片存儲在res目錄中,當圖片加載進內存時,會經過一次分辨率的轉換,然后在計算內存占用多少,這時圖片的分辨率應該是轉換之后的分辨率,而不是原圖的分辨率。
這里只討論常規圖片壓縮方式,圖片都是存儲在SD卡或者assests目錄中,對于存儲在res目錄下的情況忽略。
bitmap的壓縮方式主要有:
1.?? ?采樣率壓縮
2.?? ?縮放壓縮
3.?? ?質量壓縮
4.?? ?設置RGB_565
5.?? ?使用createScaledBitmap
下面簡單討論下各種壓縮方式
2.?采樣率壓縮
通過設置BitmapFactory.Options的inSampleSize參數,達到壓縮圖片的目的。該參數表示壓縮為原圖的幾分之一,必須大于1,小于1按照1處理。
下面通過加載原圖和設置inSampleSize來對比設置inSampleSize加載圖片之后的效果。
把一張原圖不經過壓縮直接加載到內存中:
設置inSampleSize參數,加載一張圖片到內存中:
BitmapFactory.Options options = new BitmapFactory.Options(); String str = edtvSample.getText().toString(); int sample = 2; try {sample = Integer.parseInt(str); } catch (Exception e) {Toast.makeText(this, "請輸入有效數字內容", Toast.LENGTH_SHORT).show();e.printStackTrace();return ; } options.inSampleSize = sample;Bitmap bitmap = BitmapFactory.decodeFile(Environment.getExternalStorageDirectory().getAbsolutePath() + "/compresstest/test.png", options); if(bitmap != null) {String info = "壓縮圖片大小: " + (bitmap.getByteCount()) + " 寬度: " + bitmap.getWidth() + " 高度: " + bitmap.getHeight();Log.v("sample", info);tvCompress.setText(info);imgvCompress.setImageBitmap(bitmap); }其中inSampleSize通過界面動態設置,以此來查看不同inSampleSize加載圖片的具體效果。
例如把inSampleSize設置成4,寬度和高度都變為了原來的1/4,圖片內存整整縮小為原來的1/16。
?
下面是我測試的一張效果:
3.?縮放壓縮
通過Martix變換,設置縮放值以此來達到圖片壓縮的目的。
Bitmap bitmap = BitmapFactory.decodeFile(Environment.getExternalStorageDirectory().getAbsolutePath() + "/compresstest/test.png"); String strx = edtvSx.getText().toString(); String stry = edtvSy.getText().toString();float sx = 0.5f; float sy = 0.5f; try {sx = Float.parseFloat(strx);sy = Float.parseFloat(stry); } catch (Exception e) {Toast.makeText(this, "請輸入有效數字內容", Toast.LENGTH_SHORT).show();e.printStackTrace();return ; } if(bitmap != null) {Matrix matrix = new Matrix();matrix.setScale(sx, sy);Bitmap newBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);String info = " sx: " + sx + " sy: " + sy + " 壓縮圖片大小: " + (newBitmap.getByteCount()) + " 寬度為: " + newBitmap.getWidth() + " 高度為: " + newBitmap.getHeight();Log.v("martix", info);tvCompress.setText(info);imgvCompress.setImageBitmap(newBitmap); }把x,y縮放值分別設置成0.5f,可以看到壓縮后的圖片寬,高都是原圖寬高的1/2,圖片整體大小是原圖的1/4.
?
效果圖:
4.?質量壓縮
質量壓縮并不會減少bitmap占用的內存,bitmap的分辨率會和原圖保持一致。質量壓縮的原理是通過算法扣掉(同化)了 圖片中的一些某個點附近相近的像素,以此介紹圖片中的顏色數量,達到減少文件大小的目的。
質量壓縮測試代碼:
碼是:
bitmap.compress(Bitmap.CompressFormat.JPEG, quality, baos);其中quality是壓縮質量,100表示保持最佳質量壓縮效果,值越小表示壓縮效果越差。
如果上述方法的CompressFormat參數設置成Bitmap.CompressFormat.PNG,那么后面的quality參數將會失效,無論怎樣改變quality的值,壓縮后的文件都不會改變這是因為PNG是無損壓縮。
把quality設置成5,可以看下壓縮效果:
?
效果圖:
?
5.?設置RGB_565
設置RGB_565相比ARGB_8888減少了一半內存,這是因為RGB_565每個像素是2個字節存儲的,但是bitmap的寬和高并不會改變。
BitmapFactory.Options options = new BitmapFactory.Options(); options.inPreferredConfig = config; Bitmap bitmap = BitmapFactory.decodeFile(Environment.getExternalStorageDirectory().getAbsolutePath() + "/compresstest/test.png", options); if(bitmap != null) {String info = " 壓縮圖片大小: " + (bitmap.getByteCount()) + " 寬度為: " + bitmap.getWidth() + " 高度為: " + bitmap.getHeight();Log.v("rgb", info);tvCompress.setText(info);imgvCompress.setImageBitmap(bitmap); }以下是使用RGB_565壓縮的輸出:
?效果圖:
6.?使用createScaledBitmap
使用createScaledBitmap()方法可以把圖片壓縮成用戶期望任意尺寸的圖片,如果期望尺寸和圖片相差太大,會導致圖片失真。
Bitmap bitmap = BitmapFactory.decodeFile(Environment.getExternalStorageDirectory().getAbsolutePath() + "/compresstest/test.png"); String strx = edtvWidth.getText().toString(); String stry = edtvHeight.getText().toString();int width = 200; int height = 200; try {width = Integer.parseInt(strx);height = Integer.parseInt(stry); } catch (Exception e) {Toast.makeText(this, "請輸入有效數字內容", Toast.LENGTH_SHORT).show();e.printStackTrace();return ; } if(bitmap != null) {Bitmap newBitmap = Bitmap.createScaledBitmap(bitmap, width, height, true);String info = " width: " + width + " height: " + height + " 壓縮圖片大小: " + (newBitmap.getByteCount()) + " 寬度為: " + newBitmap.getWidth() + " 高度為: " + newBitmap.getHeight();Log.v("scale", info);tvCompress.setText(info);imgvCompress.setImageBitmap(newBitmap); }把寬高設置成200之后的效果:
?
?
可以看到,如果不按比例進行縮放設置,圖片是會拉伸,失真的。
本文的源碼比較簡單,就不上傳了,需要的留下郵箱私發。
?
總結
以上是生活随笔為你收集整理的android 图片压缩,bitmap压缩总结的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一文搞懂0.1UF和10UF电容并联使用
- 下一篇: createjs初学-关于Ticker