Android-图片压缩

xiaoxiao2021-02-27  404

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 蓝色

默认色彩模式为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; } }
转载请注明原文地址: https://www.6miu.com/read-4155.html

最新回复(0)