public Bitmap compressAndGenImage(Bitmap image, String outPath, int maxSize)
throws IOException {
Bitmap bitmap;
ByteArrayOutputStream os = new ByteArrayOutputStream();
// scale
int options = 100;
// Store the bitmap into output stream(no compress)
image.compress(Bitmap.CompressFormat.JPEG, options, os);
// Compress by loop
while (os.toByteArray().length / 1024 > maxSize) {
// Clean up os
os.reset();
// 每次质量下降10
options -= 10;
image.compress(Bitmap.CompressFormat.JPEG, options, os);
}
ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
bitmap = BitmapFactory.decodeStream(is);
// Generate compressed image file
FileOutputStream fos = new FileOutputStream(outPath);
fos.write(os.toByteArray());
fos.flush();
fos.close();
is.close();
return bitmap;
}
这种方式压缩得图片,可以减少文件的存储体积,有利于文件上传。
失真
首先因为没有改变Bitmap的像素值,所以文件转换成的Bitmap图片压缩后和压缩前生成的Bitmap一样大,这时候在使用的时候就要注意了,一张3000K的图片很可能生成的Bitmap多达10M,使用的时候考虑内存溢出问题。
按照官方的解释:图片重新构造, 但是有可能图像的位深(即色深)和每个像素的透明度会变化,JPEG onlysupports opaque(不透明), 也就是说以jpeg格式压缩后, 原来图片中透明的元素将消失.所以这种格式很可能造成失真。
一般用来生成缩略图,不会失真
public Bitmap ratio(Bitmap image, float pixelW, float pixelH) {
ByteArrayOutputStream os = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG, 100, os);
if (os.toByteArray().length / 1024 > 1024) {// 判断如果图片大于1M,进行压缩避免在生成图片(BitmapFactory.decodeStream)时溢出
os.reset();// 重置baos即清空baos
image.compress(Bitmap.CompressFormat.JPEG, 50, os);// 这里压缩50%,把压缩后的数据存放到baos中
}
ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
BitmapFactory.Options newOpts = new BitmapFactory.Options();
// 开始读入图片,此时把options.inJustDecodeBounds 设回true了
newOpts.inJustDecodeBounds = true;
newOpts.inPreferredConfig = Config.RGB_565;
Bitmap bitmap = BitmapFactory.decodeStream(is, null, newOpts);
newOpts.inJustDecodeBounds = false;
int w = newOpts.outWidth;
int h = newOpts.outHeight;
float hh = pixelH;
float ww = pixelW;
// 缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可
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了
is = new ByteArrayInputStream(os.toByteArray());
bitmap = BitmapFactory.decodeStream(is, null, newOpts);
return bitmap;
}
/** * 设置水印图片到中间 */
public static Bitmap createWaterMaskCenter(Bitmap src, Bitmap watermark) {
return createWaterMaskBitmap(src, watermark,
(src.getWidth() - watermark.getWidth()) / 2,
(src.getHeight() - watermark.getHeight()) / 2);
}
public static Bitmap drawTextToLeftTop(Context context, Bitmap bitmap,
String text) {
return drawTextToLeftTop(context, bitmap, text, 16, Color.RED, 4, 4);
}
/** * 给图片添加文字到左上角 */
public static Bitmap drawTextToLeftTop(Context context, Bitmap bitmap,
String text, int size, int color, int paddingLeft, int paddingTop) {
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(color);
paint.setTextSize(dp2px(context, size));
Rect bounds = new Rect();
paint.getTextBounds(text, 0, text.length(), bounds);
return drawTextToBitmap(context, bitmap, text, paint, bounds,
dp2px(context, paddingLeft), dp2px(context, paddingTop)
+ bounds.height());
}
/** * 绘制文字到右下角 */
public static Bitmap drawTextToRightBottom(Context context, Bitmap bitmap,
String text, int size, int color, int paddingRight,
int paddingBottom) {
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(color);
paint.setTextSize(dp2px(context, size));
Rect bounds = new Rect();
paint.getTextBounds(text, 0, text.length(), bounds);
return drawTextToBitmap(
context,
bitmap,
text,
paint,
bounds,
bitmap.getWidth() - bounds.width()
- dp2px(context, paddingRight), bitmap.getHeight()
- dp2px(context, paddingBottom));
}