生活随笔
收集整理的這篇文章主要介紹了
Android压缩图片到100K以下并保持不失真的高效方法
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
在開發(fā)Android企業(yè)應(yīng)用時,會經(jīng)常上傳圖片到服務(wù)器,而我們公司目前維護(hù)的一個項目便是如此。該項目是通過私有apn與服務(wù)器進(jìn)行交互的,聯(lián)通的還好,但移動的速度實在太慢,客戶在使用軟件的過程中,由于上傳的信息中可能包含多張圖片,會經(jīng)常出現(xiàn)上傳圖片失敗的問題,為了解決這個問題,我們決定把照片壓縮到100k以下,并且保證圖片不失真(目前圖片經(jīng)過壓縮后,大約300k左右)。于是我就重新研究了一下Android的圖片壓縮技術(shù)。
Android端目錄結(jié)構(gòu)如下圖所示:
使用的第三方庫jar包,如下圖所示:
其中ksoap2-android-xxx.jar是Android用來調(diào)用webservice的,gson-xx.jar是把JavaBean轉(zhuǎn)成Json數(shù)據(jù)格式的。
本篇博客主要講解圖片壓縮的,核心代碼如下:
| 123456789
10
11
12
13 | //計算圖片的縮放值
public static int calculateInSampleSize(BitmapFactory.Options options,int reqWidth, int reqHeight) {final int height = options.outHeight;final int width = options.outWidth;int inSampleSize = 1;if (height > reqHeight || width > reqWidth) {final int heightRatio = Math.round((float) height/ (float) reqHeight);final int widthRatio = Math.round((float) width / (float) reqWidth);inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;}return inSampleSize;
}
|
| 123456789
10
11
12
13
14 | // 根據(jù)路徑獲得圖片并壓縮,返回bitmap用于顯示
public static Bitmap getSmallBitmap(String filePath) {final BitmapFactory.Options options = new BitmapFactory.Options();options.inJustDecodeBounds = true;BitmapFactory.decodeFile(filePath, options);// Calculate inSampleSizeoptions.inSampleSize = calculateInSampleSize(options, 480, 800);// Decode bitmap with inSampleSize setoptions.inJustDecodeBounds = false;return BitmapFactory.decodeFile(filePath, options);}
|
| 1
2
3
4
5
6
7
8
9 | //把bitmap轉(zhuǎn)換成String
public static String bitmapToString(String filePath) {Bitmap bm = getSmallBitmap(filePath);ByteArrayOutputStream baos = new ByteArrayOutputStream();bm.compress(Bitmap.CompressFormat.JPEG, 40, baos);byte[] b = baos.toByteArray();return Base64.encodeToString(b, Base64.DEFAULT);}
|
壓縮原理講解:壓縮一張圖片。我們需要知道這張圖片的原始大小,然后根據(jù)我們設(shè)定的壓縮比例進(jìn)行壓縮。
這樣我們就需要做3件事:
1.獲取原始圖片的長和寬
| 1
2
3
4
5 | BitmapFactory.Options options = new BitmapFactory.Options();options.inJustDecodeBounds = true;BitmapFactory.decodeFile(filePath, options);int height = options.outHeight;int width = options.outWidth;
|
以上代碼是對圖片進(jìn)行解碼,inJustDecodeBounds設(shè)置為true,可以不把圖片讀到內(nèi)存中,但依然可以計算出圖片的大小,這正好可以滿足我們第一步的需要。
2.計算壓縮比例
| 123456789
10 | int height = options.outHeight;int width = options.outWidth; int inSampleSize = 1;int reqHeight=800;int reqWidth=480;if (height > reqHeight || width > reqWidth) {final int heightRatio = Math.round((float) height/ (float) reqHeight);final int widthRatio = Math.round((float) width / (float) reqWidth); inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;}
|
一般手機(jī)的分辨率為 480*800 ,所以我們壓縮后圖片期望的寬度定為480,高度設(shè)為800,這2個值只是期望的寬度與高度,實際上壓縮后的實際寬度和高度會比期望的要大。如果圖片的原始高度或者寬度大于我們期望的寬度和高度,我們需要計算出縮放比例的數(shù)值。否則就不縮放。heightRatio是圖片原始高度與壓縮后高度的倍數(shù),widthRatio是圖片原始寬度與壓縮后寬度的倍數(shù)。inSampleSize為heightRatio與widthRatio中最小的那個,inSampleSize就是縮放值。 inSampleSize為1表示寬度和高度不縮放,為2表示壓縮后的寬度與高度為原來的1/2
3.縮放并壓縮圖片
| 1
2
3
4
5
6
7
8 | //在內(nèi)存中創(chuàng)建bitmap對象,這個對象按照縮放大小創(chuàng)建的options.inSampleSize = calculateInSampleSize(options, 480, 800);options.inJustDecodeBounds = false;Bitmap bitmap= BitmapFactory.decodeFile(filePath, options);ByteArrayOutputStream baos = new ByteArrayOutputStream();bm.compress(Bitmap.CompressFormat.JPEG, 60, baos);byte[] b = baos.toByteArray();
|
前3行的代碼其實已經(jīng)得到了一個縮放的bitmap對象,如果你在應(yīng)用中顯示圖片,就可以使用這個bitmap對象了。由于考慮到網(wǎng)絡(luò)流量的問題。我們需要犧牲圖片的質(zhì)量來換取一部分空間,這里調(diào)用bm.compress()方法進(jìn)行壓縮,這個方法的第二個參數(shù),如果是100,表示不壓縮,我這里設(shè)置的是60,你也可以更加你的需要進(jìn)行設(shè)置,在實驗的過程中我設(shè)置為30,圖片都不會失真。
壓縮效果:本demo可以把1.5M左右的圖片壓縮到100K左右,并且沒有失真。
效果圖如下:
更新:
| 123456789
10
11
12
13
14
15
16
17
18
19
20
21
22
23 | /*
壓縮圖片,處理某些手機(jī)拍照角度旋轉(zhuǎn)的問題
*/
public static String compressImage(Context context,String filePath,String fileName,int q) throws FileNotFoundException {Bitmap bm = getSmallBitmap(filePath);int degree = readPictureDegree(filePath);if(degree!=0){//旋轉(zhuǎn)照片角度bm=rotateBitmap(bm,degree);}File imageDir = SDCardUtils.getImageDir(context);File outputFile=new File(imageDir,fileName);FileOutputStream out = new FileOutputStream(outputFile);bm.compress(Bitmap.CompressFormat.JPEG, q, out);return outputFile.getPath();}
|
判斷照片角度
| 123456789
10
11
12
13
14
15
16
17
18
19
20
21
22
23 | public static int readPictureDegree(String path) {int degree = 0;try {ExifInterface exifInterface = new ExifInterface(path);int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION,ExifInterface.ORIENTATION_NORMAL);switch (orientation) {case ExifInterface.ORIENTATION_ROTATE_90:degree = 90;break;case ExifInterface.ORIENTATION_ROTATE_180:degree = 180;break;case ExifInterface.ORIENTATION_ROTATE_270:degree = 270;break;}} catch (IOException e) {e.printStackTrace();}return degree;}
|
旋轉(zhuǎn)照片
| 123456789
10 | public static Bitmap rotateBitmap(Bitmap bitmap,int degress) {if (bitmap != null) {Matrix m = new Matrix();m.postRotate(degress); bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),bitmap.getHeight(), m, true);return bitmap;}return bitmap;} |
總結(jié)
以上是生活随笔為你收集整理的Android压缩图片到100K以下并保持不失真的高效方法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。