国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統(tǒng) > Android > 正文

Android圖片壓縮以及優(yōu)化實例

2019-10-22 18:35:28
字體:
供稿:網(wǎng)友

前言

圖片壓縮在Android技術(shù)中已經(jīng)屬于爛大街,上周看了2個開源庫然后對自己項目的壓縮做了對比,發(fā)現(xiàn)一些新東西,記錄與此。

為何要壓縮

1、體積的原因

如果你的圖片是要準(zhǔn)備上傳的,那動輒幾M的大小肯定不行的,況且圖片分辨率大于設(shè)備分辨率的話毫無意義。

2、內(nèi)存原因

如果圖片要顯示下Android設(shè)備上,ImageView最終是要加載Bitmap對象的,就要考慮單個Bitmap對象的內(nèi)存占用了,如何計算一張圖片的加載到內(nèi)存的占用呢?其實就是所有像素的內(nèi)存占用總和:

bitmap內(nèi)存大小 = 圖片長度 x 圖片寬度 x 單位像素占用的字節(jié)數(shù)

起決定因素就是最后那個參數(shù)了,Bitmap'常見有2種編碼方式:ARGB_8888和RGB_565,ARGB_8888每個像素點4個byte,RGB_565是2個byte,一般都采用ARGB_8888這種。那么常見的1080*1920的圖片內(nèi)存占用就是:

1920 x 1080 x 4 = 7.9M

壓縮原理

從上面可以總結(jié)出,圖片壓縮應(yīng)該從兩個方面入手同時進行:先是降低分辨率,然后降低每個像素的質(zhì)量也就是內(nèi)存占用。

分辨率壓縮

假設(shè)有張原圖是3840x2400,我想壓縮成1920x1080,實際是不可能100%能壓縮這個值的。因為圖片壓縮要保證寬高比,試想一下800x100的橫向圖可能壓成20x200豎向圖嗎? 不可能的.。這里常見的算法就是在1920x1080的范圍內(nèi)保證較短邊,然后按照比例壓縮整個圖:

這里原圖的寬高比是 3840/2400 = 1.6,目標(biāo)圖的寬高比是1920/1080 = 1.78>1.6,較短邊是高。所以就應(yīng)該按照高的比例來壓縮。

2400/1080=2.22,這樣真實目標(biāo)值就是:1728x1080,壓縮比四舍五入是:2,然后通過下面代碼進行壓縮:

 private Bitmap compressPixel(String filePath){  Bitmap bmp = null;  BitmapFactory.Options options = new BitmapFactory.Options();  //setting inSampleSize value allows to load a scaled down version of the original image  options.inSampleSize = 2;  //inJustDecodeBounds set to false to load the actual bitmap  options.inJustDecodeBounds = false;  options.inTempStorage = new byte[16 * 1024];  try {   //load the bitmap from its path   bmp = BitmapFactory.decodeFile(filePath, options);   if (bmp == null) {    InputStream inputStream = null;    try {     inputStream = new FileInputStream(filePath);     BitmapFactory.decodeStream(inputStream, null, options);     inputStream.close();    } catch (FileNotFoundException exception) {     exception.printStackTrace();    } catch (IOException exception) {     exception.printStackTrace();    }   }  } catch (OutOfMemoryError exception) {   exception.printStackTrace();  }finally {   return bmp;  } }

看起來沒什么問題,看看實測結(jié)果,原圖 3840*2400,大小2.2M,我選4個分辨率當(dāng)做目標(biāo)值來壓縮:

Android圖片壓縮,Android圖片壓縮優(yōu)化

可以看出壓縮后的4張圖沒有一張達到目標(biāo)值,而且偏差較大,原因就是options.inSampleSize這個屬性,他只能是2的N次方,如果算出來是7,Android會取近似值8,以此類推導(dǎo)致這個值不能壓縮到目標(biāo)值。看了一下Compressor這個開源庫他對此做了處理,把壓縮后的圖片在Canvas上面按照目標(biāo)尺寸重繪,得到一個新的bitmap:

核心代碼:

Matrix scaleMatrix = new Matrix();  scaleMatrix.setScale(ratioX, ratioY, 0, 0);  Canvas canvas = new Canvas(scaledBitmap);  canvas.setMatrix(scaleMatrix);  canvas.drawBitmap(bmp, 0, 0, new Paint(Paint.FILTER_BITMAP_FLAG));

用Compressor開源庫壓縮的圖片對比下:

Android圖片壓縮,Android圖片壓縮優(yōu)化

可以看出每次都能壓縮到真實目標(biāo)值。(注意不是目標(biāo)值,注意區(qū)分目標(biāo)值和真實目標(biāo)值)

質(zhì)量壓縮

Bitmap有個方法 compress(CompressFormat format, int quality, OutputStream stream),quality就是壓縮質(zhì)量傳入0-100,數(shù)值越小壓縮的越厲害。

不過我們一般不直接設(shè)置這個數(shù)值,而是自定義一個壓縮后大小比如300KB,然后動態(tài)計算這個quality,核心代碼:

//進行有損壓縮ByteArrayOutputStream baos = new ByteArrayOutputStream();int options_ = 100;actualOutBitmap.compress(Bitmap.CompressFormat.JPEG, options_, baos);//質(zhì)量壓縮方法,把壓縮后的數(shù)據(jù)存放到baos中 (100表示不壓縮,0表示壓縮到最小)int baosLength = baos.toByteArray().length;while (baosLength / 1024 > maxFileSize) {//循環(huán)判斷如果壓縮后圖片是否大于maxMemmorrySize,大于繼續(xù)壓縮 baos.reset();//重置baos即讓下一次的寫入覆蓋之前的內(nèi)容 options_ = Math.max(0, options_ - 10);//圖片質(zhì)量每次減少10 actualOutBitmap.compress(Bitmap.CompressFormat.JPEG, options_, baos);//將壓縮后的圖片保存到baos中 baosLength = baos.toByteArray().length; if (options_ == 0)//如果圖片的質(zhì)量已降到最低則,不再進行壓縮 break;}

壓縮實踐

目前成熟的開源庫有Luban:https://github.com/Curzibn/Luban

這個開源庫算法比較復(fù)雜,根據(jù)效果圖前后對比逆向推算了微信朋友圈的壓縮,最后效果和微信差不多,如果你對壓縮要求很高可以使用這個。不過方法調(diào)用是異步的,回調(diào)形式反饋結(jié)果,這個不太好。。

Compressor:https://github.com/zetbaitsu/Compressor

這個開源庫就是在普通的壓縮算法上做了優(yōu)化改進,源碼很容易看懂,推薦!下面是用Compressor對三張大圖不同目標(biāo)值做的壓縮測試(BV是我們項目的壓縮,忽略就好),質(zhì)量參數(shù)設(shè)的是80%

Android圖片壓縮,Android圖片壓縮優(yōu)化

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持VEVB武林網(wǎng)。


注:相關(guān)教程知識閱讀請移步到Android開發(fā)頻道。
發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 德钦县| 富顺县| 中西区| 大石桥市| 德保县| 右玉县| 双柏县| 榆林市| 林甸县| 土默特左旗| 沅江市| 晋中市| 邵东县| 深水埗区| 从化市| 巴里| 图片| 射阳县| 清原| 阜宁县| 武川县| 江都市| 辽中县| 肥西县| 大渡口区| 石嘴山市| 香河县| 攀枝花市| 简阳市| 东安县| 乌拉特前旗| 凉城县| 南木林县| 社会| 镇雄县| 安徽省| 章丘市| 夏津县| 连城县| 松滋市| 云梦县|