前言
再平时开发中肯定都会用到图片相关知识,而平时大多都只会关注实现方面,但一些理论对于面试和更深入高级实现就很有用,比如很多第三方组件很多都已经实现,本篇文章先从图片加载内存计算、图片压缩、图片另存、图片一些上传等。
1、图片内存
计算公式如下:
内存=图片长度*宽度*单位像素占用字节数
注:图片长度和图片宽度的单位是像素。
创建一个BitMap时,其单位像素占用的字节数由其参数
BitmapFactory.Options的inPreferredConfig变量决定。
inPreferredConfig为
Bitmap.Config类型,
Bitmap.Config类是个枚举类型,它可以为以下值
简单点说
图片格式(Bitmap.Config) | 占用内存的计算方向 | 一张100*100的图片占用内存的大小 |
ALPHA_8 | 图片长度*图片宽度 | 100*100=10000字节 |
ARGB_4444 | 图片长度*图片宽度*2 | 100*100*2=20000字节 |
ARGB_8888 | 图片长度*图片宽度*4 | 100*100*4=40000字节 |
RGB_565 | 图片长度*图片宽度*2 | 100*100*2=20000字节 |

根据加载和未加载得到4579328大小
ViewTreeObserver vto = imageView.getViewTreeObserver();
vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
int height = imageView.getMeasuredHeight();
int width = imageView.getMeasuredWidth();
Log.i("HU", "width: " + width);
Log.i("HU", "height: " + height);
Log.i("HU","图片大小 222==width=:"+DeviceInfo.DipToPixels(MainActivity.this,width)+
"====height=="+DeviceInfo.DipToPixels(MainActivity.this,height));
return true;
}
});
得到实际的宽度和高度为:==width=:2346====height==1320
相除得到1.5,这个相对比较真实。
2、图片压缩
图片压缩一般对于面试中经常会提到或者是超大图片如何压缩到自己想要结果,比例又是如何计算出来的,压缩办法又几种,如何防止oom.
/**
* 图片压缩
* 质量压缩法
*/
private void compressImage() {
BitmapDrawable bd = (BitmapDrawable) imageView.getDrawable();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bd.getBitmap().compress(Bitmap.CompressFormat.JPEG, 100, baos);//质量压缩方法,这里100表示不压缩,把压缩
Log.e("HU","compressImage======bitmap=="+baos.size());
baos.reset();
bd.getBitmap().compress(Bitmap.CompressFormat.JPEG, 20, baos);//质量压缩方法,这里100表示不压缩,把压缩
Log.e("HU","compressImage===222===bitmap=="+baos.size());
}
09-22 16:56:29.621 22421-22421/? E/HU: compressImage======bitmap==187696
09-22 16:56:29.641 22421-22421/? E/HU: compressImage===222===bitmap==16652
100不压缩,按100分制,20就是20%压缩比例。
3、递归压缩不失真算法
/**
* 将bitmap按照最大的file size保存到指定文件
*
* @param bitmap 图片
*/
public static File saveImage(Bitmap bitmap,String fileNamePath) {
String storePath = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "ln";
File appDir = new File(storePath);
if (!appDir.exists()) {
appDir.mkdir();
}
String fileName = fileNamePath+ ".jpg";
File photoFile = new File(appDir, fileName);
FileOutputStream fileOutputStream = null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int maxSize=48*1024;
int scale = 100;
try {
fileOutputStream = new FileOutputStream(photoFile);
if (bitmap != null) {
if (bitmap.compress(Bitmap.CompressFormat.JPEG, scale, baos)) {
int baosSize = baos.toByteArray().length;
while (baosSize > maxSize && scale > 0) {
baos.reset();
bitmap.compress(Bitmap.CompressFormat.JPEG, scale, baos);
baosSize = baos.toByteArray().length;
scale -= 3;
}
// 缩放后的数据写入到文件中
baos.writeTo(fileOutputStream);
fileOutputStream.flush();
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
photoFile.delete();
e.printStackTrace();
} finally {
try {
if (fileOutputStream != null)
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return photoFile;
}