android上传图片压缩图片大小

现在手机拍照都是好几兆,直接把原图上传到服务器,对于用户来说,直接就崩溃了,在有WiFi的情况下还好。但当其他用户查看列表时,看一会估计手机都得欠费了。所以在上传图片的时候,要对图片进行压缩。
注意:这里的压缩是指质量压缩,不是尺寸压缩。

比如当我们拍一张照片,要上传到服务器。我们需要先把这个照片,读到内存中,然后进行压缩,最后把压缩后的文件输出。

关于图片的内存了,怎么加载节省内存了,这里就不说了
推荐读者看看这篇文章:http://www.jcodecraeer.com/plus/view.php?aid=3874

以下代码来自ImageLoader框架,我把它decoder图片的代码抽了出来,稍作了一下修改

使用代码

public class MainActivity extends AppCompatActivity {


    String imagePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + "123.jpg";
    String outPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + "new.jpg";

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

        final ImageDecoder decoder = new ImageDecoder();
        final ImageSize imageSize = new ImageSize(400, 800);
        final File file = new File(imagePath);
        if (file.exists()) {
            new Thread() {
                @Override
                public void run() {
                    super.run();
                    try {
                        Bitmap bitmap = decoder.decode(file, imageSize);
                        ImageUtils.compressBmpToFile(bitmap, new File(outPath));
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }.start();
        }
    }
}

ImageDecoder 类负责把图片decode成目标大小,然后ImageUtils.compressBmpToFile对图片进行压缩,压缩完之后(压缩到100K以内),输出文件

ImageDecoder.java

public class ImageDecoder {

    public Bitmap decode(File file, ImageSize targetSize) throws IOException {
        Bitmap decodedBitmap;
        ImageFileInfo imageInfo;

        InputStream imageStream = getImageStream(file);
        try {
            imageInfo = defineImageSizeAndRotation(imageStream, file);
            imageStream = resetStream(imageStream, file);
            BitmapFactory.Options decodingOptions = prepareDecodingOptions(imageInfo.imageSize, targetSize);
            decodedBitmap = BitmapFactory.decodeStream(imageStream, null, decodingOptions);
        } finally {
            closeSilently(imageStream);
        }

        if (decodedBitmap != null) {
            decodedBitmap = considerExactScaleAndOrientatiton(decodedBitmap, targetSize, imageInfo.exif.rotation,
                    imageInfo.exif.flipHorizontal);
        }
        return decodedBitmap;
    }

    private InputStream getImageStream(File res) throws IOException{
        return new FileInputStream(res);
    }

    /**
     * 定义image的大小和旋转的度
     */
    protected ImageFileInfo defineImageSizeAndRotation(InputStream imageStream, File file)
            throws IOException {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(imageStream, null, options);

        ExifInfo exif;
        if (canDefineExifParams(options.outMimeType)) {
            exif = defineExifOrientation(file);
        } else {
            exif = new ExifInfo();
        }
        return new ImageFileInfo(new ImageSize(options.outWidth, options.outHeight, exif.rotation), exif);
    }

    private boolean canDefineExifParams(String mimeType) {
        return "image/jpeg".equalsIgnoreCase(mimeType);
    }

    protected ExifInfo defineExifOrientation(File imageUri) {
        int rotation = 0;
        boolean flip = false;
        try {
            ExifInterface exif = new ExifInterface(imageUri.getAbsolutePath());
            int exifOrientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
            switch (exifOrientation) {
                case ExifInterface.ORIENTATION_FLIP_HORIZONTAL:
                    flip = true;
                case ExifInterface.ORIENTATION_NORMAL:
                    rotation = 0;
                    break;
                case ExifInterface.ORIENTATION_TRANSVERSE:
                    flip = true;
                case ExifInterface.ORIENTATION_ROTATE_90:
                    rotation = 90;
                    break;
                case ExifInterface.ORIENTATION_FLIP_VERTICAL:
                    flip = true;
                case ExifInterface.ORIENTATION_ROTATE_180:
                    rotation = 180;
                    break;
                case ExifInterface.ORIENTATION_TRANSPOSE:
                    flip = true;
                case ExifInterface.ORIENTATION_ROTATE_270:
                    rotation = 270;
                    break;
            }
        } catch (IOException e) {
            Log.w("decoder", "Can't read EXIF tags from file [%s]" + imageUri.getAbsolutePath());
        }
        return new ExifInfo(rotation, flip);
    }

    /**
     * 如果imageStream支持reset,则返回reset后的imageStream,否则返回 {@link #getImageStream(File)}
     */
    protected InputStream resetStream(InputStream imageStream, File res) throws IOException {
        //http://zhangbo-peipei-163-com.iteye.com/blog/2022460
        if (imageStream.markSupported()) {
            try {
                imageStream.reset();
                return imageStream;
            } catch (IOException ignored) {
            }
        }
        closeSilently(imageStream);
        return getImageStream(res);
    }

    /**
     * 返回计算好 simple size 的Option
     */
    protected BitmapFactory.Options prepareDecodingOptions(ImageSize imageSize, ImageSize targetSize) {
        int scale = ImageUtils.computeImageSampleSize(imageSize, targetSize);
        BitmapFactory.Options decodingOptions = new BitmapFactory.Options();
        decodingOptions.inSampleSize = scale;
        return decodingOptions;
    }

    protected Bitmap considerExactScaleAndOrientatiton(Bitmap subsampledBitmap, ImageSize targetSize,
                                                       int rotation, boolean flipHorizontal) {
        Matrix m = new Matrix();
        // 缩小到精确的大小,如果需要
        ImageSize srcSize = new ImageSize(subsampledBitmap.getWidth(), subsampledBitmap.getHeight(), rotation);
        float scale = ImageUtils.computeImageScale(srcSize, targetSize, false);
        if (Float.compare(scale, 1f) != 0) {
            m.setScale(scale, scale);
        }
        // 翻转 bitmap 如果需要
        if (flipHorizontal) {
            m.postScale(-1, 1);

        }
        // 选择 bitmap 如果需要
        if (rotation != 0) {
            m.postRotate(rotation);
        }

        Bitmap finalBitmap = Bitmap.createBitmap(subsampledBitmap, 0, 0, subsampledBitmap.getWidth(), subsampledBitmap
                .getHeight(), m, true);
        if (finalBitmap != subsampledBitmap) {
            subsampledBitmap.recycle();
        }
        return finalBitmap;
    }

    protected static class ExifInfo {

        public final int rotation;
        public final boolean flipHorizontal;

        protected ExifInfo() {
            this.rotation = 0;
            this.flipHorizontal = false;
        }

        protected ExifInfo(int rotation, boolean flipHorizontal) {
            this.rotation = rotation;
            this.flipHorizontal = flipHorizontal;
        }
    }

    protected static class ImageFileInfo {

        public final ImageSize imageSize;
        public final ExifInfo exif;

        protected ImageFileInfo(ImageSize imageSize, ExifInfo exif) {
            this.imageSize = imageSize;
            this.exif = exif;
        }
    }

    public static void closeSilently(Closeable closeable) {
        if (closeable != null) {
            try {
                closeable.close();
            } catch (Exception ignored) {
            }
        }
    }

}

ImageUtils .java

public class ImageUtils {
    private static final int DEFAULT_MAX_BITMAP_DIMENSION = 2048;

    private static ImageSize maxBitmapSize;

    static {
        int[] maxTextureSize = new int[1];
        GLES10.glGetIntegerv(GL10.GL_MAX_TEXTURE_SIZE, maxTextureSize, 0);
        int maxBitmapDimension = Math.max(maxTextureSize[0], DEFAULT_MAX_BITMAP_DIMENSION);
        maxBitmapSize = new ImageSize(maxBitmapDimension, maxBitmapDimension);
    }

    private ImageUtils() {
    }

    public static int computeImageSampleSize(ImageSize srcSize, ImageSize targetSize){
        final int srcWidth = srcSize.getWidth();
        final int srcHeight = srcSize.getHeight();
        final int targetWidth = targetSize.getWidth();
        final int targetHeight = targetSize.getHeight();

        int scale = 1;
        scale = Math.min(srcWidth / targetWidth, srcHeight / targetHeight); // min
        if (scale < 1) {
            scale = 1;
        }
        scale = considerMaxTextureSize(srcWidth, srcHeight, scale, false);

        return scale;
    }

    /**
     * 如果宽度和高度/scale大于max texture size则继续缩小
     * @return sample size
     */
    private static int considerMaxTextureSize(int srcWidth, int srcHeight, int scale, boolean powerOf2) {
        final int maxWidth = maxBitmapSize.getWidth();
        final int maxHeight = maxBitmapSize.getHeight();
        while ((srcWidth / scale) > maxWidth || (srcHeight / scale) > maxHeight) {
            if (powerOf2) {
                scale *= 2;
            } else {
                scale++;
            }
        }
        return scale;
    }

    public static float computeImageScale(ImageSize srcSize, ImageSize targetSize,
                                          boolean stretch) {
        final int srcWidth = srcSize.getWidth();
        final int srcHeight = srcSize.getHeight();
        final int targetWidth = targetSize.getWidth();
        final int targetHeight = targetSize.getHeight();

        final float widthScale = (float) srcWidth / targetWidth;
        final float heightScale = (float) srcHeight / targetHeight;

        final int destWidth;
        final int destHeight;
        if (widthScale < heightScale) {
            destWidth = targetWidth;
            destHeight = (int) (srcHeight / widthScale);
        } else {
            destWidth = (int) (srcWidth / heightScale);
            destHeight = targetHeight;
        }

        float scale = 1;
        if ((!stretch && destWidth < srcWidth && destHeight < srcHeight) || (stretch && destWidth != srcWidth && destHeight != srcHeight)) {
            scale = (float) destWidth / srcWidth;
        }

        return scale;
    }

    public static void compressBmpToFile(Bitmap bmp, File file) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        int options = 80;
        bmp.compress(Bitmap.CompressFormat.JPEG, options, baos);
        while (baos.toByteArray().length / 1024 > 100) {
            options -= 10;
            if (options > 0) {
                baos.reset();
                bmp.compress(Bitmap.CompressFormat.JPEG, options, baos);
            } else {
                break;
            }
        }
        try {
            FileOutputStream fos = new FileOutputStream(file);
            byte[] bytes = baos.toByteArray();
            fos.write(bytes);
            fos.flush();
            fos.close();
            Log.i("tag", "file.length" + file.length());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

ImageSize.java

public class ImageSize {
    private final int width;
    private final int height;

    public ImageSize(int width, int height) {
        this.width = width;
        this.height = height;
    }
    public ImageSize(int width, int height, int rotation) {
        if (rotation % 180 == 0) {
            this.width = width;
            this.height = height;
        } else {
            this.width = height;
            this.height = width;
        }
    }

    public int getWidth() {
        return width;
    }

    public int getHeight() {
        return height;
    }
}

github地址
https://github.com/wu-liao-de-ren-sheng/ImageCompress

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值