美文网首页
图片压缩,二次采样

图片压缩,二次采样

作者: lay_wn | 来源:发表于2018-06-22 20:59 被阅读0次

图片压缩就是为了避免我们内存溢出,所有要对一系列进行压缩二次采样等

1.什么是OOM?为什么会引起OOM?

out of Memory(内存溢出)我们都知道Android系统会被每个App分配一个独立的空间,或者说分配一个Dalvik虚拟机(Dalvik是Google公司自己设计用于Android平台的虚拟机。Dalvik虚拟机是Google等厂商合作开发的Android移动设备平台的核心组成部分之一。它可以支持已转换为 .dex(即Dalvik Executable)格式的Java应用程序的运行,.dex格式是专为Dalvik设计的一种压缩格式,适合内存和处理器速度有限的系统。Dalvik经过优化,允许在有限的内存中同时运行多个虚拟机的实例,并且[1]每一个Dalvik应用作为一个独立的Linux 进程执行。独立的进程可以防止在虚拟机崩溃的时候所有程序都被关闭。)这样每个APP都可以独立运行而不相互影响!而Android对于每个 Dalvik虚拟机都会有一个最大内存限制,如果当前占用的内存加上我们申请的内存资源超过了这个限制 ,系统就会抛出OOM错误!另外,这里别和RAM混淆了,即时当前RAM中剩余的内存有1G多,但是OOM还是会发生!别把RAM(物理内存)和OOM扯到一起!另外RAM不足的话,就是杀应用了,而不是仅仅是OOM了! 而这个Dalvik中的最大内存标准,不同的机型是不一样的

这里可以获取系统分给你App多少内存

ActivityManager activityManager = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE); Log.e("HEHE","最大内存:" + activityManager.getMemoryClass());

一、Bitmap:

Bitmap是Android系统中的图像处理的最重要类之一。用它可以获取图像文件信息,进行图像剪切、旋转、缩放等操作,并可以指定格式保存图像文件。

常用方法:

public void recycle()  // 回收位图占用的内存空间,把位图标记为Dead

public final boolean isRecycled()  //判断位图内存是否已释放

public final int getWidth() //获取位图的宽度

public final int getHeight() //获取位图的高度

public final boolean isMutable() //图片是否可修改

public int getScaledWidth(Canvas canvas) //获取指定密度转换后的图像的度

public int getScaledHeight(Canvas canvas) //获取指定密度转换后的图像的度

public boolean compress(CompressFormat format, int quality, OutputStream stream) //按指定的图片格式以及画质,将图片转换为输出流。

format:压缩图像的格式,如Bitmap.CompressFormat.PNG或 ·Bitmap.CompressFormat.JPEG

quality:画质,0-100.0表示最低画质压缩,100以最高画质压缩。对于PNG等无损格式的图片,会忽略此项设置。

stream: OutputStream中写入压缩数据。

return: 是否成功压缩到指定的流。

public static Bitmap createBitmap(Bitmap src)  //以src为原图生成不可变得新图像

public static Bitmap createScaledBitmap(Bitmap src, int dstWidth, int dstHeight, boolean filter) //以src为原图,创建新的图像,指定新图像的高宽以及是否可变。

public static Bitmap createBitmap(int width, int height, Config config) //创建指定格式、大小的位图

public static Bitmap createBitmap(Bitmap source, int x, int y, int width, int height) //以source为原图,创建新的图片,指定起始坐标以及新图像的高宽。

BitmapFactory.Option可设置参数

Option 参数类:

public boolean inJustDecodeBounds //如果设置为true,不获取图片,不分配 内存,但会返回图片的高度宽度信息。

如果将这个值置为true,那么在解码的时候将不会返回bitmap,只会返回这个bitmap 的尺寸。这个属性的目的是,如果你只想知道一个bitmap的尺寸,但又不想将其加载到内存时。这是一个非常有用的属性。

public int inSampleSize //图片缩放的倍数

这个值是一个int,当它小于1的时候,将会被当做1处理,如果大于1,那么就会按照比例(1 / inSampleSize)缩小bitmap的宽和高、降低分辨率,大于1时这个值将会被处置为2的倍数。例如,width=100,height=100,inSampleSize=2,那么就会将bitmap处理为,width=50,height=50,宽高降为1 / 2,像素数降为1 / 4。

public int outWidth //获取图片的宽度值

public int outHeight //获取图片的高度值

表示这个Bitmap的宽和高,一般和inJustDecodeBounds一起使用来获得Bitmap的宽高,但是不加载到内存。

public int inDensity //用于位图的像素压缩比

public int inTargetDensity //用于目标位图的像素压缩比(要生成的位图)

public byte[] inTempStorage  //创建临时文件,将图片存储

public boolean inScaled //设置为true时进行图片压缩,从inDensity到inTargetDensity

public boolean inDither  //如果为true,解码器尝试抖动解码

public Bitmap.Config inPreferredConfig  //设置解码器

这个值是设置色彩模式,默认值是ARGB_8888,在这个模式下,一个像素点占用4bytes空间,一般对透明度不做要求的话,一般采用RGB_565模式,这个模式下一个像素点占用2bytes。

public String outMimeType  //设置解码图像

public boolean inPurgeable //当存储Pixel的内存空间在系统内存不足时是否可以被回收

public boolean inInputShareable  //inPurgeable为true情况下才生效,是否可以共享一个InputStream

public boolean inPreferQualityOverSpeed  //为true则优先保证Bitmap质量其次是解码速度

public boolean inMutable  //配置Bitmap是否可以更改,比如:在Bitmap上隔几个像素加一条线段

public int inScreenDensity  //当前屏幕的像素密度

从资源中获取位图的方式有两种:通过BitmapDrawable或者BitmapFactory

你可以创建一个构造一个BitmapDrawable对象,比如通过流构建BitmapDrawable:

BitmapDrawable bmpMeizi = new BitmapDrawable(getAssets().open("pic_meizi.jpg")); Bitmap mBitmap = bmpMeizi.getBitmap(); img_bg.setImageBitmap(mBitmap);

工厂方法:

public static Bitmap decodeFile(String pathName, Options opts)  //从文件读取图片

public static Bitmap decodeFile(String pathName)

public static Bitmap decodeStream(InputStream is)  //从输入流读取图片

public static Bitmap decodeStream(InputStream is, Rect outPadding, Options opts)

public static Bitmap decodeResource(Resources res, int id)  //从资源文件读取图片

public static Bitmap decodeResource(Resources res, int id, Options opts)

public static Bitmap decodeByteArray(byte[] data, int offset, int length)  //从数组读取图片

public static Bitmap decodeByteArray(byte[] data, int offset, int length, Options opts)

public static Bitmap decodeFileDescriptor(FileDescriptor fd) //从文件读取文件 与decodeFile不同的是这个直接调用JNI函数进行读取 效率比较高

public static Bitmap decodeFileDescriptor(FileDescriptor fd, Rect outPadding, Options opts)

首先了解一下关于Bitmap的Config的理解

A:透明度 R:红色 G:绿 B:蓝

Bitmap.Config ARGB_4444:每个像素占四位,即A=4,R=4,G=4,B=4,那么一个像素点占4+4+4+4=16位

Bitmap.Config ARGB_8888:每个像素占四位,即A=8,R=8,G=8,B=8,那么一个像素点占8+8+8+8=32位

Bitmap.Config RGB_565:每个像素占四位,即R=5,G=6,B=5,没有透明度,那么一个像素点占5+6+5=16位

Bitmap.Config ALPHA_8:每个像素占四位,只有透明度,没有颜色。

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

起决定因素就是最后那个参数了,Bitmap'常见有2种编码方式:ARGB_8888和RGB_565,ARGB_8888每个像素点4个byte,RGB_565是2个byte,一般都采用ARGB_8888这种。那么常见的1080*1920的图片内存占用就是:

1920 x 1080 x 4 = 7.9M

常用的压缩方法:

1.质量压缩

private void compressQuality() { Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.test); mSrcSize = bm.getByteCount() + "byte"; ByteArrayOutputStream bos = new ByteArrayOutputStream(); bm.compress(Bitmap.CompressFormat.JPEG, 100, bos); byte[] bytes = bos.toByteArray(); mSrcBitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length); }

质量压缩不会减少图片的像素,它是在保持像素的前提下改变图片的位深及透明度,来达到压缩图片的目的,图片的长,宽,像素都不会改变,那么bitmap所占内存大小是不会变的。

我们可以看到有个参数:quality,可以调节你压缩的比例,但是还要注意一点就是,质量压缩堆png格式这种图片没有作用,因为png是无损压缩。

2.采样率压缩

private void compressSampling() { BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = 2; mSrcBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.test, options); }

采样率压缩其原理其实也是缩放bitamp的尺寸,通过调节其inSampleSize参数,比如调节为2,宽高会为原来的1/2,内存变回原来的1/4.

3.放缩法压缩

private void compressMatrix() { Matrix matrix = new Matrix(); matrix.setScale(0.5f, 0.5f); Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.test); mSrcBitmap = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true); bm = null; }

放缩法压缩使用的是通过矩阵对图片进行裁剪,也是通过缩放图片尺寸,来达到压缩图片的效果,和采样率的原理一样

4.RGB_565压缩

private void compressRGB565() { BitmapFactory.Options options = new BitmapFactory.Options(); options.inPreferredConfig = Bitmap.Config.RGB_565; mSrcBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.test, options); }

这是通过压缩像素占用的内存来达到压缩的效果,一般不建议使用ARGB_4444,因为画质实在是辣鸡,如果对透明度没有要求,建议可以改成RGB_565,相比ARGB_8888将节省一半的内存开销。

5.createScaledBitmap

private void compressScaleBitmap() { Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.test); mSrcBitmap = Bitmap.createScaledBitmap(bm, 600, 900, true); bm = null; }

将图片的大小压缩成用户的期望大小,来减少占用内存。

图片二次采样

private Bitmap getCompressBm(int id, int maxw, int maxh) {

Bitmap bm = null;

int iSamplesize = 1;

//第一次采样

BitmapFactory.Options bitmapFactoryOptions = new BitmapFactory.Options();

//该属性设置为true只会加载图片的边框进来,并不会加载图片具体的像素点

bitmapFactoryOptions.inJustDecodeBounds = true;

bm = BitmapFactory.decodeResource(getResources(), id, bitmapFactoryOptions);

Log.e("Tag", "onActivityResult: 压缩之前图片的宽:" + bitmapFactoryOptions.outWidth + "--压缩之前图片的高:"

+ bitmapFactoryOptions.outHeight + "--压缩之前图片大小:" + bitmapFactoryOptions.outWidth * bitmapFactoryOptions.outHeight * 4 / 1024 + "kb");

int iWidth = bitmapFactoryOptions.outWidth;

int iHeight = bitmapFactoryOptions.outHeight;

//对缩放比例进行调整,直到宽和高符合我们要求为止

while (iWidth > maxw|| iHeight > maxh){

//如果宽高的任意一方的缩放比例没有达到要求,都继续增大缩放比例

//sampleSize应该为2的n次幂,如果给sampleSize设置的数字不是2的n次幂,那么系统会就近取

iSamplesize = iSamplesize*2;//宽高均为原图的宽高的1/2 内存约为原来的1/4

iWidth = iWidth/iSamplesize;

iHeight = iHeight/iSamplesize;

}

//二次采样开始

//二次采样时我需要将图片加载出来显示,不能只加载图片的框架,因此inJustDecodeBounds属性要设置为false

bitmapFactoryOptions.inJustDecodeBounds = false;

bitmapFactoryOptions.inSampleSize = iSamplesize;

// 设置像素颜色信息

// bitmapFactoryOptions.inPreferredConfig = Bitmap.Config.RGB_565;

bm = BitmapFactory.decodeResource(getResources(),id, bitmapFactoryOptions);

//默认的图片格式是Bitmap.Config.ARGB_8888

Log.e("Tag", "onActivityResult: 图片的宽:" + bm.getWidth() + "--图片的高:"

+ bm.getHeight() + "--图片大小:" + bm.getWidth() * bm.getHeight() * 4 / 1024 + "kb");

return bm;//返回压缩后的照片

}

相关文章

  • 图片压缩,二次采样

    图片压缩就是为了避免我们内存溢出,所有要对一系列进行压缩二次采样等 1.什么是OOM?为什么会引起OOM? out...

  • Android 图片压缩处理避免出现oom的方法

    1. 通过设置采样率压缩 res资源图片压缩 decodeResource uri图片压缩 decodeStrea...

  • Android图片压缩(二次采样)

    一、简介: 在开发过程中,我们或多或少的都会接触到Bitmap这个东西,用的不好的话就会出现OOM问题,同时,也会...

  • 图片二次采样和压缩

    图片的存在形式 1.文件形式(即以二进制形式存在于硬盘上) 2.流的形式(即以二进制形式存在于内存中) 3.Bit...

  • 图片优化(一)Bitmap优化

    1.BitmapFactory2.图片存在的形式3.图片压缩方式 质量压缩 尺寸压缩 采样率压缩 1.图片工具类:...

  • Bitmap知识点

    采样率压缩 根据ImageView的大小,通过设置inSampleSize采样率,加载压缩后的图片。如下: inS...

  • 图片压缩

    图片压缩质量压缩,比例压缩,采样率压缩,JPEG压缩思路:根据控件的尺寸或图片要放大显示的尺寸作为参数去压缩图片原...

  • 图片压缩

    图片压缩一般有3种: 1.采样率压缩又叫邻近采样压缩,inSampleSzie为2的倍数,这种方式比较粗暴,直接选...

  • 终极图片压缩

    图片优化压缩方式大概可以分为以下几类:更换图片格式,质量压缩,采样率压缩,缩放压缩,调用jpeg压缩等 1、设置图...

  • 性能优化——Android图片压缩与优化的几种方式

    图片优化压缩方式大概可以分为以下几类:更换图片格式,质量压缩,采样率压缩,缩放压缩,调用jpeg压缩等 1、设置图...

网友评论

      本文标题:图片压缩,二次采样

      本文链接:https://www.haomeiwen.com/subject/rwslyftx.html