關(guān)鍵詞: Bitmap,質(zhì)量壓縮,比例壓縮,采樣率壓縮,微信分享
前言
android 系統(tǒng)的圖片壓縮大體上有三種方式词爬,質(zhì)量壓縮矿酵,比例壓縮给涕,采樣率壓縮
一般最簡單直觀的應(yīng)該是bitmap.compress方法著拭,把位圖的壓縮信息寫入到一個(gè)指定的輸出流帅容,其中有一個(gè)參數(shù)quality,取值0-100银伟,數(shù)值越小你虹,輸出流越小。但是無論是質(zhì)量壓縮彤避,比例壓縮傅物,還是采樣率壓縮,單獨(dú)使用可能都沒法達(dá)到理想的效果琉预。比如微信的32k限制董饰,單純的質(zhì)量壓縮就無法達(dá)到要求。所以我不得不花些時(shí)間分析這三種壓縮方式圆米,最后把這三種方式結(jié)合在一起卒暂,才得出了一個(gè)比較理想的壓縮結(jié)果,以下是對(duì)這幾種壓縮方式的一個(gè)整理娄帖。
質(zhì)量壓縮
1.代碼:
public static Bitmap getCompressBitmapByQuality(Bitmap bitmap, int quality) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, quality, outputStream);
ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
return BitmapFactory.decodeStream(inputStream, null, null);
}
2.關(guān)于質(zhì)量壓縮
關(guān)于質(zhì)量壓縮需要注意的是質(zhì)量壓縮只改變了圖片的位深及透明度也祠,但是并沒有改變Bitmap在內(nèi)存中的大小
即上邊的代碼只改變了ByteArrayOutputStream 的大小,如果把壓縮過的Bitmap保存到文件中块茁,文件的大小會(huì)變小齿坷,但是Bitmap本身的大小不會(huì)變
這里有一個(gè)延伸的知識(shí)點(diǎn):Bitmap在內(nèi)存中的占用大小是由什么決定的呢?
google對(duì)于bitmap大小的獲取在不同的API版本中有不同的方法
Api 19: 以上用getAllocationByteCount()
Api 12: 以上用getByteCount()
更早: 自己算:-)
我們可以先看看這個(gè)函數(shù) Bitmap.getByteCount()
/**
* Returns the minimum number of bytes that can be used to store this bitmap's pixels.
*
* <p>As of {@link android.os.Build.VERSION_CODES#KITKAT}, the result of this method can
* no longer be used to determine memory usage of a bitmap. See {@link
* #getAllocationByteCount()}.</p>
*/
public final int getByteCount() {
// int result permits bitmaps up to 46,340 x 46,340
return getRowBytes() * getHeight();
}
其中getRowBytes() 是bitmap 中每一行所占的比特?cái)?shù)桂肌,乘以bitmap的高度getHeight(),就是bitmap在內(nèi)存中所占用的空間大小,其中g(shù)etRowBytes()和bitmap的寬度還有bitmap所使用的色彩格式有關(guān)系永淌,比如如果使用的是ARGB_8888 那么getRowBytes()的大小就是bitmap.getWidth()4,乘以4*的原因是在ARGB_8888的色彩格式中崎场,每個(gè)像素點(diǎn)占4位。
android系統(tǒng)中的色彩模式有一下幾種
Bitmap.Config | 值 | 描述 | 占用內(nèi)存(字節(jié)) |
---|---|---|---|
Bitmap.Config | ARGB_8888 | 表示32位的ARGB位圖 | 4 |
Bitmap.Config | ARGB_4444 | 表示16位的ARGB位圖 | 2 |
Bitmap.Config | RGB_565 | 表示16位的RGB位圖 | 2 |
Bitmap.Config | ALPHA_8 | 表示8位的Alpha位圖 | 1 |
由此可見bitmap在內(nèi)存中的大小相關(guān)的因素是:像素點(diǎn),分辨率(寬x高),色彩模式
比例壓縮
1.代碼
public static Bitmap getCompressBitmapByScale(Bitmap bitmap, int maxW, int maxH) {
int w = bitmap.getWidth();
int h = bitmap.getHeight();
float sx = (float) maxW / (float) w;
float sy = (float) maxH / (float) h;
Matrix matrix = new Matrix();
matrix.setScale(sx, sy);
return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
}
2.關(guān)于比例壓縮
比例壓縮通過改變bitmap的寬高遂蛀,可以顯著改變圖片大小谭跨,但是如果縮放過度了,圖片也會(huì)完全糊掉李滴。一般會(huì)按照一個(gè)指定的比例(比如 scale=0.8)循環(huán)縮放,直到壓到合適的尺寸
采樣率壓縮
1.代碼
public static Bitmap getCompressBitmapBySampleSize(Bitmap bitmap, int sampleSize) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = sampleSize;
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
return BitmapFactory.decodeByteArray(outputStream.toByteArray(), 0, outputStream.toByteArray().length, options);
}
2.關(guān)于采樣率
采樣率為1的時(shí)候?yàn)樵即笮◇χ妫瑸?的時(shí)候,寬高為原來的1/2所坯,像素?cái)?shù)和占用內(nèi)存數(shù)為原來1/4,采樣率是2的指數(shù)谆扎。
谷歌提供的一個(gè)關(guān)于采樣率的計(jì)算方法:
public static int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) >= reqHeight
&& (halfWidth / inSampleSize) >= reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
分享到微信的壓縮算法
最后提供一個(gè)分享到微信的壓縮算法,基本上是結(jié)合了采樣率壓縮芹助,比例壓縮和質(zhì)量壓縮,在把圖片壓縮到指定大小的同時(shí)堂湖,盡可能保證圖片的清晰度
這是一個(gè)圖片壓縮的demo,三種壓縮方式都有一個(gè)簡單的實(shí)現(xiàn)
https://github.com/jhwing/ImageCompress
這是一個(gè)社會(huì)化分享的sdk状土,支持微信无蜂,微博,qq蒙谓,三個(gè)平臺(tái)的分享功能,關(guān)于圖片壓縮的算法在這個(gè)sdk里
https://github.com/jhwing/SKShare
延伸閱讀
http://www.cnblogs.com/hrlnw/p/4403334.html
http://blog.csdn.net/lsyz0021/article/details/51356670
https://github.com/bither/bither-android-lib/blob/master/REASON.md
http://blog.csdn.net/angel1hao/article/details/51890938
https://github.com/zetbaitsu/Compressor
https://developer.android.com/training/displaying-bitmaps/load-bitmap.html