android中圖片是以bitmap形式存在的糙及,那么bitmap所占內存详幽,直接影響到了應用所占內存大小,首先要知道bitmap所占內存大小計算方式:
<font color="red" style="box-sizing: border-box;">圖片長度 x 圖片寬度 x 一個像素點占用的字節(jié)數</font>
以下是圖片的壓縮格式:
其中浸锨,A代表透明度唇聘;R代表紅色;G代表綠色柱搜;B代表藍色迟郎。
ALPHA_8
表示8位Alpha位圖,即A=8,一個像素點占用1個字節(jié),它沒有顏色,只有透明度
ARGB_4444
表示16位ARGB位圖,即A=4,R=4,G=4,B=4,一個像素點占4+4+4+4=16位聪蘸,2個字節(jié)
ARGB_8888
表示32位ARGB位圖宪肖,即A=8,R=8,G=8,B=8,一個像素點占8+8+8+8=32位表制,4個字節(jié)
RGB_565
表示16位RGB位圖,即R=5,G=6,B=5,它沒有透明度,一個像素點占5+6+5=16位,2個字節(jié)
我是用的小米手機2s來測試的控乾,從sd卡取出一個照片么介,如下所示:
bit = BitmapFactory.decodeFile(Environment
.getExternalStorageDirectory().getAbsolutePath()
+ "/DCIM/Camera/test.jpg");
Log.i("wechat", "壓縮前圖片的大小" + (bit.getByteCount() / 1024 / 1024)
+ "M寬度為" + bit.getWidth() + "高度為" + bit.getHeight());
出來的log是:
將取得的bitmap進行壓縮,下面開始說阱持,bitmap的幾種壓縮方式夭拌。
<a name="t0" style="box-sizing: border-box; background: transparent; color: rgb(79, 161, 219); text-decoration: none; margin: 0px; padding: 0px; font-weight: 400; outline: 0px;"></a>1.質量壓縮
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int quality = Integer.valueOf(editText.getText().toString());
bit.compress(CompressFormat.JPEG, quality, baos);
byte[] bytes = baos.toByteArray();
bm = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
Log.i("wechat", "壓縮后圖片的大小" + (bm.getByteCount() / 1024 / 1024)
+ "M寬度為" + bm.getWidth() + "高度為" + bm.getHeight()
+ "bytes.length= " + (bytes.length / 1024) + "KB"
+ "quality=" + quality);
其中quality是從edittext獲取的數字魔熏,可以從0–100改變衷咽,這里出來的log是:
可以看到,圖片的大小是沒有變的蒜绽,因為質量壓縮不會減少圖片的像素镶骗,它是在保持像素的前提下改變圖片的位深及透明度等,來達到壓縮圖片的目的躲雅,這也是為什么該方法叫質量壓縮方法鼎姊。那么,圖片的長相赁,寬相寇,像素都不變,那么bitmap所占內存大小是不會變的钮科。
但是我們看到bytes.length是隨著quality變小而變小的唤衫。這樣適合去傳遞二進制的圖片數據,比如微信分享圖片绵脯,要傳入二進制數據過去佳励,限制32kb之內。
這里要說蛆挫,如果是bit.compress(CompressFormat.PNG, quality, baos);這樣的png格式赃承,quality就沒有作用了,bytes.length不會變化悴侵,因為png圖片是無損的瞧剖,不能進行壓縮。
CompressFormat還有一個屬性是可免,CompressFormat.WEBP格式抓于,該格式是google自己推出來一個圖片格式,更多信息巴元,文末會貼出地址毡咏。
<a name="t1" style="box-sizing: border-box; background: transparent; color: rgb(79, 161, 219); text-decoration: none; margin: 0px; padding: 0px; font-weight: 400; outline: 0px;"></a>2.采樣率壓縮
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 2;
bm = BitmapFactory.decodeFile(Environment
.getExternalStorageDirectory().getAbsolutePath()
+ "/DCIM/Camera/test.jpg", options);
Log.i("wechat", "壓縮后圖片的大小" + (bm.getByteCount() / 1024 / 1024)
+ "M寬度為" + bm.getWidth() + "高度為" + bm.getHeight());
出來的log是
設置inSampleSize的值(int類型)后,假如設為2逮刨,則寬和高都為原來的1/2呕缭,寬高都減少了堵泽,自然內存也降低了。
我上面的代碼沒用過options.inJustDecodeBounds = true; 因為我是固定來取樣的數據恢总,為什么這個壓縮方法叫采樣率壓縮迎罗,是因為配合inJustDecodeBounds,先獲取圖片的寬片仿、高【這個過程就是取樣】纹安,然后通過獲取的寬高,動態(tài)的設置inSampleSize的值砂豌。
當inJustDecodeBounds設置為true的時候厢岂,BitmapFactory通過decodeResource或者decodeFile解碼圖片時,將會返回空(null)的Bitmap對象阳距,這樣可以避免Bitmap的內存分配塔粒,但是它可以返回Bitmap的寬度、高度以及MimeType筐摘。
<a name="t2" style="box-sizing: border-box; background: transparent; color: rgb(79, 161, 219); text-decoration: none; margin: 0px; padding: 0px; font-weight: 400; outline: 0px;"></a>3.縮放法壓縮(martix)
Matrix matrix = new Matrix();
matrix.setScale(0.5f, 0.5f);
bm = Bitmap.createBitmap(bit, 0, 0, bit.getWidth(),
bit.getHeight(), matrix, true);
Log.i("wechat", "壓縮后圖片的大小" + (bm.getByteCount() / 1024 / 1024)
+ "M寬度為" + bm.getWidth() + "高度為" + bm.getHeight());
出來的log是
可以看出來卒茬,bitmap的長度和寬度分別縮小了一半,圖片大小縮小了四分之一咖熟。
關于martix更多信息圃酵,文末會有一個參考文章。
<a name="t3" style="box-sizing: border-box; background: transparent; color: rgb(79, 161, 219); text-decoration: none; margin: 0px; padding: 0px; font-weight: 400; outline: 0px;"></a>4.RGB_565法
BitmapFactory.Options options2 = new BitmapFactory.Options();
options2.inPreferredConfig = Bitmap.Config.RGB_565;
bm = BitmapFactory.decodeFile(Environment
.getExternalStorageDirectory().getAbsolutePath()
+ "/DCIM/Camera/test.jpg", options2);
Log.i("wechat", "壓縮后圖片的大小" + (bm.getByteCount() / 1024 / 1024)
+ "M寬度為" + bm.getWidth() + "高度為" + bm.getHeight());
出來的log是:
我們看到圖片大小直接縮小了一半馍管,長度和寬度也沒有變郭赐,相比argb_8888減少了一半的內存。
<font color="red" style="box-sizing: border-box;">注意:由于ARGB_4444的畫質慘不忍睹咽斧,一般假如對圖片沒有透明度要求的話堪置,可以改成RGB_565,相比ARGB_8888將節(jié)省一半的內存開銷张惹。</font>
<a name="t4" style="box-sizing: border-box; background: transparent; color: rgb(79, 161, 219); text-decoration: none; margin: 0px; padding: 0px; font-weight: 400; outline: 0px;"></a>5.createScaledBitmap
bm = Bitmap.createScaledBitmap(bit, 150, 150, true);
Log.i("wechat", "壓縮后圖片的大小" + (bm.getByteCount() / 1024) + "KB寬度為"
+ bm.getWidth() + "高度為" + bm.getHeight());
出來的log是
這里是將圖片壓縮成用戶所期望的長度和寬度舀锨,但是這里要說,如果用戶期望的長度和寬度和原圖長度寬度相差太多的話宛逗,圖片會很不清晰坎匿。
<a name="t5" style="box-sizing: border-box; background: transparent; color: rgb(79, 161, 219); text-decoration: none; margin: 0px; padding: 0px; font-weight: 400; outline: 0px;"></a>總結
以上就是5種圖片壓縮的方法,這里需要強調雷激,他們的壓縮僅僅只是對android中的bitmap來說的替蔬。如果將這些壓縮后的bitmap另存為sd中,他們的內存大小并不一樣屎暇。
android手機中承桥,圖片的所占的內存大小和很多因素相關,計算起來也很麻煩根悼。為了計算出一個圖片的內存大小凶异,可以將圖片當做一個文件來間接計算蜀撑,用如下的方法:
File file = new File(Environment.getExternalStorageDirectory()
.getAbsolutePath() + "/DCIM/Camera/test.jpg");
Log.i("wechat", "file.length()=" + file.length() / 1024);
或者
FileInputStream fis = null;
try {
fis = new FileInputStream(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
try {
Log.i("wechat", "fis.available()=" + fis.available() / 1024);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
上面兩個方法計算的結果是一樣的。
<font color="red" style="box-sizing: border-box;">看完了這篇內容剩彬,其實說白了酷麦,Bitmap壓縮都是圍繞這個來做文章:Bitmap所占用的內存 = 圖片長度 x 圖片寬度 x 一個像素點占用的字節(jié)數。3個參數喉恋,任意減少一個的值沃饶,就達到了壓縮的效果。</font>
參考文章:
Android Bitmap 優(yōu)化(1) - 圖片壓縮http://anany.me/2015/10/15/bitmap1/
多圖比較谷歌WebP和JPEG圖像格式http://www.win7china.com/html/8668.html
Android-使用Matrix對Bitmap進行處理http://blog.csdn.net/nupt123456789/article/details/24600055