图片压缩到规定大小和规定尺寸之内

上个项目做了一个图片批量上传,要求压缩到规定大小和尺寸,并且加文字跟图片水印。花了好长时间才完成,在此记录一下以方便以后使用。

 /** * 压缩图片,保持图片宽高在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();
            }
        }
    }

这里给出我的思路图:
按宽度缩放
图片压缩到规定大小和规定尺寸之内_第1张图片

按高度缩放
图片压缩到规定大小和规定尺寸之内_第2张图片

不进行缩放
图片压缩到规定大小和规定尺寸之内_第3张图片

精确缩放

/** * 裁剪图片 * * @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;
    }

代码写得比较杂乱,看起来可能比较费劲。希望大家能耐心看完,也希望多多交流,指出问题,共同学习进步。

你可能感兴趣的:(图片处理)