图片压缩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: 压缩完毕

记得配置权限!

猜你喜欢

转载自blog.csdn.net/Mr_Leixiansheng/article/details/100331564