請尊重他人的勞動成果,轉載請注明出處:[Android圖片壓縮技巧](http://blog.csdn.net/fengyuzhengfan/article/details/41759835)
[http://blog.csdn.net/fengyuzhengfan/article/details/41759835](http://blog.csdn.net/fengyuzhengfan/article/details/41759835)
當需要將Android客戶端的圖片上傳到服務器時,往往需要將圖片進行壓縮,關于圖片的壓縮方法,小編分享幾種常用的方式:
## 第一種方式:裁切以達到壓縮的目的
我曾在《[Android開發之裁剪照片](http://blog.csdn.net/fengyuzhengfan/article/details/39940587)》一文中詳細介紹過如何裁切照片,感興趣的朋友可以去看一下。
## 第二種方式:將圖片進行降質處理(即降低圖片的質量)以達到壓縮的目的
這種方式也是比較常用的方式,下面就為大家介紹如何對圖片進行降質:
將圖片降質我們可以使用Bitmap的這個方法:boolean android.graphics.Bitmap.compress(CompressFormat format, int quality, OutputStream stream)
其中,參數format表示壓縮后的格式,quality壓縮后的圖片質量(0表示最低,100表示不壓縮),stream表示要將壓縮后的圖片保存到的輸出流。
下面是詳細代碼:
~~~
/**
* 多線程壓縮圖片的質量
* @author JPH
* @param bitmap 內存中的圖片
* @param imgPath 圖片的保存路徑
* @date 2014-12-5下午11:30:43
*/
public static void compressImageByQuality(final Bitmap bitmap,final String imgPath){
new Thread(new Runnable() {//開啟多線程進行壓縮處理
@Override
public void run() {
// TODO Auto-generated method stub
ByteArrayOutputStream baos = new ByteArrayOutputStream();
options = 100;
bitmap.compress(Bitmap.CompressFormat.JPEG, options, baos);//質量壓縮方法,把壓縮后的數據存放到baos中 (100表示不壓縮,0表示壓縮到最小)
while (baos.toByteArray().length / 1024 > 100) {//循環判斷如果壓縮后圖片是否大于100kb,大于繼續壓縮
baos.reset();//重置baos即讓下一次的寫入覆蓋之前的內容
options -= 10;//圖片質量每次減少10
if(options<0)options=0;//如果圖片質量小于10,則將圖片的質量壓縮到最小值
bitmap.compress(Bitmap.CompressFormat.JPEG, options, baos);//將壓縮后的圖片保存到baos中
if(options==0)break;//如果圖片的質量已降到最低則,不再進行壓縮
}
try {
FileOutputStream fos = new FileOutputStream(new File(imgPath));//將壓縮后的圖片保存的本地上指定路徑中
fos.write(baos.toByteArray());
fos.flush();
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
~~~
方法解析:
由于此方法中包含I/O操作和遞歸調用比較耗時所以我采用了多線程去處理。
## 第三種方式:按比例縮小圖片的像素以達到壓縮的目的
此種方法主要是使用android.graphics.BitmapFactory.Options.Options()方法將圖片以指定的采用率加載到內存然后輸出到本地以達到壓縮像素的目的。
詳細代碼:
~~~
/**
* 按比例縮小圖片的像素以達到壓縮的目的
* @author JPH
* @param imgPath
* @date 2014-12-5下午11:30:59
*/
public static void compressImageByPixel(String imgPath) {
BitmapFactory.Options newOpts = new BitmapFactory.Options();
newOpts.inJustDecodeBounds = true;//只讀邊,不讀內容
Bitmap bitmap = BitmapFactory.decodeFile(imgPath, newOpts);
newOpts.inJustDecodeBounds = false;
int width = newOpts.outWidth;
int height = newOpts.outHeight;
float maxSize = 1000f;//默認1000px
int be = 1;
if (width > height && width > maxSize) {//縮放比,用高或者寬其中較大的一個數據進行計算
be = (int) (newOpts.outWidth / maxSize);
} else if (width < height && height > maxSize) {
be = (int) (newOpts.outHeight / maxSize);
}
be++;
newOpts.inSampleSize = be;//設置采樣率
newOpts.inPreferredConfig = Config.ARGB_8888;//該模式是默認的,可不設
newOpts.inPurgeable = true;// 同時設置才會有效
newOpts.inInputShareable = true;//。當系統內存不夠時候圖片自動被回收
bitmap = BitmapFactory.decodeFile(imgPath, newOpts);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
try {
FileOutputStream fos = new FileOutputStream(new File(imgPath));
fos.write(baos.toByteArray());
fos.flush();
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
~~~
## 第四種方式:將圖片先按比例壓縮然后再降質
此種方式主要結合第二種和第三種方法以下是詳細代碼:
~~~
/**
* 多線程壓縮圖片的質量
* @author JPH
* @param bitmap 內存中的圖片
* @param imgPath 圖片的保存路徑
* @date 2014-12-5下午11:30:43
*/
public static void compressImageByQuality(final Bitmap bitmap,final String imgPath){
new Thread(new Runnable() {//開啟多線程進行壓縮處理
@Override
public void run() {
// TODO Auto-generated method stub
ByteArrayOutputStream baos = new ByteArrayOutputStream();
options = 100;
bitmap.compress(Bitmap.CompressFormat.JPEG, options, baos);//質量壓縮方法,把壓縮后的數據存放到baos中 (100表示不壓縮,0表示壓縮到最小)
while (baos.toByteArray().length / 1024 > 100) {//循環判斷如果壓縮后圖片是否大于100kb,大于繼續壓縮
baos.reset();//重置baos即讓下一次的寫入覆蓋之前的內容
options -= 10;//圖片質量每次減少10
if(options<0)options=0;//如果圖片質量小于10,則將圖片的質量壓縮到最小值
bitmap.compress(Bitmap.CompressFormat.JPEG, options, baos);//將壓縮后的圖片保存到baos中
if(options==0)break;//如果圖片的質量已降到最低則,不再進行壓縮
}
try {
FileOutputStream fos = new FileOutputStream(new File(imgPath));//將壓縮后的圖片保存的本地上指定路徑中
fos.write(baos.toByteArray());
fos.flush();
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
/**
* 按比例縮小圖片的像素以達到壓縮的目的
* @author JPH
* @param imgPath
* @date 2014-12-5下午11:30:59
*/
public static void compressImageByPixel(String imgPath) {
BitmapFactory.Options newOpts = new BitmapFactory.Options();
newOpts.inJustDecodeBounds = true;//只讀邊,不讀內容
Bitmap bitmap = BitmapFactory.decodeFile(imgPath, newOpts);
newOpts.inJustDecodeBounds = false;
int width = newOpts.outWidth;
int height = newOpts.outHeight;
float maxSize = 1000f;//默認1000px
int be = 1;
if (width > height && width > maxSize) {//縮放比,用高或者寬其中較大的一個數據進行計算
be = (int) (newOpts.outWidth / maxSize);
} else if (width < height && height > maxSize) {
be = (int) (newOpts.outHeight / maxSize);
}
be++;
newOpts.inSampleSize = be;//設置采樣率
newOpts.inPreferredConfig = Config.ARGB_8888;//該模式是默認的,可不設
newOpts.inPurgeable = true;// 同時設置才會有效
newOpts.inInputShareable = true;//。當系統內存不夠時候圖片自動被回收
bitmap = BitmapFactory.decodeFile(imgPath, newOpts);
compressImageByQuality(bitmap,imgPath);//壓縮好比例大小后再進行質量壓縮
}
~~~