Android-图片压缩

1、图片的基本知识

1.文件形式(即以二进制形式存在于硬盘上)
获取大小(Byte):
File.length()
2.流的形式(即以二进制形式存在于内存中)
获取大小(Byte):
new FileInputStream(File).available()
3.Bitmap形式
获取大小(Byte):
Bitmap.getByteCount()

这三种形式的区别: 文件形式和流的形式对图片体积大小并没有影响,也就是说,如果你手机SD卡上的如果是100K,那么通过流的形式读到内存中,也一定是占100K的内存,注意是流的形式,不是Bitmap的形式,当图片以Bitmap的形式存在时,其占用的内存会瞬间变大, 我试过500K文件形式的图片加载到内存,以Bitmap形式存在时,占用内存将近10M,当然这个增大的倍数并不是固定的。

bitmap大小=图片长度(px) x 图片宽度(px) x 单位像素占用的字节数

色彩模式:

单位像素所占字节数就是图片的色彩模式。当一个颜色表现形式越多,那么画面整体的色彩就会更丰富,图片质量就会越高,当然,图片占用的储存空间也越大。
在BitmapFactory.Options.inPreferredConfig这里可以找到,一共有4种, ARGB代表:A 透明度 , R 红色, G 绿色, B 蓝色
Markdown

默认色彩模式为ARGB_8888

质量压缩:

Bitmap.compress(CompressFormat format, int quality, OutputStream stream)

这个方法有三个参数,是布尔类型的返回值

CompressFormat 指定的Bitmap被压缩成的图片格式,只支持JPEG,PNG,WEBP三种。
quality 图片压缩质量的控制,范围为0~100,0表示压缩后体积最小,但是质量也是最差,100表示压缩后体积最大,但是质量也是最好的(个人认为相当于未压缩),有些格式,例如png,它是无损的,所以会忽略这个值。
OutputStream 压缩后的数据会写入这个字节流中。

该方法是压缩图片的质量, 注意它不会减少图片的像素,比方说, 你的图片是300K的, 1280*700像素的, 经过该方法压缩后, File形式的图片是在100以下, 以方便上传服务器, 但是你BitmapFactory.decodeFile到内存中,变成Bitmap时,它的像素仍然是1280*700,
计算图片像素的方法是 bitmap.getWidth()和bitmap.getHeight(),
图片是由像素组成的, 每个像素又包含什么呢? 熟悉PS的人知道, 图片是有色相,明度和饱和度构成的.

二次采样:

该方法就是对Bitmap形式的图片进行压缩, 也就是通过设置采样率, 减少Bitmap的像素, 从而减少了它所占用的内存。

2、压缩图片的目的与方法:

一,避免占用内存过多。二,可能要上传图片,如果图片太大,浪费流量。(有时候需要上传原图除外)

1、避免内存过多的压缩方法:

归根结底,图片是要显示在界面组件上的,所以还是要用到bitmap,从上面可得出Bitmap的在内存中的大小只和图片尺寸和色彩模式有关,那么要想改变Bitmap在内存中的大小,要么改变尺寸,要么改变色彩模式。

2、避免上传浪费流量的压缩方法:

改变图片尺寸(二次采样),改变色彩模式,改变图片质量都行。正常情况下,先改变图片尺寸和色彩模式,再改变图片质量。

3、工具类示例:

package com.example.administrator.downloadimgdemo.compressutils;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;

/**
 * Created by Administrator on 2017/5/4.
 */

public class CompressImageUtil {

    /**
     * 质量压缩方法:限制100kb,不改变分辨率
     *
     * @param image
     * @return
     */
    public static Bitmap compressImage(Bitmap image) {

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        image.compress(Bitmap.CompressFormat.JPEG, 100, baos);

        int options = 100;
        while (baos.toByteArray().length / 1024 > 100) {
            baos.reset();
            options -= 5;
            image.compress(Bitmap.CompressFormat.JPEG, options, baos);
        }

        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
        Bitmap bitmap = BitmapFactory.decodeStream(bais, null, null);

        return bitmap;
    }


    /**
     * 图片按比例大小压缩方法:二次采样压缩
     *
     * @param srcPath (根据路径获取图片并压缩)
     * @return
     */
    public static Bitmap getImage(String srcPath) {

        //1.获取原始图片的长和宽
        //inJustDecodeBounds设置为true,可以不把图片读到内存中,但依然可以计算出图片的大小
        BitmapFactory.Options newOpts = new BitmapFactory.Options();
        newOpts.inJustDecodeBounds = true;
        Bitmap bitmap = BitmapFactory.decodeFile(srcPath, newOpts);
        int height = newOpts.outHeight;
        int width = newOpts.outWidth;

        //2.计算压缩比例
        //inSampleSize为1表示宽度和高度不缩放,为2表示压缩后的宽度与高度为原来的1/2
        int reqHeight = 800;
        int reqWidth = 480;
        int be = 1;//be=1表示不缩放
        if (width/reqWidth > height/reqHeight && width > reqWidth) {//取比率较大者且比率大于1
            be = (int) (width / reqWidth);
        } else if (height/reqHeight > width/reqWidth && height > reqHeight) {
            be = (int) (height / reqHeight);
        }

        newOpts.inSampleSize = be;//设置缩放比例
        // newOpts.inPreferredConfig = Config.RGB_565;//降低图片从ARGB888到RGB565

        //3.缩放并压缩图片
        newOpts.inJustDecodeBounds = false;
        bitmap = BitmapFactory.decodeFile(srcPath, newOpts);

        return bitmap;
    }

    /**
     * 图片按比例大小压缩方法:二次采样
     *
     * @param image (根据Bitmap图片压缩)
     * @return
     */

    public static Bitmap compressScale(Bitmap image) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        image.compress(Bitmap.CompressFormat.JPEG, 100, baos);
        //判断如果图片大于1M,进行压缩避免在生成图片(BitmapFactory.decodeStream)时溢出
        if (baos.toByteArray().length / 1024 > 1024) {
            baos.reset();
            image.compress(Bitmap.CompressFormat.JPEG, 50, baos);
        }
        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());

        //1.获取原始图片的长和宽
        //inJustDecodeBounds设置为true,可以不把图片读到内存中,但依然可以计算出图片的大小
        // 开始读入图片,此时把options.inJustDecodeBounds 设回true了
        BitmapFactory.Options newOpts = new BitmapFactory.Options();
        newOpts.inJustDecodeBounds = true;
        Bitmap bitmap = BitmapFactory.decodeStream(bais, null, newOpts);
        int height = newOpts.outHeight;
        int width = newOpts.outWidth;

        //2.计算压缩比例
        //be为1表示宽度和高度不缩放,为2表示压缩后的宽度与高度为原来的1/2
        int reqHeight = 800;
        int reqWidth = 480;
        int be = 1;//be=1表示不缩放
        if (width/reqWidth > height/reqHeight && width > reqWidth) {//取比率较大者且比率大于1
            be = (int) (width / reqWidth);
        } else if (height/reqHeight > width/reqWidth && height > reqHeight) {
            be = (int) (height / reqHeight);
        }

        newOpts.inSampleSize = be;//设置缩放比例
        // newOpts.inPreferredConfig = Config.RGB_565;//降低图片从ARGB888到RGB565

        //3.缩放并压缩图片
        // 重新读入图片,注意此时已经把options.inJustDecodeBounds 设回false了
        newOpts.inJustDecodeBounds = false;
        bais = new ByteArrayInputStream(baos.toByteArray());
        bitmap = BitmapFactory.decodeStream(bais, null, newOpts);

        return bitmap;
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值