android图片压缩

非原创,只是整理,如果里面发现引用的内容没有标识出来,欢迎指出。

一、基本知识

(1)两种图片:

1)矢量图:

矢量图又叫向量图,是用一系列计算机指令来描述和记录一幅图,一幅图可以解为一系列由点、线、面等到组成的子图,它所记录的是对象的几何形状、线条粗细和色彩等。生成的矢量图文件存储量很小,无论放大和缩小多少倍,图形都有一样的平滑边缘和清晰的视觉效果。

例如,输入法的文字就是矢量图。

2)点阵图(位图):

就是图象由无数个点(像素)组成。每个像素里都由一个颜色表现,所以点阵图是有一个个有颜色的点(像素)排列而成。我们平时看到的文件格式有PSD、TIF、JPG、GIF等都是点阵图,数码相机拍摄的照片就是点阵图。

(2)像素(pixel简称px):

在位图中,图片是由很多点组成,那每个点就是1个像素。像素是屏幕中可以显示的最小元素单元,我们应用里任何可见的东西都是由一个个像素点组成的。单独一个像素点非常的微小,肉眼是无法看见的,可是当许许多多的像素点聚集到一起时,就可以拼接成五彩缤纷的图案。

(3)屏幕尺寸

屏幕尺寸指屏幕的对角线的长度,单位是英寸,1英寸=2.54厘米

比如常见的屏幕尺寸有2.4、2.8、3.5、3.7、4.2、5.0、5.5、6.0等

(4)分辨率:

图像分辨率:图像分辨率是指每英寸图像内的像素点数。这里的分辨率其实是密度,是指1英寸里有多少像素。它以  像素/英尺(ppi)为单位,如一个图像的分辨率为72ppi,就表示该图像中每英尺包含72个像素。(但是现在通常将分辨率表示成每一个方向上的像素数量,比如 640X480 等。)

屏幕分辨率:屏幕分辨率是指在横纵向上的像素点数,单位是px,1px=1个像素点,每个屏幕有自己的分辨率。一般以纵向像素*横向像素,如1960*1080。屏幕分辨率越高,所呈现的色彩越多,清晰度越高。

(5)色彩模式

图像的大小和质量不仅仅由像素总数决定,还跟色彩模型有关。色彩模型有RGB模式,CMYK模式,位图模式,灰度模式等等。

(6)图片大小

通过一个例子来理解:

选择一个24位深度分辨率为225×225的位图,

由于24位位图是真彩色,没有颜色表,所以

其文件大小为:152154=14+40+(225×3+1)×225

注:因为1个像素用三个字节来表示,所以乘以3;因为位图存储时,Windows规定一个扫描行所占的字节数必须是4的倍数(即以long为单位),不足的以0填充,225×3+1刚好是4的倍数;14和40是位图文件头和位图信息头的字节大小;

当利用绘图程序将文件保存为256色,即8位深度的位图后,文件大小变为52378字节:

52378 = 14 + 50 + 256 × 4 + (225 + 3)× 225

注:256色位图有颜色表,每个颜色表结构体是4字节,所以颜色表这一项占256*4 个字节;225+3 刚好凑成4的倍数

可见分辨率没变,因为位深从24变成了8。所以图像质量下降了,图像大小也变小了。

二、图片的存在形式:

1.文件形式(即以二进制形式存在于硬盘上)

获取大小(Byte):File.length()

2.流的形式(即以二进制形式存在于内存中)

获取大小(Byte):new FileInputStream(File).available()

3.Bitmap形式

获取大小(Byte):Bitmap.getByteCount()

这三种形式的区别:

文件形式和流的形式对图片体积大小并没有影响,也就是说,如果你手机SD卡上的如果是100K,那么通过流的形式读到内存中,也一定是占100K的内存,注意是流的形式,不是Bitmap的形式。当图片以Bitmap的形式存在时,其占用的内存会变大。

三、bitmap介绍:

(1) Bitmap.Config

一张图片Bitmap所占用的内存 =图片长度 x 图片宽度 x 一个像素点占用的字节数

而Bitmap.Config,正是指定单位像素占用的字节数的重要参数。

其中,A代表透明度;R代表红色;G代表绿色;B代表蓝色。

ALPHA_8

表示8位Alpha位图,即A=8,一个像素点占用1个字节,它没有颜色,只有透明度

ARGB_4444

表示16位ARGB位图,即A=4,R=4,G=4,B=4,一个像素点占4+4+4+4=16位,2个字节

ARGB_8888

表示32位ARGB位图,即A=8,R=8,G=8,B=8,一个像素点占8+8+8+8=32位,4个字节

RGB_565

表示16位RGB位图,即R=5,G=6,B=5,它没有透明度,一个像素点占5+6+5=16位,2个字节

Bitmap.Config主要作用是:

以何种方式像素存储。不同的配置将会影响图像的画质(色彩深度),位数越高画质越高,显然在这里ARGB_8888是最占内存的。当然,画质越高也就越占内存了。

Tips:由于ARGB_4444的画质惨不忍睹,一般假如对图片没有透明度要求的话,可以改成RGB_565,相比ARGB_8888将节省一半的内存开销。


配置不同Bitmap.Config在相同分辨率下的占用内存情况:

一张图片Bitmap所占用的内存 = 图片长度 x 图片宽度 x 一个像素点占用的字节数

在Android里面可以通过下面的代码来设置解码率

(2) Bitmap.CompressFormat

从字面上理解,它的含义是:Bitmap压缩格式

其实这个参数很简单,就是指定Bitmap是以JPEG、PNG还是WEBP格式来压缩

(3) Bitmap.compress()方法

重磅方法来了,通过这个方法,可以实现图片的压缩。使用该方法需要传三个参数进去:

CompressFormat

指定Bitmap的压缩格式,可选择JPEG、PNG、WEBP

int类型的quality

指定Bitmap的压缩品质,范围是0 ~ 100;该值越高,画质越高。0表示画质最差,100画质最高。

OutputStream

指定Bitmap的字节输出流。一般使用:

ByteArrayOutputStream stream = new ByteArrayOutputStream();

这个方法不改变图片分辨率,只通过改变编码格式来改变每个像素大小,从而改变图片大小和质量。

四、BitmapFactory

BitmapFactory是获取Bitmap和压缩Bitmap的重要类,下面开始介绍BitmapFactory几个重要的成员变量和方法:

(1)通过BitmapFactory解码(获取)Bitmap的几种方式

1)decodeFile()//从SD卡文件读取

Bitmap  bm=BitmapFactory.decodeFile(Environment.getExternalStorageDirectory().getAbsolutePath()+"/photo.jpg");

2)decodeResource()//从资源文件res读取

Bitmap bm=BitmapFactory.decodeResource(this.getResources(), R.mipmap.test_pic);

3)decodeStream()//从输入流读取

Bitmap bm=BitmapFactory.decodeStream(inputStream);

4)decodeByteArray()//从字节数组读取

Bitmap bm=BitmapFactory.decodeByteArray(bytes,0,bytes.length);


(2)BitmapFactory.Options

BitmapFactory在使用方法decodeFile()、decodeResource()解码图片时,可以指定它的BitmapFactory.Options。

这个参数作用非常大,它可以设置Bitmap的采样率,通过改变图片的宽度、高度、缩放比例等,以达到降低图片的像素的目的,这样可以做到图片压缩,减少Bitmap的内存

下面列出BitmapFactory.Options的部分成员变量:


in开头的代表的就是设置某参数;out开头的代表的就是获取某参数。比如,inSampleSize就是设置Bitmap的缩放比例、outWidth就是获取Bitmap的高度。

1) inJustDecodeBounds 设置只去读图片的附加信息(宽高),不去解析真实的Bitmap

从字面上理解,它的含义是:”设置仅解码Bitmap的边界”。那它真正的作用是啥呢?

当inJustDecodeBounds设置为true的时候,BitmapFactory通过decodeResource或者decodeFile解码图片时,将会返回空(null)的Bitmap对象,这样可以避免Bitmap的内存分配,但是它可以返回Bitmap的宽度、高度以及MimeType。


这样做的意义就在于,可以先不用产生Bitmap内存,从而获得图片的宽高信息,尽可能的做到节约内存。

2)inSampleSize 设置图片的缩放比例(宽和高)

这里注意,google推荐用2的倍数:

在这里着重讲一下这个inSampleSize。从字面上理解,它的含义是:”设置取样大小“。

它的作用是:设置inSampleSize的值(int类型)后,假如设为4,则宽和高都为原来的1/4,宽高都减少了,自然内存也降低了。

如图所示:

在这里参考Google官方文档来解释:

http://developer.android.com/intl/zh-cn/training/displaying-bitmaps/load-bitmap.html#load-bitmap

如何理解”设置取样大小“呢?如果你认真看了上面的内容话,聪明的你一定知道,肯定需要配合inJustDecodeBounds,先获取图片的宽、高【这个过程就是取样】,然后通过获取的宽高,动态的设置inSampleSize的值。

【当然,你也可以不动态,可以写死inSampleSize的值。比如设置inSampleSize = 4的话,一张分辨率为2048x1536px的图像将使用inSampleSize值为4的设置来解码,产生的Bitmap大小约为512*384px。相较于完整图片占用12M的内存,这种方式只需0.75M内存(假设Bitmap配置为ARGB_8888)。】

四、两种压缩方式:

(1)质量压缩:

将图片保存到本地时进行压缩, 即将图片从Bitmap形式变为File形式时进行压缩

该方法是利用compress方法。压缩图片的质量, 它不会减少图片的像素。

比方说, 你的图片是300K的, 1280*700像素的, 经过该方法压缩后, File形式的图片是在100k以下, 但是你BitmapFactory.decodeFile到内存中,变成Bitmap时,它的像素仍然是1280*700。计算图片像素的方法是 bitmap.getWidth()和bitmap.getHeight()。

(2)取样压缩

通过调整inSampleSize的值,在图片从本地读到内存时,进行压缩 ,即图片从File形式变为Bitmap形式。这种方式通过改变图像的尺寸(像素总数)来压缩,每个像素所占用的大小不变。

(3)常用的图片压缩方法是将两者结合。


参考资料:

http://blog.sina.com.cn/s/blog_9e1e8c1301015xat.html

http://www.tuicool.com/articles/eue6z2

http://anany.me/2015/10/15/bitmap1/

https://developer.android.com/training/displaying-bitmaps/load-bitmap.html

http://www.bubuko.com/infodetail-1041128.html

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容