inDensity 原始密度:为0则设置为默认 160dpi; 文件夹代表密度
inTargetDensity 显示目标图片密度
inScreenDensity 屏幕密度
直接显示Bitmap占用内存会过大导致内存溢出OOM问题:
粗略方式:
计算公式:图片长 * 宽 * 4bytes/ARG_8888 - 不正确Native 方法中,mBitmapWidth = mOriginalWidth * (scale = opts.inTargetDensity / opts.inDensity) * 1/inSampleSize,
mBitmapHeight = mOriginalHeight * (scale = opts.inTargetDensity / opts.inDensity) * 1/inSampleSize
例如:
将一张 720x1080图片放在 drawable-xhdpi 目录下(inDensity = 320),
手机屏幕大小 1280 x 720(inTarget = 320),加载 xxhdpi (inDensity = 480)中的图片 1920 x 1080,scale = 320 / 480,inSampleSize = 1,最终获得的 Bitmap 的图像大小是 :
mBitmapWidth = opts.outWidth = 1080 * (320 / 480) * 1/1 = 720,
mBitmapHeight = opt.outHeight = 1920 * (320 / 480) * 1/1 = 1280,
getAllocatedMemory() = mBitmapWidth * mBitmapHeight * 4 = Bitmap占用内存。
inJustDecodeBounds:为true时仅返回 Bitmap 宽高等属性,返回bmp=null,为false时才返回占内存的 bmp;
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;//不分配bitmap内存:不会造成内存溢出OOM
/**
* decodeFile 本地文件
* decodeStream 网络上的图片
* decodeResource 资源文件中图片
*/
BitmapFactory.decodeFile(path, options);
int outHeight = options.outHeight;
int outWidth = options.outWidth;
获取计算inSampleSize对宽、高,压缩
inSampleSize:表示 Bitmap 的压缩比例,值必须 > 1 & 是2的幂次方。inSampleSize = 2 时,表示压缩宽高各1/2,最后返回原始图1/4大小的Bitmap;
public static int calculateInSampleSize(BitmapFactory.Options options,
int reqWidth, int reqHeight) {
// 源图片的高度和宽度
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
// 计算出实际宽高和目标宽高的比率
final int heightRatio = Math.round((float) height / (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
// 选择宽和高中最小的比率作为inSampleSize的值,这样可以保证最终图片的宽和高
// 一定都会大于等于目标的宽和高。
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
return inSampleSize;
}
public class TestActivity extends RootActivity {
private ImageView imageView;
private Handler handler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
switch (msg.what) {
case 1:
imageView.setImageBitmap(bitmap);
break;
case 2:
RingToast.show("bitmap= null");
break;
}
return false;
}
});
@Override
protected void onInit() {
super.onInit();
setContentView(R.layout.activity_test);
}
@Override
protected void onFindViews() {
super.onFindViews();
imageView = findViewById(R.id.imageView);
}
public void onClick(View view) {
RingToast.show("下载");
if (view.getId() == R.id.localBtn) {
showResources();
} else
new DownloadImage("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1585219233084&di=3f992df116687f73f7174be2d602389b&imgtype=0&src=http%3A%2F%2Fa3.att.hudong.com%2F68%2F61%2F300000839764127060614318218_950.jpg").start();
}
private Bitmap bitmap;
private class DownloadImage extends Thread {
String path;
public DownloadImage(String path) {
this.path = path;
}
@Override
public void run() {
super.run();
HttpURLConnection urlConnection = null;
InputStream inputStream = null;
try {
URL url = new URL(path);
//保存本地
urlConnection = (HttpURLConnection) url.openConnection();
inputStream = urlConnection.getInputStream();
File file = createDir(Config.CAMERA_CLASS_PATH + File.separator + "原始图片" + ".jpg");
FileOutputStream outputStream = new FileOutputStream(file);
int hasRead = 0;
while ((hasRead = inputStream.read()) != -1) {
outputStream.write(hasRead);
}
outputStream.close();
//获取原图片尺寸
urlConnection = (HttpURLConnection) url.openConnection();
inputStream = urlConnection.getInputStream();
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(inputStream, null, options);
inputStream.close();
//获取压缩系数
BitmapFactory.Options options2 = new BitmapFactory.Options();
options2.inSampleSize = ImageToolsUtils.calculateInSampleSize(options, ScreenUtils.getScreenWidth(TestActivity.this), ScreenUtils.getScreenHeight(TestActivity.this));
// options2.inSampleSize = 1;
options2.inJustDecodeBounds = false;
//获取最终压缩图片bitmap
urlConnection = (HttpURLConnection) url.openConnection();
inputStream = urlConnection.getInputStream();
bitmap = BitmapFactory.decodeStream(inputStream, null, options2);
FileUtil.saveBitmap(bitmap);
if (bitmap != null) {
Message message = new Message();
message.what = 1;
handler.sendMessage(message);
} else {
Message message = new Message();
message.what = 2;
handler.sendMessage(message);
}
} catch (Exception e) {
RingLog.e("访问网络异常:" + e.getMessage());
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
try {
if (inputStream != null) {
inputStream.close();
}
} catch (IOException e) {
}
}
}
}
private void showResources() {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = false;
Bitmap bm = BitmapFactory.decodeResource(getResources(), R.mipmap.launch_welcome, options);
FileUtil.saveBitmap(bm);
//获取压缩系数
options.inSampleSize = ImageToolsUtils.calculateInSampleSize(options, 300, 300);
options.inJustDecodeBounds = false;
//获取最终压缩图片bitmap
bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.launch_welcome, options);
FileUtil.saveBitmap(bitmap);
if (bitmap != null) {
Message message = new Message();
message.what = 1;
handler.sendMessage(message);
} else {
Message message = new Message();
message.what = 2;
handler.sendMessage(message);
}
}
}
参考:
https://www.jianshu.com/p/4ba3e63c8cdc
https://www.tuicool.com/articles/3eMNr2n
https://blog.csdn.net/guolin_blog/article/details/9316683
https://www.codercto.com/a/32923.html