1. 背景
项目上的需求,拍照上传到后台。没有任何经验,以为很简单,按照给定的接口,用xutils很快就写好接口了,就等后台实现。但是事实上要复杂些,考虑到业务上的问题,流量,效率问题,还有http报文的长度问题,就要多做一些处理了,那就是图片压缩。因为现在的手机随便拍一张照片都是那么1M以上,稍微好点的手机3M、5M甚至更大是很正常的事。这个时候,如果上传原图,老板不拍死你才怪呢。除了老板之外,由于后台服务器的限制,也不可能上传这么大的文件。
2. 解决方法
既然是图片大了,那么就压缩吧。首先,我们要确定我们业务需求什么样的图片,对质量、大小有什么要求,确定好这些问题后我们再实现压缩。
3. 图片压缩原理
考虑bitmap位图,如图所示,我们看到的一张图片直观看作是一个n*m的表格,表格中的每一个小格代表一个像素,每一个像素点代表一种颜色,这样所有的像素点排列起来显示就是我们所看到的图片了。
(0,0) |
(0,1) |
(0,2) |
(0,3) |
(0,4) |
…. |
(0,n-1) |
(1,0) |
|
|
|
|
|
|
(2,0) |
|
|
|
|
|
|
(3,0) |
|
|
|
|
|
|
(4,0) |
|
|
|
|
|
|
….. |
|
|
|
|
|
|
(m-1,0) |
|
|
|
|
|
|
一张图片的大小是这样计算的:
size = length*width*deep(单位为字节Byte)(1-1)
length和width即是长和宽,length*width=pixels(像素总数),deep理解为位深,它的大小决定了所有可能颜色的总量,怎么说呢,要描述得越细节,那么需要的颜色就要越多,而占存储空间就会越大(在相同像素数量下)。
deep = 1byte,颜色有256种,灰度图用这个数量颜色表示也够了
deep = 2byte,颜色有256*256,彩色图,质量还好(在android里面貌似是取前面5bit为R,中间6bit为G,后面5bit为B)
deep = 3byte,颜色有256*256*256种,可以表示我们最容易理解的RGB三原色
deep = 4byte,颜色有256*256*256*256种,也是我们比较容易理解的ARGB(A为透明度)
8位,16位,32位,应该是三种颜色模型,针对这三种模型就有不同的存储结构,也就有了不同的读取方法,对图像进行像素级别的处理时就要根据不同的颜色模型,不同的存储结构用不同的读取方式这样才能正确进行处理(当然有android那么强大的api不会要自己写这些代码的)。
回到我们的图片大小公式(1-1),如何压缩图片相信大家基本有那么一点自己的认识了吧。没错,压缩图片可以从两个方面去考虑(1)减少像素length*width(2)降低图片质量deep