圖片壓縮Luban

內容:對圖片進行壓縮,可指定忽略壓縮圖片大小和壓縮後圖片保存位置。在此對多圖、圖組進行二次封裝,使用更方便

Luban原理:使用了Bitmap基礎的壓縮策略,可見:Bitmap圖片壓縮、圖片副本及特效處理、畫板功能(保存相冊刷新)、刮刮獎

Luban關鍵代碼:計算壓縮比例、設置旋轉

源碼:

File compress() throws IOException {
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inSampleSize = computeSize();

    Bitmap tagBitmap = BitmapFactory.decodeFile(srcImg, options);
    ByteArrayOutputStream stream = new ByteArrayOutputStream();

    tagBitmap = rotatingImage(tagBitmap);
    tagBitmap.compress(Bitmap.CompressFormat.JPEG, 60, stream);
    tagBitmap.recycle();

    FileOutputStream fos = new FileOutputStream(tagImg);
    fos.write(stream.toByteArray());
    fos.flush();
    fos.close();
    stream.close();

    return tagImg;
  }
private int computeSize() {
    srcWidth = srcWidth % 2 == 1 ? srcWidth + 1 : srcWidth;
    srcHeight = srcHeight % 2 == 1 ? srcHeight + 1 : srcHeight;

    int longSide = Math.max(srcWidth, srcHeight);
    int shortSide = Math.min(srcWidth, srcHeight);

    float scale = ((float) shortSide / longSide);
    if (scale <= 1 && scale > 0.5625) {
      if (longSide < 1664) {
        return 1;
      } else if (longSide >= 1664 && longSide < 4990) {
        return 2;
      } else if (longSide > 4990 && longSide < 10240) {
        return 4;
      } else {
        return longSide / 1280 == 0 ? 1 : longSide / 1280;
      }
    } else if (scale <= 0.5625 && scale > 0.5) {
      return longSide / 1280 == 0 ? 1 : longSide / 1280;
    } else {
      return (int) Math.ceil(longSide / (1280.0 / scale));
    }
  }
private Bitmap rotatingImage(Bitmap bitmap) {
    if (srcExif == null) return bitmap;

    Matrix matrix = new Matrix();
    int angle = 0;
    int orientation = srcExif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
    switch (orientation) {
      case ExifInterface.ORIENTATION_ROTATE_90:
        angle = 90;
        break;
      case ExifInterface.ORIENTATION_ROTATE_180:
        angle = 180;
        break;
      case ExifInterface.ORIENTATION_ROTATE_270:
        angle = 270;
        break;
    }

    matrix.postRotate(angle);

    return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
  }

Luban壓縮後的效果

好了不廢話,直接上如何使用

步驟如下:

1、引入Luban三方庫。GitHub:https://github.com/Curzibn/Luban

    implementation 'top.zibin:Luban:1.1.8'

2、主代碼進行二次封裝(未生成工具類,可自行提取,只展示思想)

public class MainActivity extends AppCompatActivity {

    private static final int COMPRESS_START = 100;
    private static final int COMPRESS_SUCCESS = 101;
    private static final int COMPRESS_FAIL = 102;

    public static final String SD_PATH = Environment.getExternalStorageDirectory().getPath() + File.separator;
    private String path1 = SD_PATH + "test1.jpg";
    private String path2 = SD_PATH + "test2.jpg";
    private String path3 = SD_PATH + "test3.jpg";
    private String path4 = SD_PATH + "test4.jpg";
    private String path5 = SD_PATH + "test5.jpg";
    private List<List<String>> pathList = new ArrayList<>();
    private String cachePath = SD_PATH + "Test";

    private int compressChildIndex = 0;     //子類壓縮指引
    private int childTotal = 0;     //子類壓縮總數
    private int compressFatherIndex = 0;        //父類壓縮指引

    private Handler mHandler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case COMPRESS_START:
                    compressChildIndex = 0;
                    childTotal = pathList.get(compressFatherIndex).size();
                    doCompress(pathList.get(compressFatherIndex));
                    break;
                case COMPRESS_SUCCESS:
                    LogUtil("壓縮完畢");
                    break;
                case COMPRESS_FAIL:
                    LogUtil((String) msg.obj);
                    break;
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initData();
        findViewById(R.id.btn_compress).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new PermissionUtil(MainActivity.this, new PermissionUtil.PermissionCheckListener() {
                    @Override
                    public void ok() {
                        compressConfig();
                    }

                    @Override
                    public void notOk() {
                        Toast.makeText(MainActivity.this, "need permission", Toast.LENGTH_SHORT).show();
                    }
                }, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}).check();
            }
        });
    }

    private void initData() {
        List<String> paths1 = new ArrayList<>();
        List<String> paths2 = new ArrayList<>();
        paths1.add(path1);
        paths1.add(path2);
        paths1.add(path3);
        paths2.add(path4);
        paths2.add(path5);
        pathList.add(paths1);
        pathList.add(paths2);
    }

    private void compressConfig() {
        compressFatherIndex = 0;

        File cacheFile = new File(cachePath);
        if (!cacheFile.exists())
            cacheFile.mkdirs();

        mHandler.sendEmptyMessage(COMPRESS_START);
    }

    private void doCompress(List<String> paths) {
        Luban.with(this)
                .load(paths)
                .ignoreBy(100)
                .setTargetDir(cachePath)
                .setCompressListener(new OnCompressListener() {
                    @Override
                    public void onStart() {
                    }

                    @Override
                    public void onSuccess(File file) {
                        compressChildIndex++;       //移動到子類下一張,壓縮完成則+1
                        LogUtil(file.getAbsolutePath() + "=====childTotal:" + childTotal + "=====compressChildIndex:" + compressChildIndex);
                        //判斷上一組是否壓縮完畢
                        if (compressChildIndex >= childTotal) {
                            compressFatherIndex++;      //移動到父類下一組
                            LogUtil("pathList.size:" + pathList.size() + "=====compressFatherIndex:" + compressFatherIndex);
                            //判斷是否所有組壓縮完畢
                            if (compressFatherIndex >= pathList.size()) {
                                mHandler.sendEmptyMessage(COMPRESS_SUCCESS);
                            } else {
                                mHandler.sendEmptyMessage(COMPRESS_START);
                            }
                        }
                    }

                    @Override
                    public void onError(Throwable e) {
                        Message msg = new Message();
                        msg.obj = e.toString();
                        msg.what = COMPRESS_FAIL;
                        mHandler.sendMessage(msg);
                    }
                }).launch();
    }

    private void LogUtil(String str) {
        Log.e("Luban", str);
    }
}

Log打印如下:

com.leixiansheng.lubantest E/Luban: /storage/emulated/0/Test/1567416655160624.jpeg=====childTotal:3=====compressChildIndex:1
com.leixiansheng.lubantest E/Luban: /storage/emulated/0/Test/1567416656157573.jpeg=====childTotal:3=====compressChildIndex:2
com.leixiansheng.lubantest E/Luban: /storage/emulated/0/Test/1567416656813325.jpeg=====childTotal:3=====compressChildIndex:3
com.leixiansheng.lubantest E/Luban: pathList.size:2=====compressFatherIndex:1
com.leixiansheng.lubantest E/Luban: /storage/emulated/0/Test/1567416657053777.jpeg=====childTotal:2=====compressChildIndex:1
com.leixiansheng.lubantest E/Luban: /storage/emulated/0/Test/1567416657730368.jpeg=====childTotal:2=====compressChildIndex:2
com.leixiansheng.lubantest E/Luban: pathList.size:2=====compressFatherIndex:2
com.leixiansheng.lubantest E/Luban: 壓縮完畢

記得配置權限!

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