Android 图片压缩器

发布时间:2017-11-30
技术:Android + Java

概述

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 += "\nCompress 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


本实例支付的费用只是购买源码的费用,如有疑问欢迎在文末留言交流,如需作者在线代码指导、定制等,在作者开启付费服务后,可以点击“购买服务”进行实时联系,请知悉,谢谢
手机上随时阅读、收藏该文章 ?请扫下方二维码