上个项目做了一个图片批量上传,要求压缩到规定大小和尺寸,并且加文字跟图片水印。花了好长时间才完成,在此记录一下以方便以后使用。
/** * 压缩图片,保持图片宽高在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;
}
代码写得比较杂乱,看起来可能比较费劲。希望大家能耐心看完,也希望多多交流,指出问题,共同学习进步。