參考:
1.https://blog.csdn.net/pbm863521/article/details/74391787
2.https://www.jianshu.com/p/871f0c1f0006
1.背景:
最近一個項目的開發,需要用到相機拍照,裁剪(使用的是ucrop,推薦使用),保存,上傳圖片到七牛雲的操作,並在上傳的過程中遇到了圖片過大,服務器返回溢出的錯誤,難搞哦。在其中發現,如果調用系統的相機,拍出來的圖片會有5M的大小,但是調用美圖相機的應用,拍照大小隻有500k不到,但是用戶的手機不可能每個都裝美圖相機軟件,所以需要對圖片進行壓縮。
2.方法:
網上大致的方法分爲三種,質量壓縮,按比例大小壓縮(尺寸壓縮),採樣率壓縮,常用到的有兩種,其中採樣率壓縮不太常用,故不作過多的闡述。主要說一下其他兩種。
2.1 質量壓縮
保持像素的前提下改變圖片的位深及透明度(即:通過算法抹掉(同化)圖片中的一些某點附近 相近的像素)達到降低質量壓縮文件的目的。
2.2 尺寸壓縮
通過減少單位尺寸的像素值,真正意義上的降低像素(通過縮放圖片像素來減少圖片佔用內存大小)
2.3 第三方開源庫
近期看資料的時候看到的,魯班(luban),據說逆向微信圖片壓縮算法得來的,雖不能完全達到微信效果,但是也很可觀了,github上Star已經11K+了,我還沒試過,小夥伴可以嘗試:https://github.com/Curzibn/Luban
3.代碼 (親測可用)
3.1 指定圖片大小,使用縮放,質量壓縮的方式將圖片壓縮到 100 k以內
/**
* 圖片按比例大小壓縮方法
*
* @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);// 此時返回bm爲空
newOpts.inJustDecodeBounds = false;
int w = newOpts.outWidth;
int h = newOpts.outHeight;
float hh = 1920f;// 這裏設置高度爲1920f
float ww = 1080f;// 這裏設置寬度爲1080f
// 縮放比。由於是固定比例縮放,只用高或者寬其中一個數據進行計算即可
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);// 壓縮好比例大小後再進行質量壓縮
}
/**
* 質量壓縮方法
*
* @param image
* @return
*/
public static Bitmap compressImage(Bitmap image) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG, 100, baos);// 質量壓縮方法,這裏100表示不壓縮,把壓縮後的數據存放到baos中
int options = 90;
while (baos.toByteArray().length / 1024 > 100) { // 循環判斷如果壓縮後圖片是否大於100kb,大於繼續壓縮
baos.reset(); // 重置baos即清空baos
image.compress(Bitmap.CompressFormat.JPEG, options, baos);// 這裏壓縮options%,把壓縮後的數據存放到baos中
options -= 10;// 每次都減少10
}
ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());// 把壓縮後的數據baos存放到ByteArrayInputStream中
Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);// 把ByteArrayInputStream數據生成圖片
return bitmap;
}
3.2 將Bitmap保存到本地手機路徑
/**
* 保存Bitmap到指定文件
* @param bitmap 需要保存的圖片
* @param file 保存的文件路徑
*/
public static void saveBitmap(Bitmap bitmap, File file) {
try {
FileOutputStream fos = new FileOutputStream(file);
// 這兩保存的時候我選擇了70的質量
bitmap.compress(Bitmap.CompressFormat.JPEG, 70, fos);
fos.flush();
fos.close();
} catch (Exception e) {
PLog.e("saveBitmap err11 = ", e);
}
}
4.總結
開發一個項目的過程中,會遇到很多困難,中間會遇到各種各樣的問題,會百度各種各種的問題,也會test各種方法,有用或沒用,可以在旁邊新建一個記事本,將用到的,可用的,方法記錄下來,包括參考的博客地址,記錄可以雜亂一點,但不影響。這樣在項目結束之後,有了充足的時間,然後再去一點點整理,由淺及深,慢慢的去看這些博客,梳理成自己的知識。這樣在下次遇到這些問題的時候,就會有一種我遇到過,我知道怎麼解決,對於預言項目週期,以及自身成長都有不錯的效果。