終極圖片壓縮

圖片優(yōu)化壓縮方式大概可以分為以下幾類(lèi):更換圖片格式,質(zhì)量壓縮,采樣率壓縮,縮放壓縮,調(diào)用jpeg壓縮等

1、設(shè)置圖片格式

Android目前常用的圖片格式有png,jpeg和webp,
png:無(wú)損壓縮圖片格式,支持Alpha通道,Android切圖素材多采用此格式
jpeg:有損壓縮圖片格式,不支持背景透明,適用于照片等色彩豐富的大圖壓縮,不適合logo
webp:是一種同時(shí)提供了有損壓縮和無(wú)損壓縮的圖片格式,派生自視頻編碼格式VP8,從谷歌官網(wǎng)來(lái)看,無(wú)損webp平均比png小26%,有損的webp平均比jpeg小25%~34%,無(wú)損webp支持Alpha通道,有損webp在一定的條件下同樣支持,有損webp在A(yíng)ndroid4.0(API 14)之后支持,無(wú)損和透明在A(yíng)ndroid4.3(API18)之后支持
采用webp能夠在保持圖片清晰度的情況下,可以有效減小圖片所占有的磁盤(pán)空間大小

2、質(zhì)量壓縮

質(zhì)量壓縮并不會(huì)改變圖片在內(nèi)存中的大小,僅僅會(huì)減小圖片所占用的磁盤(pán)空間的大小,因?yàn)橘|(zhì)量壓縮不會(huì)改變圖片的分辨率,而圖片在內(nèi)存中的大小是根據(jù)widthheight一個(gè)像素的所占用的字節(jié)數(shù)計(jì)算的,寬高沒(méi)變,在內(nèi)存中占用的大小自然不會(huì)變,質(zhì)量壓縮的原理是通過(guò)改變圖片的位深和透明度來(lái)減小圖片占用的磁盤(pán)空間大小,所以不適合作為縮略圖,可以用于想保持圖片質(zhì)量的同時(shí)減小圖片所占用的磁盤(pán)空間大小。另外,由于png是無(wú)損壓縮,所以設(shè)置quality無(wú)效,以下是實(shí)現(xiàn)方式:

/**
 * 質(zhì)量壓縮 bitmap.compress
 *
 * @param format  圖片格式 jpeg,png,webp
 * @param quality 圖片的質(zhì)量,0-100,數(shù)值越小質(zhì)量越差
 */
public static void compress(Bitmap.CompressFormat format, int quality) {
    File sdFile = Environment.getExternalStorageDirectory();
    File originFile = new File(sdFile, "originImg.jpg");
    Bitmap originBitmap = BitmapFactory.decodeFile(originFile.getAbsolutePath());
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    originBitmap.compress(format, quality, bos);
    try {
        FileOutputStream fos = new FileOutputStream(new File(sdFile, "resultImg.jpg"));
        fos.write(bos.toByteArray());
        fos.flush();
        fos.close();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

3、采樣率壓縮

采樣率壓縮是通過(guò)設(shè)置BitmapFactory.Options.inSampleSize,來(lái)減小圖片的分辨率,進(jìn)而減小圖片所占用的磁盤(pán)空間和內(nèi)存大小。
設(shè)置的inSampleSize會(huì)導(dǎo)致壓縮的圖片的寬高都為1/inSampleSize,整體大小變?yōu)樵紙D片的inSampleSize平方分之一,當(dāng)然,這些有些注意點(diǎn):
1、inSampleSize小于等于1會(huì)按照1處理
2、inSampleSize只能設(shè)置為2的平方,不是2的平方則最終會(huì)減小到最近的2的平方數(shù),如設(shè)置7會(huì)按4進(jìn)行壓縮,設(shè)置15會(huì)按8進(jìn)行壓縮。
具體的代碼實(shí)現(xiàn)方式如下:

/**
 * 
 * @param inSampleSize  可以根據(jù)需求計(jì)算出合理的inSampleSize
 */
public static void compress(int inSampleSize) {
    File sdFile = Environment.getExternalStorageDirectory();
    File originFile = new File(sdFile, "originImg.jpg");
    BitmapFactory.Options options = new BitmapFactory.Options();
    //設(shè)置此參數(shù)是僅僅讀取圖片的寬高到options中,不會(huì)將整張圖片讀到內(nèi)存中,防止oom
    options.inJustDecodeBounds = true;
    Bitmap emptyBitmap = BitmapFactory.decodeFile(originFile.getAbsolutePath(), options);
 
    options.inJustDecodeBounds = false;
    options.inSampleSize = inSampleSize;
    Bitmap resultBitmap = BitmapFactory.decodeFile(originFile.getAbsolutePath(), options);
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    resultBitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);
    try {
        FileOutputStream fos = new FileOutputStream(new File(sdFile, "resultImg.jpg"));
        fos.write(bos.toByteArray());
        fos.flush();
        fos.close();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

4.框架實(shí)現(xiàn)的效果:

4.1 設(shè)置壓縮配置參數(shù)

  compressConfig = CompressConfig.builder()
                .setUnCompressMinPixel(1000) // 最小像素不壓縮,默認(rèn)值:1000
                .setUnCompressNormalPixel(2000) // 標(biāo)準(zhǔn)像素不壓縮,默認(rèn)值:2000
                .setMaxPixel(1000) // 長(zhǎng)或?qū)挷怀^(guò)的最大像素 (單位px),默認(rèn)值:1200
                .setMaxSize(100 * 1024) // 壓縮到的最大大小 (單位B),默認(rèn)值:200 * 1024 = 200KB
                .enablePixelCompress(true) // 是否啟用像素壓縮,默認(rèn)值:true
                .enableQualityCompress(true) // 是否啟用質(zhì)量壓縮,默認(rèn)值:true
                .enableReserveRaw(true) // 是否保留源文件,默認(rèn)值:true
                .setCacheDir("") // 壓縮后緩存圖片路徑,默認(rèn)值:Constants.COMPRESS_CACHE
                .setShowCompressDialog(true) // 是否顯示壓縮進(jìn)度條,默認(rèn)值:false
                .create();

4.2 多圖壓縮

 private void compressMore() {
        // 測(cè)試多張圖片同時(shí)壓縮
        ArrayList<Photo> photos = new ArrayList<>();
        photos.add(new Photo("/storage/emulated/0/DCIM/Camera/IMG_20171108_151541.jpg"));
        photos.add(new Photo("/storage/emulated/0/DCIM/Camera/IMG_20171011_095724.jpg"));
        photos.add(new Photo("/storage/emulated/0/DCIM/Camera/IMG_20171011_092207.jpg"));
        photos.add(new Photo("/storage/emulated/0/DCIM/Camera/IMG_20170608_113509.jpg"));
        photos.add(new Photo("/storage/emulated/0/tencent/MicroMsg/WeiXin/mmexport1535449679877.jpg"));
        photos.add(new Photo("/storage/emulated/0/autoLite/cameraImg/1535016551150.jpg"));
        photos.add(new Photo("/storage/emulated/0/Download/微信圖片_20171205095927.jpg"));
        photos.add(new Photo("/storage/emulated/0/Pictures/camera_20181115_111332.jpg"));
        photos.add(new Photo("/storage/emulated/0/Pictures/camera_20180706_173207.jpg"));
        compress(photos);
    }
  // 開(kāi)始?jí)嚎s
    private void compress(ArrayList<Photo> photos) {
        if (compressConfig.isShowCompressDialog()) {
            Log.e("netease >>> ", "開(kāi)啟了加載框");
            dialog = CommonUtils.showProgressDialog(this, "壓縮中……");
        }
        CompressImageManager.build(this, compressConfig, photos, this).compress();
    }

4.3 壓縮完回調(diào)

 @Override
    public void onCompressSuccess(ArrayList<Photo> arrayList) {
        Log.e("netease >>> ", "壓縮成功");
        if (dialog != null && !isFinishing()) {
            dialog.dismiss();
        }
    }

    @Override
    public void onCompressFailed(ArrayList<Photo> arrayList, String error) {
        Log.e("netease >>> ", error);
        if (dialog != null && !isFinishing()) {
            dialog.dismiss();
        }
    }

代碼解析:

通過(guò)建造者配置壓縮參數(shù):


import java.io.Serializable;

/**
 * 壓縮配置類(lèi)
 */
public class CompressConfig implements Serializable {

    /**
     * 最小像素不壓縮
     */
    private int unCompressMinPixel = 1000;
    /**
     * 標(biāo)準(zhǔn)像素不壓縮
     */
    private int unCompressNormalPixel = 2000;
    /**
     * 長(zhǎng)或?qū)挷怀^(guò)的最大像素,單位px
     */
    private int maxPixel = 1200;
    /**
     * 壓縮到的最大大小,單位B
     */
    private int maxSize = 200 * 1024;
    /**
     * 是否啟用像素壓縮
     */
    private boolean enablePixelCompress = true;
    /**
     * 是否啟用質(zhì)量壓縮
     */
    private boolean enableQualityCompress = true;
    /**
     * 是否保留源文件
     */
    private boolean enableReserveRaw = true;
    /**
     * 壓縮后緩存圖片目錄,非文件路徑
     */
    private String cacheDir;
    /**
     * 是否顯示壓縮進(jìn)度條
     */
    private boolean showCompressDialog;

    public static CompressConfig getDefaultConfig() {
        return new CompressConfig();
    }

    private CompressConfig() {
    }

    public int getUnCompressMinPixel() {
        return unCompressMinPixel;
    }

    private void setUnCompressMinPixel(int unCompressMinPixel) {
        this.unCompressMinPixel = unCompressMinPixel;
    }

    public int getUnCompressNormalPixel() {
        return unCompressNormalPixel;
    }

    private void setUnCompressNormalPixel(int unCompressNormalPixel) {
        this.unCompressNormalPixel = unCompressNormalPixel;
    }

    public int getMaxPixel() {
        return maxPixel;
    }

    private void setMaxPixel(int maxPixel) {
        this.maxPixel = maxPixel;
    }

    public int getMaxSize() {
        return maxSize;
    }

    private void setMaxSize(int maxSize) {
        this.maxSize = maxSize;
    }

    public boolean isEnablePixelCompress() {
        return enablePixelCompress;
    }

    private void setEnablePixelCompress(boolean enablePixelCompress) {
        this.enablePixelCompress = enablePixelCompress;
    }

    public boolean isEnableQualityCompress() {
        return enableQualityCompress;
    }

    private void setEnableQualityCompress(boolean enableQualityCompress) {
        this.enableQualityCompress = enableQualityCompress;
    }

    public boolean isEnableReserveRaw() {
        return enableReserveRaw;
    }

    private void setEnableReserveRaw(boolean enableReserveRaw) {
        this.enableReserveRaw = enableReserveRaw;
    }

    public String getCacheDir() {
        return cacheDir;
    }

    public void setCacheDir(String cacheDir) {
        this.cacheDir = cacheDir;
    }

    public boolean isShowCompressDialog() {
        return showCompressDialog;
    }

    private void setShowCompressDialog(boolean showCompressDialog) {
        this.showCompressDialog = showCompressDialog;
    }

    public static Builder builder() {
        return new Builder();
    }

    public static class Builder {

        private CompressConfig config;

        private Builder() {
            config = new CompressConfig();
        }

        public Builder setUnCompressMinPixel(int unCompressMinPixel) {
            config.setUnCompressMinPixel(unCompressMinPixel);
            return this;
        }

        public Builder setUnCompressNormalPixel(int unCompressNormalPixel) {
            config.setUnCompressNormalPixel(unCompressNormalPixel);
            return this;
        }

        public Builder setMaxSize(int maxSize) {
            config.setMaxSize(maxSize);
            return this;
        }

        public Builder setMaxPixel(int maxPixel) {
            config.setMaxPixel(maxPixel);
            return this;
        }

        public Builder enablePixelCompress(boolean enablePixelCompress) {
            config.setEnablePixelCompress(enablePixelCompress);
            return this;
        }

        public Builder enableQualityCompress(boolean enableQualityCompress) {
            config.setEnableQualityCompress(enableQualityCompress);
            return this;
        }

        public Builder enableReserveRaw(boolean enableReserveRaw) {
            config.setEnableReserveRaw(enableReserveRaw);
            return this;
        }

        public Builder setCacheDir(String cacheDir) {
            config.setCacheDir(cacheDir);
            return this;
        }

        public Builder setShowCompressDialog(boolean showCompressDialog) {
            config.setShowCompressDialog(showCompressDialog);
            return this;
        }

        public CompressConfig create() {
            return config;
        }
    }
}


壓縮封裝整合:對(duì)壓縮的集合進(jìn)行遞歸壓縮,壓縮完回調(diào)



import android.content.Context;
import android.text.TextUtils;

import com.netease.image.library.bean.Photo;
import com.netease.image.library.config.CompressConfig;
import com.netease.image.library.core.CompressImageUtil;
import com.netease.image.library.listener.CompressImage;
import com.netease.image.library.listener.CompressResultListener;

import java.io.File;
import java.util.ArrayList;

/**
 * 框架:思路、起稿。千萬(wàn)不要過(guò)度封裝
 * 壓縮圖片管理類(lèi)
 * 1、單例?
 * 2、能否重復(fù)壓縮?
 */
public class CompressImageManager implements CompressImage {

    private CompressImageUtil compressImageUtil; // 壓縮工具類(lèi)
    private ArrayList<Photo> images; // 要壓縮的圖片集合
    private CompressImage.CompressListener listener; // 壓縮監(jiān)聽(tīng),告知MainActivity
    private CompressConfig config; // 壓縮配置

    /**
     * 私有實(shí)現(xiàn)
     *
     * @param context 上下文
     * @param config 配置
     * @param images 圖片集合
     * @param listener 監(jiān)聽(tīng)
     * @return
     */
    private CompressImageManager(Context context, CompressConfig config,
                                ArrayList<Photo> images, CompressListener listener) {
        compressImageUtil = new CompressImageUtil(context, config);
        this.config = config;
        this.images = images;
        this.listener = listener;
    }

    /**
     * 靜態(tài)方法,new實(shí)現(xiàn)
     *
     * @param context 上下文
     * @param config 配置
     * @param images 圖片集合
     * @param listener 監(jiān)聽(tīng)
     * @return
     */
    public static CompressImage build(Context context, CompressConfig config,
                                      ArrayList<Photo> images, CompressImage.CompressListener listener) {
        return new CompressImageManager(context, config, images, listener);
    }

    @Override
    public void compress() {
        if (images == null || images.isEmpty()) {
            listener.onCompressFailed(images, "集合為空");
            return;
        }

        for (Photo image : images) {
            if (image == null) {
                listener.onCompressFailed(images, "某圖片為空");
                return;
            }
        }

        // 開(kāi)始遞歸壓縮,從第一張開(kāi)始
        compress(images.get(0));
    }

    // 從第一張開(kāi)始,index = 0
    private void compress(Photo image) {
        // 路徑為空
        if (TextUtils.isEmpty(image.getOriginalPath())) {
            // 繼續(xù)
            continueCompress(image, false);
            return;
        }

        // 文件不存在
        File file = new File(image.getOriginalPath());
        if (!file.exists() || !file.isFile()) {
            continueCompress(image, false);
            return;
        }

        // < 200KB
        if (file.length() < config.getMaxSize()) {
            continueCompress(image, true);
            return;
        }

        // 單張壓縮
        compressImageUtil.compress(image.getOriginalPath(), new CompressResultListener() {
            @Override
            public void onCompressSuccess(String imgPath) {
                image.setCompressPath(imgPath);
                continueCompress(image, true);
            }

            @Override
            public void onCompressFailed(String imgPath, String error) {
                continueCompress(image, false, error);
            }
        });
    }

    private void continueCompress(Photo image, boolean bool, String... error) {
        image.setCompressed(bool);
        // 當(dāng)前圖片的索引
        int index = images.indexOf(image);
        if (index == images.size() - 1) { // 最后一張
            handlerCallback(error);
        } else {
            compress(images.get(index + 1));
        }
    }

    private void handlerCallback(String... error) {
        if (error.length > 0) {
            listener.onCompressFailed(images, error[0]);
            return;
        }

        for (Photo image : images) {
            // 如果存在沒(méi)有壓縮的圖片,或者壓縮失敗的
            if (!image.isCompressed()) {
                listener.onCompressFailed(images, image.getOriginalPath() + "壓縮失敗");
                return;
            }
        }

        listener.onCompressSuccess(images);
    }
}

根據(jù)傳人圖片路徑,以及壓縮方式進(jìn)行對(duì)應(yīng)壓縮回調(diào):



import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.text.TextUtils;
import android.util.Log;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;

import com.netease.image.library.config.CompressConfig;
import com.netease.image.library.listener.CompressResultListener;
import com.netease.image.library.utils.Constants;

/**
 * 壓縮照片
 */
public class CompressImageUtil {

    private CompressConfig config;
    private Context context;
    private Handler mhHandler = new Handler();

    public CompressImageUtil(Context context, CompressConfig config) {
        this.context = context;
        this.config = config == null ? CompressConfig.getDefaultConfig() : config;
    }

    public void compress(String imgPath, CompressResultListener listener) {
        if (config.isEnablePixelCompress()) {
            try {
                compressImageByPixel(imgPath, listener);
            } catch (FileNotFoundException e) {
                listener.onCompressFailed(imgPath, String.format("圖片壓縮失敗,%s", e.toString()));
                e.printStackTrace();
            }
        } else {
            compressImageByQuality(BitmapFactory.decodeFile(imgPath), imgPath, listener);
        }
    }

    /**
     * 多線(xiàn)程壓縮圖片的質(zhì)量
     */
    private void compressImageByQuality(final Bitmap bitmap, final String imgPath, final CompressResultListener listener) {
        if (bitmap == null) {
            sendMsg(false, imgPath, "像素壓縮失敗,bitmap為空", listener);
            return;
        }
        //開(kāi)啟多線(xiàn)程進(jìn)行壓縮處理
        new Thread(() -> {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            int options = 100;
            bitmap.compress(Bitmap.CompressFormat.JPEG, options, baos); // 質(zhì)量壓縮方法,把壓縮后的數(shù)據(jù)存放到baos中 (100表示不壓縮,0表示壓縮到最小)
            while (baos.toByteArray().length > config.getMaxSize()) { // 循環(huán)判斷如果壓縮后圖片是否大于指定大小,大于繼續(xù)壓縮
                baos.reset(); // 重置baos即讓下一次的寫(xiě)入覆蓋之前的內(nèi)容
                options -= 5; // 圖片質(zhì)量每次減少5
                if (options <= 5) options = 5; // 如果圖片質(zhì)量小于5,為保證壓縮后的圖片質(zhì)量,圖片最底壓縮質(zhì)量為5
                bitmap.compress(Bitmap.CompressFormat.JPEG, options, baos); // 將壓縮后的圖片保存到baos中
                if (options == 5) break; // 如果圖片的質(zhì)量已降到最低則,不再進(jìn)行壓縮
            }
            try {
                File thumbnailFile = getThumbnailFile(new File(imgPath));
                FileOutputStream fos = new FileOutputStream(thumbnailFile);//將壓縮后的圖片保存的本地上指定路徑中
                fos.write(baos.toByteArray());
                fos.flush();
                fos.close();
                baos.flush();
                baos.close();
                bitmap.recycle();
                sendMsg(true, thumbnailFile.getPath(), null, listener);

            } catch (Exception e) {
                sendMsg(false, imgPath, "質(zhì)量壓縮失敗", listener);
                e.printStackTrace();
            }
        }).start();
    }

    /**
     * 按比例縮小圖片的像素以達(dá)到壓縮的目的
     */
    private void compressImageByPixel(String imgPath, CompressResultListener listener) throws FileNotFoundException {
        if (imgPath == null) {
            sendMsg(false, null, "要壓縮的文件不存在", listener);
            return;
        }
        BitmapFactory.Options newOpts = new BitmapFactory.Options();
        newOpts.inJustDecodeBounds = true; // 只讀邊,不讀內(nèi)容
        BitmapFactory.decodeFile(imgPath, newOpts);
        newOpts.inJustDecodeBounds = false;
        int width = newOpts.outWidth;
        int height = newOpts.outHeight;
        float maxSize = config.getMaxPixel();
        int be = 1;
        if (width >= height && width > maxSize) { // 縮放比,用高或者寬其中較大的一個(gè)數(shù)據(jù)進(jìn)行計(jì)算
            be = (int) (newOpts.outWidth / maxSize);
            be++;
        } else if (width < height && height > maxSize) {
            be = (int) (newOpts.outHeight / maxSize);
            be++;
        }
        if (width <= config.getUnCompressNormalPixel() || height <= config.getUnCompressNormalPixel()) {
            be = 2;
            if (width <= config.getUnCompressMinPixel() || height <= config.getUnCompressMinPixel()) be = 1;
        }
        newOpts.inSampleSize = be; // 設(shè)置采樣率
        newOpts.inPreferredConfig = Config.ARGB_8888; // 該模式是默認(rèn)的,可不設(shè)
        newOpts.inPurgeable = true; // 同時(shí)設(shè)置才會(huì)有效
        newOpts.inInputShareable = true; // 當(dāng)系統(tǒng)內(nèi)存不夠時(shí)候圖片自動(dòng)被回收
        Bitmap bitmap = BitmapFactory.decodeFile(imgPath, newOpts);
        if (config.isEnableQualityCompress()) {
            compressImageByQuality(bitmap, imgPath, listener); // 壓縮好比例大小后再進(jìn)行質(zhì)量壓縮
        } else {
            File thumbnailFile = getThumbnailFile(new File(imgPath));
            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, new FileOutputStream(thumbnailFile));

            listener.onCompressSuccess(thumbnailFile.getPath());
        }
    }

    private File getThumbnailFile(File file) {
        if (file == null || !file.exists()) return file;
        return getPhotoCacheDir(file);
    }

    private File getPhotoCacheDir(File file) {
        if (TextUtils.isEmpty(config.getCacheDir())) config.setCacheDir(Constants.COMPRESS_CACHE);
        File mCacheDir = new File(Constants.BASE_CACHE_PATH
                + context.getPackageName() + "/cache", config.getCacheDir());
        Log.e("netease >>> ", mCacheDir.getAbsolutePath());
        if (!mCacheDir.mkdirs() && (!mCacheDir.exists() || !mCacheDir.isDirectory())) {
            return file;
        } else {
            return new File(mCacheDir, "compress_" + file.getName());
        }
    }

    /**
     * 發(fā)送壓縮結(jié)果的消息
     *
     * @param isSuccess 壓縮是否成功
     */
    private void sendMsg(final boolean isSuccess, final String imagePath, final String message, final CompressResultListener listener) {
        mhHandler.post(() -> {
            if (isSuccess) {
                listener.onCompressSuccess(imagePath);
            } else {
                listener.onCompressFailed(imagePath, message);
            }
        });
    }

}

最終調(diào)用方式:


import android.Manifest;
import android.app.ProgressDialog;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;

import com.netease.image.compress.utils.UriParseUtils;
import com.netease.image.library.CompressImageManager;

import java.io.File;
import java.util.ArrayList;

import com.netease.image.library.bean.Photo;
import com.netease.image.library.config.CompressConfig;
import com.netease.image.library.listener.CompressImage;
import com.netease.image.library.utils.CachePathUtils;
import com.netease.image.library.utils.CommonUtils;
import com.netease.image.library.utils.Constants;

public class MainActivity extends AppCompatActivity implements CompressImage.CompressListener {

    private CompressConfig compressConfig; // 壓縮配置
    private ProgressDialog dialog; // 壓縮加載框
    private String cameraCachePath; // 拍照源文件路徑

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

        compressConfig = CompressConfig.builder()
                .setUnCompressMinPixel(1000) // 最小像素不壓縮,默認(rèn)值:1000
                .setUnCompressNormalPixel(2000) // 標(biāo)準(zhǔn)像素不壓縮,默認(rèn)值:2000
                .setMaxPixel(1000) // 長(zhǎng)或?qū)挷怀^(guò)的最大像素 (單位px),默認(rèn)值:1200
                .setMaxSize(100 * 1024) // 壓縮到的最大大小 (單位B),默認(rèn)值:200 * 1024 = 200KB
                .enablePixelCompress(true) // 是否啟用像素壓縮,默認(rèn)值:true
                .enableQualityCompress(true) // 是否啟用質(zhì)量壓縮,默認(rèn)值:true
                .enableReserveRaw(true) // 是否保留源文件,默認(rèn)值:true
                .setCacheDir("") // 壓縮后緩存圖片路徑,默認(rèn)值:Constants.COMPRESS_CACHE
                .setShowCompressDialog(true) // 是否顯示壓縮進(jìn)度條,默認(rèn)值:false
                .create();
        compressMore();
    }

    private void compressMore() {
        // 測(cè)試多張圖片同時(shí)壓縮
        ArrayList<Photo> photos = new ArrayList<>();
        photos.add(new Photo("/storage/emulated/0/DCIM/Camera/IMG_20171108_151541.jpg"));
        photos.add(new Photo("/storage/emulated/0/DCIM/Camera/IMG_20171011_095724.jpg"));
        photos.add(new Photo("/storage/emulated/0/DCIM/Camera/IMG_20171011_092207.jpg"));
        photos.add(new Photo("/storage/emulated/0/DCIM/Camera/IMG_20170608_113509.jpg"));
        photos.add(new Photo("/storage/emulated/0/tencent/MicroMsg/WeiXin/mmexport1535449679877.jpg"));
        photos.add(new Photo("/storage/emulated/0/autoLite/cameraImg/1535016551150.jpg"));
        photos.add(new Photo("/storage/emulated/0/Download/微信圖片_20171205095927.jpg"));
        photos.add(new Photo("/storage/emulated/0/Pictures/camera_20181115_111332.jpg"));
        photos.add(new Photo("/storage/emulated/0/Pictures/camera_20180706_173207.jpg"));
        compress(photos);
    }

    // 點(diǎn)擊拍照
    public void camera(View view) {
        // FileProvider
        Uri outputUri;
        File file = CachePathUtils.getCameraCacheFile();
        ;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            outputUri = UriParseUtils.getCameraOutPutUri(this, file);
        } else {
            outputUri = Uri.fromFile(file);
        }
        cameraCachePath = file.getAbsolutePath();
        // 啟動(dòng)拍照
        CommonUtils.hasCamera(this, CommonUtils.getCameraIntent(outputUri), Constants.CAMERA_CODE);
    }

    // 點(diǎn)擊相冊(cè)
    public void album(View view) {
        CommonUtils.openAlbum(this, Constants.ALBUM_CODE);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        // 拍照返回
        if (requestCode == Constants.CAMERA_CODE && resultCode == RESULT_OK) {
            // 壓縮(集合?單張)
            preCompress(cameraCachePath);
        }

        // 相冊(cè)返回
        if (requestCode == Constants.ALBUM_CODE && resultCode == RESULT_OK) {
            if (data != null) {
                Uri uri = data.getData();
                String path = UriParseUtils.getPath(this, uri);
                // 壓縮(集合?單張)
                preCompress(path);
            }
        }
    }

    // 準(zhǔn)備壓縮,封裝圖片集合
    private void preCompress(String photoPath) {
        ArrayList<Photo> photos = new ArrayList<>();
        photos.add(new Photo(photoPath));
        if (!photos.isEmpty()) compress(photos);
    }

    // 開(kāi)始?jí)嚎s
    private void compress(ArrayList<Photo> photos) {
        if (compressConfig.isShowCompressDialog()) {
            Log.e("netease >>> ", "開(kāi)啟了加載框");
            dialog = CommonUtils.showProgressDialog(this, "壓縮中……");
        }
        CompressImageManager.build(this, compressConfig, photos, this).compress();
    }

    @Override
    public void onCompressSuccess(ArrayList<Photo> arrayList) {
        Log.e("netease >>> ", "壓縮成功");
        if (dialog != null && !isFinishing()) {
            dialog.dismiss();
        }
    }

    @Override
    public void onCompressFailed(ArrayList<Photo> arrayList, String error) {
        Log.e("netease >>> ", error);
        if (dialog != null && !isFinishing()) {
            dialog.dismiss();
        }
    }

    private void initPermission() {
        // 運(yùn)行時(shí)權(quán)限申請(qǐng)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            String[] perms = {Manifest.permission.CAMERA,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE};
            if (checkSelfPermission(perms[0]) == PackageManager.PERMISSION_DENIED ||
                    checkSelfPermission(perms[1]) == PackageManager.PERMISSION_DENIED) {
                requestPermissions(perms, 200);
            }
        }
    }


}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 參考PNG、EPS、bmp、jpg等幾種圖片格式有什么區(qū)別GIF/PNG/JPG和WEBP/base64/apng...
    合肥黑閱讀 13,097評(píng)論 0 15
  • 為何要壓縮 1、體積的原因如果你的圖片是要準(zhǔn)備上傳的,那動(dòng)輒幾M的大小肯定不行的,況且圖片分辨率大于設(shè)備分辨率的話(huà)...
    mahongyin閱讀 932評(píng)論 0 1
  • 摘要:對(duì)android 上圖片壓縮,其實(shí)總結(jié)起來(lái)基本可以分為兩類(lèi)壓縮:尺寸壓縮和質(zhì)量壓縮, 尺寸壓縮其實(shí)也可以理解...
    男爵是只貓丶閱讀 8,987評(píng)論 2 14
  • 盡量減少PNG圖片的大小是Android里面很重要的一條規(guī)范。相比起JPEG,PNG能夠提供更加清晰無(wú)損的圖片,但...
    Viking_Den閱讀 535評(píng)論 0 0
  • 上周五跟同學(xué)一起回家,路上我們聊了很多問(wèn)題。其中,她有句問(wèn)倒了我,“萬(wàn)一你的文章投稿被別人公眾號(hào)發(fā)表使用了,但沒(méi)有...
    那么蕭閱讀 242評(píng)論 0 1

友情鏈接更多精彩內(nèi)容