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

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

阿里云代金券1000元免费领取地址:https://promotion.aliyun.com/ntms/yunparter/invite.html?userCode=2a7uv47d
新老阿里云账户均可领取!可用于购买阿里云服务器ECS、云数据库RDS、虚拟主机、安骑士、DDoS高防IP等100多云计算产品。 代金券自领取之日起,有效期是30天,请及时使用,过30天后还可以重新领取。

/**

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

这里给出我的思路图:
按宽度缩放
按宽度缩放
20170104111336706

按高度缩放
这里写图片描述
20170104111633904

不进行缩放
这里写图片描述
20170104111811359

精确缩放

/**

 * 裁剪图片
 *
 * @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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值