• Android 图片压缩器


    概述

    Android 图片压缩器:一款高效的图片压缩器库,支持批量压缩,异步压缩、多线程多任务压缩,压缩比设置等特性。

    详细

    一、android图片压缩器特点

    1.压缩比可以选择控制。

    2.高效率的多线程压缩

    3.支持批量压缩

    二、实现过程

    2.1 压缩任务线程类

    该类是用于实现多线程压缩任务,利用CountDownLatch 计数计数实现多线程任务等待机制,核心代码如下:

    /**
     * Created by caizhiming on 2016/6/2.
     * 图片压缩任务线程
     */
    public class CompressTask extends Thread{
        CountDownLatch mLatch;
        Boolean mRet;
        String mInFilePath;
        String mOutFilePath;
        boolean mIsNeedCompress;
        public CompressTask(CountDownLatch latch,Boolean ret,String inFilePath,String outFilePath,boolean isNeedCompress){
            mLatch = latch;
            mRet = ret;
            mInFilePath = inFilePath;
            mOutFilePath = outFilePath;
            mIsNeedCompress = isNeedCompress;
        }
        @Override
        public void run() {
            if(mIsNeedCompress) {
                mRet = NativeBitmapUtil.syncCompressBitmap(mInFilePath,mOutFilePath);
                mLatch.countDown();
            }else{
                mRet = true;
                mLatch.countDown();
            }
        }
    }

    2.2 图片图像工具类

    该工具类主要对Bitmap图像处理做了一些封装,比如Bitmap旋转,获取旋转角度等,核心代码如下:

    /**
     * 获取旋转后的图片
     * @param path
     * @return
     */
    public static Bitmap getRotateBitmapByPath(String path) {
        return rotateBitmapByDegree(BitmapFactory.decodeFile(path), getBitmapDegree(path));
    }
    /**
     * 获取旋转后的图片
     * @param path
     * @return
     */
    public static Bitmap getRotateBitmapByPath(String path,final int maxSize) {
        BitmapFactory.Options  options= new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(path, options);
        options.inSampleSize = BitmapUtils.calculateInSampleSize(options,maxSize,maxSize);
        options.inJustDecodeBounds = false;
        return rotateBitmapByDegree(BitmapFactory.decodeFile(path,options), getBitmapDegree(path));
    }
    /**
     * 将图片按照某个角度进行旋转
     *
     * @param bm
     *            需要旋转的图片
     * @param degree
     *            旋转角度
     * @return 旋转后的图片
     */
    public static Bitmap rotateBitmapByDegree(Bitmap bm, int degree) {
        Bitmap returnBm = null;
    
        // 根据旋转角度,生成旋转矩阵
        Matrix matrix = new Matrix();
        matrix.postRotate(degree);
        try {
            if (bm != null) {
                // 将原始图片按照旋转矩阵进行旋转,并得到新的图片
                returnBm = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true);
            }
        } catch (OutOfMemoryError e) {
        }
        if (returnBm == null) {
            returnBm = bm;
        }
        if (bm != returnBm) {
            bm.recycle();
        }
        return returnBm;
    }
    /**
     * 读取图片的旋转的角度
     *
     * @param path
     *            图片绝对路径
     * @return 图片的旋转角度
     */
    public static int getBitmapDegree(String path) {
        int degree = 0;
        try {
            // 从指定路径下读取图片,并获取其EXIF信息
            ExifInterface exifInterface = new ExifInterface(path);
            // 获取图片的旋转信息
            int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION,
                    ExifInterface.ORIENTATION_NORMAL);
            switch (orientation) {
                case ExifInterface.ORIENTATION_ROTATE_90:
                    degree = 90;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_180:
                    degree = 180;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_270:
                    degree = 270;
                    break;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return degree;
    }

    2.3 压缩器类的实现

    该功能类只要实现多线程文件压缩功能,支持异步压缩单张图片和多张图片等特性。

    2.3.1首先定义图片压缩状态监听接口,如下:

    /**
     * 图片压缩监听器
     */
    public interface ImageCompressListener {
        void onSuccess(List<String> outFilePathList);
    
        void onFailure(String message);
    }

    2.3.2 其次提供是否压缩判断方案:

    public static long MAX_FILE_SIZE = 1024 * 1024;
    /**
     * 是否压缩图片:大于 1280*1280的 图片 需要压缩 或者 大小大于1M
     * @param inFilePath
     * @return isNeedCompress
     */
    public static boolean isNeedCompress(String inFilePath){
        boolean ret = true;
        File file = new File(inFilePath);
        if(file != null && file.exists()){
            BitmapFactory.Options  options= new BitmapFactory.Options();
            options.inJustDecodeBounds = true;
            BitmapFactory.decodeFile(inFilePath,options);
            if(options.outWidth <= BitmapUtil.MAX_SIZE
                    && options.outHeight <= BitmapUtil.MAX_SIZE){
                ret = false;
            }
            if(file.length() > MAX_FILE_SIZE){
                ret = true;
            }
        }
        return ret;
    }

    2.3.3 最后实现异步压缩功能,核心代码如下:

    /**
     * 异步压缩多张图片
     * @param inFilePathList:需要压缩的图片的路径列表
     * @param outList:压缩后输出的新图片的路径列表
     * @param listener:压缩监听器
     */
    public static void compress(final List<String> inFilePathList, final List<String> outList
            , final ImageCompressListener listener) {
        final List<String> outFilePathList = (outList == null) ? createOutFilePathList(inFilePathList) : outList;
        new AsyncTask<Void, Void, Boolean>() {
            @Override
            protected Boolean doInBackground(Void... params) {
                boolean isSuccess = true;
                CountDownLatch singal = new CountDownLatch(inFilePathList.size());
                List<Boolean> retList = new ArrayList<>();
                for (int i = 0; i < inFilePathList.size(); i++) {
                    retList.add(i, Boolean.TRUE);
                    boolean isNeedCompress = isNeedCompress(inFilePathList.get(i));
                    if(!isNeedCompress){
                        outFilePathList.set(i,inFilePathList.get(i));
                    }
                    CompressTask compressTask = new CompressTask(singal, retList.get(i)
                            , inFilePathList.get(i), outFilePathList.get(i),isNeedCompress);
                    compressTask.start();
                }
                try {
                    singal.await();
                    for (Boolean ret : retList) {
                        if(!ret) isSuccess = false;
                    }
    
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    isSuccess = false;
                }finally {
                    if(!isSuccess) {
                        String failErrorMsg = "";
                        for(int i =0;i < retList.size();i++){
                            if(!retList.get(i)){
                                failErrorMsg += "
    Compress error: "+inFilePathList.get(i);
                            }
                        }
                    }
                    return isSuccess;
                }
            }
    
            @Override
            protected void onPostExecute(Boolean result) {
                super.onPostExecute(result);
                if(listener != null){
                    if(result) {
                        listener.onSuccess(outFilePathList);
                        for(String path :outFilePathList){
                            Log.v("czm","outFilePath="+path);
                        }
                    }else{
                        listener.onFailure("图片压缩失败!!");
                    }
                }
            }
        }.execute();
    }

    三、使用方法

    3.1 使用该压缩器很简单,直接一个方法搞定:

        List<String> srcFilePathList = new ArrayList<>();
        List<String> outputFilePathList = new ArrayList<>();
        //默认压缩方法
        XCImageCompressor.compress(srcFilePathList, new XCImageCompressor.ImageCompressListener() {
            @Override
            public void onSuccess(List<String> outFilePathList) {
    
            }
    
            @Override
            public void onFailure(String message) {
    
            }
        });
        
        //支持压缩后的输出目录的压缩方法
        XCImageCompressor.compress(srcFilePathList, outputFilePathList,new XCImageCompressor.ImageCompressListener() {
            @Override
            public void onSuccess(List<String> outFilePathList) {
    
            }
    
            @Override
            public void onFailure(String message) {
    
            }
        });

    四、源码目录截图

    111.png

    注:本文著作权归作者,由demo大师发表,拒绝转载,转载需要作者授权

  • 相关阅读:
    前端总结挺全面的
    cmd与bat脚本的使用
    Spring控制反转(IoC)的理解
    C# 中迭代器
    URL 分页并排序
    结合Flash上传文件时显示进度条
    C# 语言特性
    where T:new()
    图片缩放特效
    C# 隐藏窗体 ALT+TAb不可见
  • 原文地址:https://www.cnblogs.com/demodashi/p/8491140.html
Copyright © 2020-2023  润新知