Android图片压缩的代码实现

来源:互联网 发布:神机妙算软件打不开 编辑:程序博客网 时间:2024/05/29 03:39

参考文章:http://www.codeceo.com/article/android-image-compression.html

在App开发过程中,免不了要上传图片到Server端。考虑到大图片带来的请求时长及传输失败风险,通常情况下都会对图片进行压缩处理后再上传。目前常用的两种压缩方式是:

1.通过降低图片质量;

2.通过减小图片分辨率;

详见开篇提到的参考文章。

这里再补充一下实现过程中的注意事项:

1.图片质量Quality不能无限制过低;需要根据压缩后图片的展示区域作调整。在200x200的展示区域下,图片质量不宜低于40;

2.有些图片的Exif信息里图片原始的方向是有转向的,比如具体展示时需要根据exif里的方向信息转向90度或者180度再显示。这些信息在图片压缩时可能会被压缩掉;从而导致这些图片展示时方向不对。

下面给出的代码实现综合考虑了上述因素后,实现原理如下:

1.根据图片的最大限制值来判断是否是需要压缩;

2.压缩前,先读取图片的exif信息;如果需要转向,则先对图片进行转向处理;

3.对纠正了转向之后的图片先进行图片分辨率的压缩,再进行图片质量的压缩;

下面是具体实现:

其中方法:

ArrayList<String> compress(Context context, ArrayList<String> srcPicList)
是入口方法。

package com.wuba.job.parttime.utils;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Matrix;import android.media.ExifInterface;import android.net.Uri;import android.os.SystemClock;import android.text.TextUtils;import com.wuba.commons.AppCommonInfo;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.util.ArrayList;/** * Created by changwenna on 2016/11/25. */public class PtBitmapUtils {    private final static String PT_CACHE_TEMP_PIC_PATH = AppCommonInfo.sDatadir + File.separator + "ptjob" + File.separator + "temp" + File.separator;    private static int UPLOAD_MAX_FILE_SIZE = 512000;// 500K    private static int UPLOAD_QUALITY_LOW = 40;    public static ArrayList<String> compress(Context context, ArrayList<String> srcPicList) {        ArrayList<String> destPicList = new ArrayList<>();        File file;        for (int i = 0; i < srcPicList.size(); i++) {            String sourceUrl = srcPicList.get(i);            if (TextUtils.isEmpty(sourceUrl) || sourceUrl.startsWith("http")) {                continue;            }            file = new File(sourceUrl);            if (file.exists() && file.length() > UPLOAD_MAX_FILE_SIZE) {                //超过限制,需要压缩                String procedUrl = procPicFile(context, file.getAbsolutePath());                if (TextUtils.isEmpty(procedUrl)) {                    //压缩失败,则返回原图                    destPicList.add(sourceUrl);                }                File procedFile = new File(procedUrl);                if (procedFile.exists()) {                    destPicList.add(procedFile.getAbsolutePath());                }            } else{                destPicList.add(sourceUrl);            }        }        return destPicList;    }    /**     * 是否需要调整图片方向     *     * @param filePath     * @return     */    public static boolean needRotate(String filePath) {        try {            ExifInterface exif = new ExifInterface(filePath);            int orientation = exif.getAttributeInt(                    ExifInterface.TAG_ORIENTATION,                    ExifInterface.ORIENTATION_UNDEFINED);            switch (orientation) {                case ExifInterface.ORIENTATION_ROTATE_90:                    return true;                case ExifInterface.ORIENTATION_ROTATE_270:                    return true;                case ExifInterface.ORIENTATION_ROTATE_180:                    return true;            }            return false;        } catch (IOException e) {            e.printStackTrace();            return false;        }    }    public static void rotatedBitmap(Context context, String filePath, String dstFilePath) throws IOException {        File file = new File(dstFilePath);        if (file.getParentFile() != null && !file.getParentFile().exists()) {            file.getParentFile().mkdirs();        }        ExifInterface exif = new ExifInterface(filePath);        int orientation = exif.getAttributeInt(                ExifInterface.TAG_ORIENTATION,                ExifInterface.ORIENTATION_UNDEFINED);        Matrix matrix = null;        switch (orientation) {            case ExifInterface.ORIENTATION_ROTATE_90:                matrix = new Matrix();                matrix.postRotate(90);                break;            case ExifInterface.ORIENTATION_ROTATE_270:                matrix = new Matrix();                matrix.postRotate(270);                break;            case ExifInterface.ORIENTATION_ROTATE_180:                matrix = new Matrix();                matrix.postRotate(180);                break;        }        Bitmap bmp = getSmallBitmap(context,                Uri.fromFile(new File(filePath)));        if (matrix != null) {            Bitmap bmp2 = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(),                    bmp.getHeight(), matrix, true);            bmp.recycle();            FileOutputStream fos = new FileOutputStream(dstFilePath);            bmp2.compress(Bitmap.CompressFormat.JPEG, 100, fos);            fos.close();            bmp2.recycle();        } else {            FileOutputStream fos = new FileOutputStream(dstFilePath);            FileInputStream fis = new FileInputStream(filePath);            byte[] buffer = new byte[1024];            int len = 0;            while ((len = fis.read(buffer)) != -1) {                fos.write(buffer, 0, len);            }            fos.close();            fis.close();        }    }    /**     * 通过压缩图片质量来压缩图片     * 常用于图片上传     *     * @param image     * @param dstFilePath     */    public static void compressImageByQuality(Bitmap image, String dstFilePath) {        if (image == null) {            return;        }        if (TextUtils.isEmpty(dstFilePath)) {            return;        }        File sourecFile = new File(dstFilePath);        if (!sourecFile.exists()) {            return;        }        int quality = 100;        ByteArrayOutputStream baos = new ByteArrayOutputStream();        image.compress(Bitmap.CompressFormat.JPEG, quality, baos);        while (baos.toByteArray().length / 1024 > UPLOAD_MAX_FILE_SIZE) {            baos.reset();            try {                image.compress(Bitmap.CompressFormat.JPEG, quality, baos);            } catch (Exception e) {                e.printStackTrace();                break;            }            if (quality <= UPLOAD_QUALITY_LOW) {                break;            }            quality -= 10;        }        image.recycle();        ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());        Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);        FileOutputStream fos;        try {            fos = new FileOutputStream(dstFilePath);            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);            try {                fos.close();            } catch (IOException e) {                e.printStackTrace();            }        } catch (Exception e) {            e.printStackTrace();        }        bitmap.recycle();    }    /**     * 默认先进行像素压缩,如果还达高于大小的限制,再进行图片质量的压缩     *     * @param srcPath     * @param dstFilePath     */    public static void compressImage(String srcPath, String dstFilePath) {        if (TextUtils.isEmpty(srcPath) || TextUtils.isEmpty(dstFilePath)) {            return;        }        File sourecFile = new File(srcPath);        if (!sourecFile.exists()) {            return;        }        if (sourecFile.length() / 1024 <= UPLOAD_MAX_FILE_SIZE) {            //原始文件不需要压缩            return;        }        BitmapFactory.Options newOpts = new BitmapFactory.Options();        newOpts.inJustDecodeBounds = true;        BitmapFactory.decodeFile(srcPath, newOpts);        int w = newOpts.outWidth;        int h = newOpts.outHeight;        //现在主流手机比较多是800*480分辨率,所以目标高和宽我们设置为:        float hh = 800f;        float ww = 480f;        //缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可        int be = 1; //be=1表示不缩放        if (w > h && w > ww) {            //如果宽度大的话根据宽度固定大小缩放            be = (int) (newOpts.outWidth / ww);        } else if (w < h && h > hh) {            //如果高度高的话根据宽度固定大小缩放            be = (int) (newOpts.outHeight / hh);        }        if (be <= 0) {            be = 1;        }        newOpts.inSampleSize = be;        newOpts.inJustDecodeBounds = false;        Bitmap bitmap = BitmapFactory.decodeFile(srcPath, newOpts);        FileOutputStream fos;        try {            fos = new FileOutputStream(dstFilePath);            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);            try {                fos.close();            } catch (IOException e) {                e.printStackTrace();            }        } catch (Exception e) {            e.printStackTrace();        }        File dstFile = new File(dstFilePath);        if (!dstFile.exists()) {            return;        }        if (dstFile.length() <= UPLOAD_MAX_FILE_SIZE) {            return;        }        compressImageByQuality(bitmap, dstFilePath);    }    public static Bitmap getSmallBitmap(Context context, Uri uri) {        return getBitmap(context, uri, -1, 128 * 128);    }    public static Bitmap getBitmap(Context context, Uri uri, int maxWidth,                                   int maxHeight) {        try {            final BitmapFactory.Options options = new BitmapFactory.Options();            options.inJustDecodeBounds = true;            InputStream is = context.getContentResolver().openInputStream(uri);            BitmapFactory.decodeStream(is, null, options);            is.close();            // Calculate inSampleSize            options.inSampleSize = calculateInSampleSize(options, maxWidth, maxHeight);            // Decode bitmap with inSampleSize set            options.inJustDecodeBounds = false;            is = context.getContentResolver().openInputStream(uri);            Bitmap bmp = BitmapFactory.decodeStream(is, null, options);            is.close();            return bmp;        } catch (Exception e) {            e.printStackTrace();            return null;        }    }    public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {        int initialSize = computeInitialSampleSize(options, reqWidth, reqHeight);        int roundedSize;        if (initialSize <= 8) {            roundedSize = 1;            while (roundedSize < initialSize) {                roundedSize <<= 1;            }        } else {            roundedSize = (initialSize + 7) / 2;        }        return roundedSize;    }    private static int computeInitialSampleSize(BitmapFactory.Options options, int minSideLength, int maxNumOfPixels) {        double w = options.outWidth;        double h = options.outHeight;        int lowerBound = (maxNumOfPixels == -1) ? 1 :                (int) Math.ceil(Math.sqrt(w * h / maxNumOfPixels));        int upperBound = (minSideLength == -1) ? 128 :                (int) Math.min(Math.floor(w / minSideLength),                        Math.floor(h / minSideLength));        if (upperBound < lowerBound) {            return lowerBound;        }        if ((maxNumOfPixels == -1) &&                (minSideLength == -1)) {            return 1;        } else if (minSideLength == -1) {            return lowerBound;        } else {            return upperBound;        }    }    /**     * @param context     * @param mySourecUrl     * @return     */    public static String procPicFile(Context context, String mySourecUrl) {        String procedUrl = null;        if (TextUtils.isEmpty(mySourecUrl)) {            return procedUrl;        }        File sourecFile = new File(mySourecUrl);        if (!sourecFile.exists()) {            return procedUrl;        }        if (sourecFile.length() / 1024 <= UPLOAD_MAX_FILE_SIZE) {            return mySourecUrl;        }        // 压缩前准备:调整图片方向,以免压缩后丢掉了exif信息导致图片显示方向异常        if (needRotate(mySourecUrl)) {            String urlRotated = PT_CACHE_TEMP_PIC_PATH + "tmp_rotate" + SystemClock.currentThreadTimeMillis() + ".jpg";            File rotatedFile = new File(urlRotated);            if (rotatedFile.exists()) {                rotatedFile.delete();                try {                    rotatedFile.createNewFile();                } catch (IOException e) {                    e.printStackTrace();                }            }            try {                rotatedBitmap(context, mySourecUrl, urlRotated);                procedUrl = urlRotated;            } catch (Exception e) {                e.printStackTrace();                procedUrl = mySourecUrl;            }        } else {            procedUrl = mySourecUrl;        }        String urlCompressed = PT_CACHE_TEMP_PIC_PATH + "tmp_compress" + SystemClock.currentThreadTimeMillis() + ".jpg";        File compressFile = new File(urlCompressed);        if (compressFile.exists()) {            compressFile.delete();        }        //开始压缩图片文件        compressImage(procedUrl, urlCompressed);        File compressedFile = new File(urlCompressed);        if (compressedFile.exists()) {            procedUrl = urlCompressed;        } else {            procedUrl = null;        }        return procedUrl;    }}

0 0
原创粉丝点击