Android圖片壓縮

來源:互聯網
上載者:User

標籤:

好長時間沒寫部落格了,最近忙著畢業的事。其實我一直想寫一篇關於圖片壓縮的部落格,寫部落格其實也是為了整理一下自己學過的知識和思路作為記錄。

Android的圖片壓縮不僅是在移動開發中是痛點,在任何語言中處理起來都不是特別簡單。一般來說分為兩種:尺寸壓縮和品質壓縮,這兩種是最常見的,在APP開發過程中圖片上傳最是很常見的了,現在市面上的手機像素都非常高,比如Vivo手機一張圖片差不多得15M左右,這對於使用者來說就太痛苦了,上傳一張圖片,這個月的流量就沒了,咱們不能這麼幹,得把圖片壓縮到一定的程度再上傳比較貼切。下面提供兩種壓縮圖片的方式:

一、尺寸壓縮的方法一(根據圖片的路徑進行壓縮):

/** * 圖片按比例大小壓縮方法(根據路徑擷取圖片並壓縮) *  * @param srcPath * @return */public static Bitmap getimage(String srcPath) {BitmapFactory.Options newOpts = new BitmapFactory.Options();// 開始讀入圖片,此時把options.inJustDecodeBounds 設回true了newOpts.inJustDecodeBounds = true;Bitmap bitmap = BitmapFactory.decodeFile(srcPath, newOpts);// 此時返回Bitmap為空白newOpts.inJustDecodeBounds = false;int w = newOpts.outWidth;int h = newOpts.outHeight;// 現在主流手機比較多是800*480解析度,所以高和寬我們設定為float hh = 800f;// 這裡設定高度為800ffloat ww = 480f;// 這裡設定寬度為480f// 縮放比。由於是固定比例縮放,只用高或者寬其中一個資料進行計算即可int be = 1;// be=1表示不縮放if (w > h && w > ww) {// 如果寬度大的話根據寬度固定大小縮放be = (int) (newOpts.outWidth / ww);} else if (w < h && h > hh) {// 如果高度高的話根據寬度固定大小縮放be = (int) (newOpts.outHeight / hh);}if (be <= 0)be = 1;newOpts.inSampleSize = be;// 設定縮放比例// 重新讀入圖片,注意此時已經把options.inJustDecodeBounds 設回false了bitmap = BitmapFactory.decodeFile(srcPath, newOpts);// 壓縮好比例大小後再進行品質壓縮return compressImage(bitmap);}
二、尺寸壓縮的方法二(根據圖片的Bitmap進行壓縮):

/** * 圖片按比例大小壓縮方法(根據Bitmap圖片壓縮) *  * @param image * @return */public static Bitmap comp(Bitmap image) {ByteArrayOutputStream baos = new ByteArrayOutputStream();image.compress(Bitmap.CompressFormat.JPEG, 100, baos);// 判斷如果圖片大於1M,進行壓縮避免在產生圖片(BitmapFactory.decodeStream)時溢出if (baos.toByteArray().length / 1024 > 1024) {// 重設BAOS即清空BAOSbaos.reset();// 這裡壓縮50%,把壓縮後的資料存放到BAOS中image.compress(Bitmap.CompressFormat.JPEG, 50, baos);}ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());BitmapFactory.Options newOpts = new BitmapFactory.Options();// 開始讀入圖片,此時把options.inJustDecodeBounds 設回true了newOpts.inJustDecodeBounds = true;Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, newOpts);newOpts.inJustDecodeBounds = false;int w = newOpts.outWidth;int h = newOpts.outHeight;// 現在主流手機比較多是800*480解析度,所以高和寬我們設定為float hh = 800f;// 這裡設定高度為800ffloat ww = 480f;// 這裡設定寬度為480f// 縮放比。由於是固定比例縮放,只用高或者寬其中一個資料進行計算即可int be = 1;// be=1表示不縮放// 如果寬度大的話根據寬度固定大小縮放if (w > h && w > ww) {be = (int) (newOpts.outWidth / ww);// 如果高度高的話根據寬度固定大小縮放} else if (w < h && h > hh) {be = (int) (newOpts.outHeight / hh);}if (be <= 0)be = 1;newOpts.inSampleSize = be;// 設定縮放比例// 重新讀入圖片,注意此時已經把options.inJustDecodeBounds 設回false了isBm = new ByteArrayInputStream(baos.toByteArray());bitmap = BitmapFactory.decodeStream(isBm, null, newOpts);// 壓縮好比例大小後再進行品質壓縮return compressImage(bitmap);}
但是有的時候單純的使用尺寸壓縮並不能壓縮到你自己需要的記憶體大小,而且如果用尺寸壓縮力度太大,會導致圖片失真,可以看到上面的代碼進行尺寸壓縮之後隨之又調用了一個方法compressImage(bitmap);這個方法是品質壓縮,將尺寸壓縮和品質壓縮結合使用,這樣的優點是圖片壓縮之後不會失真。

三、圖片的品質壓縮(抽取部分像素)

/** * 圖片的品質壓縮 *  * @param image * @return */public static Bitmap compressImage(Bitmap image) {ByteArrayOutputStream baos = new ByteArrayOutputStream();// 品質壓縮方法,這裡100表示不壓縮,把壓縮後的資料存放到BAOS中image.compress(Bitmap.CompressFormat.JPEG, 100, baos);int options = 100;// 迴圈判斷如果壓縮後圖片是否大於100kb,大於繼續壓縮while (baos.toByteArray().length / 1024 > 100) { // 重設BAOS即清空BAOSbaos.reset();// 這裡壓縮options%,把壓縮後的資料存放到BAOS中image.compress(Bitmap.CompressFormat.JPEG, options, baos);// 每次都減少10options -= 10;}// 把壓縮後的資料BAOS存放到ByteArrayInputStream中ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());// 把ByteArrayInputStream資料產生圖片Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);return bitmap;}
下面是我所用到的圖片處理的工具類,大家可以copy直接使用:

package com.reduce_weight.utils;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.File;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.util.Date;import android.annotation.SuppressLint;import android.graphics.Bitmap;import android.graphics.BitmapFactory;public class PictureUtil {/** * 將bitmap位元影像儲存到path路徑下 * * @param bitmap */@SuppressLint("SdCardPath")public static String saveBitmap(Bitmap bitmap) {File filePath = new File("/sdcard/圖片緩衝/");if (!filePath.exists()) {filePath.mkdir();}File file = new File("/sdcard/圖片緩衝/", new Date().getTime()+ "temp.png");// 建立檔案if (file.exists()) {file.delete();}try {FileOutputStream out = new FileOutputStream(file);bitmap.compress(Bitmap.CompressFormat.PNG, 90, out);out.flush();out.close();} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}return file.getAbsolutePath();}/** * 圖片按比例大小壓縮方法(根據路徑擷取圖片並壓縮) *  * @param srcPath * @return */public static Bitmap getimage(String srcPath) {BitmapFactory.Options newOpts = new BitmapFactory.Options();// 開始讀入圖片,此時把options.inJustDecodeBounds 設回true了newOpts.inJustDecodeBounds = true;Bitmap bitmap = BitmapFactory.decodeFile(srcPath, newOpts);// 此時返回Bitmap為空白newOpts.inJustDecodeBounds = false;int w = newOpts.outWidth;int h = newOpts.outHeight;// 現在主流手機比較多是800*480解析度,所以高和寬我們設定為float hh = 800f;// 這裡設定高度為800ffloat ww = 480f;// 這裡設定寬度為480f// 縮放比。由於是固定比例縮放,只用高或者寬其中一個資料進行計算即可int be = 1;// be=1表示不縮放if (w > h && w > ww) {// 如果寬度大的話根據寬度固定大小縮放be = (int) (newOpts.outWidth / ww);} else if (w < h && h > hh) {// 如果高度高的話根據寬度固定大小縮放be = (int) (newOpts.outHeight / hh);}if (be <= 0)be = 1;newOpts.inSampleSize = be;// 設定縮放比例// 重新讀入圖片,注意此時已經把options.inJustDecodeBounds 設回false了bitmap = BitmapFactory.decodeFile(srcPath, newOpts);// 壓縮好比例大小後再進行品質壓縮return compressImage(bitmap);}/** * 圖片按比例大小壓縮方法(根據Bitmap圖片壓縮) *  * @param image * @return */public static Bitmap comp(Bitmap image) {ByteArrayOutputStream baos = new ByteArrayOutputStream();image.compress(Bitmap.CompressFormat.JPEG, 100, baos);// 判斷如果圖片大於1M,進行壓縮避免在產生圖片(BitmapFactory.decodeStream)時溢出if (baos.toByteArray().length / 1024 > 1024) {// 重設BAOS即清空BAOSbaos.reset();// 這裡壓縮50%,把壓縮後的資料存放到BAOS中image.compress(Bitmap.CompressFormat.JPEG, 50, baos);}ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());BitmapFactory.Options newOpts = new BitmapFactory.Options();// 開始讀入圖片,此時把options.inJustDecodeBounds 設回true了newOpts.inJustDecodeBounds = true;Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, newOpts);newOpts.inJustDecodeBounds = false;int w = newOpts.outWidth;int h = newOpts.outHeight;// 現在主流手機比較多是800*480解析度,所以高和寬我們設定為float hh = 800f;// 這裡設定高度為800ffloat ww = 480f;// 這裡設定寬度為480f// 縮放比。由於是固定比例縮放,只用高或者寬其中一個資料進行計算即可int be = 1;// be=1表示不縮放// 如果寬度大的話根據寬度固定大小縮放if (w > h && w > ww) {be = (int) (newOpts.outWidth / ww);// 如果高度高的話根據寬度固定大小縮放} else if (w < h && h > hh) {be = (int) (newOpts.outHeight / hh);}if (be <= 0)be = 1;newOpts.inSampleSize = be;// 設定縮放比例// 重新讀入圖片,注意此時已經把options.inJustDecodeBounds 設回false了isBm = new ByteArrayInputStream(baos.toByteArray());bitmap = BitmapFactory.decodeStream(isBm, null, newOpts);// 壓縮好比例大小後再進行品質壓縮return compressImage(bitmap);}/** * 圖片的品質壓縮 *  * @param image * @return */public static Bitmap compressImage(Bitmap image) {ByteArrayOutputStream baos = new ByteArrayOutputStream();// 品質壓縮方法,這裡100表示不壓縮,把壓縮後的資料存放到BAOS中image.compress(Bitmap.CompressFormat.JPEG, 100, baos);int options = 100;// 迴圈判斷如果壓縮後圖片是否大於100kb,大於繼續壓縮while (baos.toByteArray().length / 1024 > 100) { // 重設BAOS即清空BAOSbaos.reset();// 這裡壓縮options%,把壓縮後的資料存放到BAOS中image.compress(Bitmap.CompressFormat.JPEG, options, baos);// 每次都減少10options -= 10;}// 把壓縮後的資料BAOS存放到ByteArrayInputStream中ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());// 把ByteArrayInputStream資料產生圖片Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);return bitmap;}}
本人在項目中用的就是這種方式進行的壓縮,上傳到伺服器都在100K以下,而且圖片開啟還是比較清楚的,感覺這種壓縮方式還是比較靠譜的,大家如果有好的方式可以直接留言告訴我,我們一起共同學習。




Android圖片壓縮

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.