上個項目做了一個圖片批量上傳,要求壓縮到規定大小和尺寸,並且加文字跟圖片水印。花了好長時間才完成,在此記錄一下以方便以後使用。
/**
* 壓縮圖片,保持圖片寬高在768*1024之內(圖片寬高不進行拉伸,等比縮放) 大小在120k以下
* 並且添加圖片文字水印
*
* @param srcPath 文件路徑
* @param context Activity
* @param savePath 保存路徑
* @param fileName 文件名
*/
public void compress(String srcPath, Activity context, String savePath, String fileName) throws IOException {
//設置目標範圍爲1024*768;
float hh = 1024;
float ww = 768;
//讀取bitmap
BitmapFactory.Options opts = new BitmapFactory.Options();
//設置只讀取大小(防止內存溢出)
opts.inJustDecodeBounds = true;
BitmapFactory.decodeFile(srcPath, opts);
int w = opts.outWidth;
int h = opts.outHeight;
int zoom; //大小縮放級別
Bitmap bitmap = null;
Bitmap result = null;
//判斷原圖寬高,進行粗略縮放防止精確縮放時內存溢出(縮放後的圖片)
//如果寬高都小於目標寬高
if (w < ww && h < hh) {
//不進行縮放,直接讀取bitmap
opts.inJustDecodeBounds = false;
result = BitmapFactory.decodeFile(srcPath, opts);
} else {
//圖片寬高不在768*1024之內,粗略縮放(縮放結果寬高仍然不在768*1024之內,但是尺寸肯定會小於等於現在尺寸,這樣來防止內存溢出)
//如果寬度縮放比大於高度縮放比,則按照寬度縮放(保持圖片寬高比)
if (w / ww >= h / hh) {
zoom = (int) (w / ww);
} else {
//如果高度縮放比大於寬度縮放比,則按照高度縮放
zoom = (int) (h / hh);
}
//最小爲1,不進行縮放
if (zoom < 1) {
zoom = 1;
}
opts.inSampleSize = zoom;
//設置讀取bitmap
opts.inJustDecodeBounds = false;
//讀出粗略縮放的bitmap
bitmap = BitmapFactory.decodeFile(srcPath, opts);
//精確縮放(寬高在768*1024之內,圖片等比縮放)
int w1; //目標寬度
int h1; //目標高度
//寬度縮放到768,高度等比縮放
if (bitmap.getWidth() / ww >= bitmap.getHeight() / hh) {
w1 = (int) ww;
h1 = (int) (bitmap.getHeight() * (ww / bitmap.getWidth()));
} else {
//高度縮放到1024,寬度等比縮放
h1 = (int) hh;
w1 = (int) (bitmap.getWidth() * (hh / bitmap.getHeight()));
}
//開始精確縮放
result = zoomImg(bitmap, w1, h1);
//釋放無用的bitmap
if (bitmap != null && !bitmap.isRecycled()) {
bitmap.recycle();
bitmap = null;
}
}
//圖片添加水印(原本是想壓縮後再加上水印防止水印模糊,但是添加水印後圖片就變大了,所以就放在質量壓縮之前)
if (result != null && !result.isRecycled()) {
//爲小圖添加上水印
Resources r = context.getResources();
Bitmap bmp = BitmapFactory.decodeResource(r, R.mipmap.water_pic);
int sw = result.getWidth();
int sh = result.getHeight();
int wmw = bmp.getWidth();
int hmh = bmp.getHeight();
Bitmap newb = null;
if (wmw < sw - 40 && hmh < sh - 40) {
Date date = new Date();
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm");
Paint textPaint = new Paint();
textPaint.setTextSize(20);
textPaint.setColor(Color.argb(255, 241, 54, 52));
textPaint.setAntiAlias(true);
String time = format.format(date);
//測量文本的寬度
float timeWith = textPaint.measureText(time);
newb = Bitmap.createBitmap(sw, sh, Bitmap.Config.ARGB_8888);
Canvas cv = new Canvas(newb);
cv.drawBitmap(result, 0, 0, null);
//右下角添加圖片水印
cv.drawBitmap(bmp, sw - (wmw + 20), sh - (hmh + 20), null);
//右上角添加文字水印
cv.drawText(time, sw - (timeWith + 20), 40, textPaint);
cv.save(Canvas.ALL_SAVE_FLAG);
cv.restore();
// //成功獲取水印圖片後釋放無用bitmap
if (result != null && !result.isRecycled()) {
result.recycle();
result = null;
}
} else {
//圖片過小,不添加水印
newb = result;
}
if (bmp != null && !bmp.isRecycled()) {
bmp.recycle();
bmp = null;
}
//質量壓縮
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int quality = 100;
newb.compress(Bitmap.CompressFormat.JPEG, quality, baos);
//設置大小不超過120k
while (baos.toByteArray().length > 120 * 1024) {
baos.reset();
quality -= 10;
newb.compress(Bitmap.CompressFormat.JPEG, quality, baos);
}
try {
File file = new File(savePath);
if (!file.exists()) {
file.mkdir();
}
//存儲
String sdStatus = Environment.getExternalStorageState();
if (sdStatus.equals(Environment.MEDIA_MOUNTED)) { // 檢測sd是否可用
baos.writeTo(new FileOutputStream(file.getAbsolutePath() + "/" + fileName));
baos.flush();
baos.close();
} else {
Toast.makeText(context, "SD卡不可用", Toast.LENGTH_SHORT).show();
}
if (newb != null && !newb.isRecycled()) {
newb.recycle();
newb = null;
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
這裏給出我的思路圖:
按寬度縮放
按高度縮放
不進行縮放
精確縮放
/**
* 裁剪圖片
*
* @param bm 位圖
* @param newWidth 新圖寬度
* @param newHeight 新圖高度
* @return
*/
public static Bitmap zoomImg(Bitmap bm, int newWidth, int newHeight) {
// 獲得圖片的寬高
int width = bm.getWidth();
int height = bm.getHeight();
// 計算縮放比例
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
// 取得想要縮放的matrix參數
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
// 得到新的圖片
Bitmap newbm = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, true);
return newbm;
}
代碼寫得比較雜亂,看起來可能比較費勁。希望大家能耐心看完,也希望多多交流,指出問題,共同學習進步。