图片处理

420 阅读2分钟

压缩流程

处理图片旋转

有些手机拍照的图片会自动旋转。需要将图片旋转回来

处理过程:

  • 获取ExifInterface,拿到旋转角度。
  • 使用矩阵把图片摆正

图片压缩

ANR

尺寸压缩(inSampleSize)

通过减少单位尺寸的像素值,真正意义上的降低像素值。

处理过程:

  • 如果图片宽高大于服务器要求的宽高
  • BitmapFactory.Options用于图片解码时的参数控制
  • 设置BitmapFactory.Options=true,返回bitmap为null,避免bitmap的内存分配,只获取bitmap信息,获取图片宽高
  • 根据图片宽高和目标图片宽高计算采样率
  • 图片宽高/目标宽高取最小值作为目标采样率
  • 采样率必须是2的倍数,需要额外做处理??
  • 将inJustDecodeBounds=false,设置inSampleSize,通过BitmapFactory.decodeFile拿到目标bitmap

质量压缩

通过算法扣掉(同化) 图片中的一些某个点附近相近的像素,达到降低质量 减少 文件大小的目的。

过程

  • 当图片大小大于服务器要求的图片大小
  • bitmap(compress)压缩成字节输出流,计算字节大小,小于最大值,继续压缩
  • 压缩系数从70开始,-5依次递减压缩,直到小于最大值

保存文件

文件输出流

上传到后台

  • OKHTTP传递文件需要传key值
  • 文件名,最好把文件名转成BASE64编码(中文会出错)

图片大小计算

Bitmap getByteCount() =getRowBytes() * getHeight(); 资源文件:width * height * nTargetDensity/inDensity * nTargetDensity/inDensity * 一个像素所占的内存; 其他:图片的占用内存 = 图片的长度(像素单位) * 图片的宽度(像素单位) * 单位像素所占字节数

加载图片占多少内存

下载图片后的大小+解码成Bitmap占用内存的大小

Bitmap占用的内存大小:getByteCount()或者getAllocationByteCount()

  • 一般情况下两者是相等的;
  • 通过复用Bitmap来解码图片,如果被复用的Bitmap的内存比待分配内存的Bitmap大,那么getByteCount()表示新解码图片占用内存的大小(并非实际内存大小,实际大小是复用的那个Bitmap的大小),getAllocationByteCount()表示被复用Bitmap真实占用的内存大小(即mBuffer的长度)。

bitmap优化

  • 选择适合的解码方式(ARGB_8888以及RGB_565)
  • 尺寸压缩(inSampleSize)
  • 质量压缩,选择适合的像素格式
  • 使用矩阵(绘制的图放大,占用的内存却仍然是我们采样出来的大小)。

图片保存

选择适合的编码方式

  • jpg: 是一种有损压缩的图片存储格式,没有 alpha 通道
  • png :则是 无损压缩的图片存储格式,有 alpha 通道 选择思路
  • 色彩丰富的选择jpg,色彩单调选择png
  • 减少耗时,选择png
  • 减少内存,选择jpg
  • 需要alpha通道选择jpg,否则选择png