圖片壓縮到規定大小和規定尺寸之內

上個項目做了一個圖片批量上傳,要求壓縮到規定大小和尺寸,並且加文字跟圖片水印。花了好長時間才完成,在此記錄一下以方便以後使用。

 /**
     * 壓縮圖片,保持圖片寬高在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;
    }

代碼寫得比較雜亂,看起來可能比較費勁。希望大家能耐心看完,也希望多多交流,指出問題,共同學習進步。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章