图片压缩_学习笔记

图片压缩_学习笔记

android原生图片压缩方法

    private String beforeCompressPath = Environment.getExternalStorageDirectory().getAbsolutePath()+
            File.separator + "183" + File.separator + "TestCompress" + File.separator +
            "BeforeCompress" + File.separator + "pic.jpg";

    private String afterCompressPath = Environment.getExternalStorageDirectory().getAbsolutePath()+
            File.separator + "183" + File.separator + "TestCompress" + File.separator +
            "AfterCompress" + File.separator + "compressPic.jpg";

    private Bitmap mBitmapOrigin;
    private Bitmap mBitmapAfter;

    private android.widget.ImageView ivprecompress;
    private android.widget.ImageView ivaftcompress;
    private android.widget.Button btncompress;
        /**
         * 将图片压缩到1M,quality图片质量每次减1,压缩一张3.9M的图片用了十几秒。该算法不适合在主线程中使用,试试鲁班的。
         */
        btncompress.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mBitmapOrigin = BitmapFactory.decodeFile(beforeCompressPath);

                try {
                    //内存输出流,与其他流向硬盘写数据不一样,它向内存中写数据,运算速度更快。
                    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                    int quality = 100;
                    while (true) {
                        byteArrayOutputStream.reset();
                        //jpg压缩效果比png好很多
                        mBitmapOrigin.compress(Bitmap.CompressFormat.JPEG, quality, byteArrayOutputStream);
                        int size = byteArrayOutputStream.size();

                        if (size > 1000 * 1024) {
                            quality -= 1;
                        } else {
                            break;
                        }
                        Log.e("quality", "quality == " + quality);
                    }

                    Log.e("quality", "quality == " + quality);
                    FileOutputStream fileOutputStream = new FileOutputStream(afterCompressPath);
                    mBitmapOrigin.compress(Bitmap.CompressFormat.JPEG, quality, fileOutputStream);

                    mBitmapAfter = BitmapFactory.decodeFile(afterCompressPath);

                    //将图片以bitmap的形式显示到imageview中
                    ivprecompress.setImageBitmap(mBitmapOrigin);
                    ivaftcompress.setImageBitmap(mBitmapAfter);

                } catch (Exception e) {
                    e.printStackTrace();
                }

            }
        });
  • 原生核心方法为:Bitmap.compress();
  • 压缩的算法有很多种,这里用到的是将图片压缩到1MB,每次图片的质量会减少1%,知道图片小于1MB
  • 缺点:耗时很长…

Luban图片压缩第三方框架

GitHub

https://github.com/Curzibn/Luban

集成

implementation 'top.zibin:Luban:1.1.3'

基本用法

  • GitHub上说的已经很明白了

    Luban.with(this)
          .load(photos)                                   // 传人要压缩的图片列表
          .ignoreBy(100)                                  // 忽略不压缩图片的大小
          .setTargetDir(getPath())                        // 设置压缩后文件存储位置
          .setCompressListener(new OnCompressListener() { //设置回调
            @Override
            public void onStart() {
              // TODO 压缩开始前调用,可以在方法内启动 loading UI
            }
    
            @Override
            public void onSuccess(File file) {
              // TODO 压缩成功后调用,返回压缩后的图片文件
            }
    
            @Override
            public void onError(Throwable e) {
              // TODO 当压缩过程出现问题时调用
            }
          }).launch();    //启动压缩
  • 压缩单个图片

      private String mBeforeCompressPicPath = Environment.getExternalStorageDirectory().getAbsolutePath() +
              File.separator + "183" + File.separator + "TestCompress" + File.separator +
              "BeforeCompress" + File.separator + "pic2.jpg";
    
      private String mAfterCompressPicPath = Environment.getExternalStorageDirectory().getAbsolutePath() +
              File.separator + "183" + File.separator + "TestCompress" + File.separator +
              "AfterCompress";
    
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.aty_compress_single_picture);
    
          Luban.with(this)
                  .load(mBeforeCompressPicPath)                               // 传人要压缩的图片列表
                  .ignoreBy(100)                                              // 忽略不压缩图片的大小
                  .setTargetDir(mAfterCompressPicPath)                        // 设置压缩后文件存储位置
                  .setCompressListener(new OnCompressListener() { //设置回调
                      @Override
                      public void onStart() {
                          // TODO 压缩开始前调用,可以在方法内启动 loading UI
                          LogUtil.e("开始图片压缩,这里可以启动loading UI");
                      }
    
                      @Override
                      public void onSuccess(File file) {
                          // TODO 压缩成功后调用,返回压缩后的图片文件
                          LogUtil.e("压缩成功,返回压缩后图片文件,文件大小:" + file.length() / 1000 + "KB");
                          file.renameTo(new File(mAfterCompressPicPath, "compressPic2.jpg"));
                      }
    
                      @Override
                      public void onError(Throwable e) {
                          // TODO 当压缩过程出现问题时调用
                          LogUtil.e("压缩出现问题:" + e.getMessage());
                      }
                  }).launch();    //启动压缩
      }

    打印结果:

    04-07 10:43:47.923 7000-7000/com.tupobi.testlubancompresspictuer E/AtyCompressSinglePicture 1.onStart(Line:40):loadingUI040710:43:48.20170007000/com.tupobi.testlubancompresspictuerE/AtyCompressSinglePicture 1. o n S t a r t ( L i n e : 40 ) : 开 始 图 片 压 缩 , 这 里 可 以 启 动 l o a d i n g U I ​ 04 − 07 10 : 43 : 48.201 7000 − 7000 / c o m . t u p o b i . t e s t l u b a n c o m p r e s s p i c t u e r E / A t y C o m p r e s s S i n g l e P i c t u r e 1.onSuccess(Line:46): 压缩成功,返回压缩后图片文件,文件大小:221KB

  • 压缩一组图片

      private int mPictureIndex;
      private List<String> mOriginPictureLists;
      private String mAfterCompressPicPath = Environment.getExternalStorageDirectory().getAbsolutePath() +
              File.separator + "183" + File.separator + "TestCompress" + File.separator +
              "AfterCompressList";
    
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.aty_compress_list_pictures);
    
          mOriginPictureLists = new ArrayList<>();
          String originPic1 = Environment.getExternalStorageDirectory().getAbsolutePath() +
                  File.separator + "183" + File.separator + "TestCompress" + File.separator +
                  "BeforeCompress" + File.separator + "pic.jpg";
    
          String originPic2 = Environment.getExternalStorageDirectory().getAbsolutePath() +
                  File.separator + "183" + File.separator + "TestCompress" + File.separator +
                  "BeforeCompress" + File.separator + "pic2.jpg";
    
    
          mOriginPictureLists.add(originPic1);
          mOriginPictureLists.add(originPic2);
    
          Luban.with(this)
                  .load(mOriginPictureLists)                                   // 传人要压缩的图片列表
                  .ignoreBy(100)                                  // 忽略不压缩图片的大小
                  .setTargetDir(mAfterCompressPicPath)                        // 设置压缩后文件存储位置
                  .setCompressListener(new OnCompressListener() { //设置回调
                      @Override
                      public void onStart() {
                          // TODO 压缩开始前调用,可以在方法内启动 loading UI
                          LogUtil.e("开始压缩,调用loadingUI");
                      }
    
                      @Override
                      public void onSuccess(File file) {
                          // TODO 压缩成功后调用,返回压缩后的图片文件
                          // 可以用图片列表下标来判断是否为最后一张图片,并停止loading UI
                          File newFile = new File(mAfterCompressPicPath, "lzj" + System.currentTimeMillis());
                          file.renameTo(newFile);
                          mPictureIndex++;
                          LogUtil.e("压缩第" + mPictureIndex + "张成功!" + "文件名:" + newFile.getName() + ", 大小" + newFile.length() / 1000 +"KB");
                      }
    
                      @Override
                      public void onError(Throwable e) {
                          // TODO 当压缩过程出现问题时调用
                          LogUtil.e("压缩第" + mPictureIndex + "失败!");
                      }
                  }).launch();    //启动压缩
      }

    打印结果:

    04-07 10:43:54.829 7000-7000/com.tupobi.testlubancompresspictuer E/AtyCompressListPictures$1.onStart(Line:54): 开始压缩,调用loadingUI

    04-07 10:43:55.128 7000-7000/com.tupobi.testlubancompresspictuer E/AtyCompressListPictures$1.onSuccess(Line:63): 压缩第1张成功!文件名:lzj1523069035127, 大小246KB

    04-07 10:43:55.128 7000-7000/com.tupobi.testlubancompresspictuer E/AtyCompressListPictures$1.onStart(Line:54): 开始压缩,调用loadingUI

    04-07 10:43:55.446 7000-7000/com.tupobi.testlubancompresspictuer E/AtyCompressListPictures$1.onSuccess(Line:63): 压缩第2张成功!文件名:lzj1523069035446, 大小221KB

    PS:这里.load(mOriginPictureLists) 传入的是一个图片路径的列表,对于每一张图片的处理都有回调。所以当要批量压缩图片时,可以判断图片列表的下标是否是最后一个了,然后停止loading UI

总结

  • 现在android手机拍一张图片动辄3MB往上走,如果要将图片上传至服务器势必需要压缩。当然上传一张原图一张压缩后的更好,根据需求和资源而定。

  • 采用Luban压缩图片的第三方框架很简洁,默认是异步执行。同步执行可以与RxJava1.x一起使用,不过好像还不支持2.x,使用RxJava最好也尽量避免在主线程调用以免阻塞主线程,下面以rxJava调用为例

    Flowable.just(photos)
      .observeOn(Schedulers.io())
      .map(new Function<List<String>, List<File>>() {
        @Override public List<File> apply(@NonNull List<String> list) throws Exception {
          // 同步方法直接返回压缩后的文件
          return Luban.with(MainActivity.this).load(list).get();
        }
      })
      .observeOn(AndroidSchedulers.mainThread())
      .subscribe();

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值