Android Bitmap使用
Posted 花姓-老花
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android Bitmap使用相关的知识,希望对你有一定的参考价值。
在android开发中,跟图片打交道在正常不过了。不过如果图片处理不当就会造成内存溢出(OOM),所以了解Bitmap相关用法就有必要了,Bitmap在Android中指的是一张图片,图片类型可以是png、jpg等。
1、BitmapFactory
BitmapFactory进一步封装了获取Bitmap对象,BitmapFactory提供获取Bitmap对象的方法有以下:
1、decodeByteArray 从指定字节数组中获取
用法:
private void getBitmap()
//主要是把网络图片的数据流读入到内存中
new Thread(new Runnable()
@Override
public void run()
//Android4.0以后,网络请求一定要在子线程中进行
final byte[] data = getImages("http://img5.imgtn.bdimg.com/it/u=274881988,3237971911&fm=27&gp=0.jpg");
//更新UI可以在runOnUiThread这个方法或通过handler
runOnUiThread(new Runnable()
@Override
public void run()
Bitmap bitmap = BitmapFactory.decodeByteArray(data,0,data.length);
mImage.setImageBitmap(bitmap);
);
).start();
private byte[] getImages(String path)
try
URL url = new URL(path);
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setRequestMethod("GET");
httpURLConnection.setReadTimeout(6*1000);
InputStream inputStream = null;
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = -1;
if (httpURLConnection.getResponseCode() == HttpURLConnection.HTTP_OK)
inputStream = httpURLConnection.getInputStream();
while ((len = inputStream.read(buffer)) !=-1)
outputStream.write(buffer,0,len);
outputStream.close();
inputStream.close();
return outputStream.toByteArray();
catch (MalformedURLException e)
e.printStackTrace();
catch (IOException e)
e.printStackTrace();
return null;
注:网络请求一定要在子线程中来做,否则就会抛NetworkOnMainThreadException异常
2、decodeFile、decodeFileDescriptor 从指定文件中获取
用法:
private void getDecodeFileBitmap()
String fileName = "/sdcard/daniulivelogo.png"; //自己手机sd图片路径
File file = new File(fileName);
if (file.exists())
Bitmap bm = BitmapFactory.decodeFile(fileName);
mImage.setImageBitmap(bm);
else
Log.v("hjz","文件不存在");
注:sd相对路径
有外置内存:/sdcard/Android/data/<application package>/cache
无外置内存:/data/data/Android/data/<application package>/cache
3、decodeResource 从指定本地资源获取
private void getDecodeResourceBitmap()
Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher);
mImage.setImageBitmap(bitmap);
4、decodeStream 从输入流中获取
用法:
private void getDecodeStreamBitmap()
new Thread(new Runnable()
@Override
public void run()
final Bitmap bitmap = getImageFromNet("http://img5.imgtn.bdimg.com/it/u=274881988,3237971911&fm=27&gp=0.jpg");
runOnUiThread(new Runnable()
@Override
public void run()
mImage.setImageBitmap(bitmap);
);
).start();
private Bitmap getImageFromNet(String path)
HttpURLConnection httpURLConnection = null;
InputStream inputStream = null;
try
URL url = new URL(path);
httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setRequestMethod("GET");
httpURLConnection.setReadTimeout(6 * 1000);
if (httpURLConnection.getResponseCode() == HttpURLConnection.HTTP_OK)
inputStream = httpURLConnection.getInputStream();
return BitmapFactory.decodeStream(inputStream);
catch (MalformedURLException e)
e.printStackTrace();
catch (IOException e)
e.printStackTrace();
finally
if (inputStream != null)
try
inputStream.close();
inputStream = null;
catch (IOException e)
e.printStackTrace();
if (httpURLConnection != null)
httpURLConnection.disconnect();
return null;
上面是没有添加任何策略的常规用法,容易造成OOM现象。
2、BitmapFactory.Options
高效加载类图其核心就是BitmapFactory.Options,在开发中很多时候并不需要图片原图大小和原图这么高清,目的对图片进行采样压缩,降低内存占有空间,从而减少了内存溢出(OOM)问题。
1、BitmapFactory.Options常用方法:
参数 | 说明 | 备注 |
---|---|---|
inJustDecodeBounds | 如果设置为true,则只返回bitmap尺寸,没有为 其分配内存 如果设置为false,解码返回位图,为其分配内存 | 预加载图片,获取图片尺寸 |
inSampleSize | 当设置值>1时,按相关比例缩放bitmap宽高,返回较小图片在保存 当设置值<=1时,就当做1来处理 | 案例:width=100,height=100,inSampleSize = 2, 则返回width=50,height=50,像素50*50=250 图片将为了原来1/4 |
inPreferredConfig | 如果这是非空的,解码器将尝试解码到这个内部配置。如果它是null, 或者请求不能满足,解码器将尝试根据系统的屏幕深度选择 最佳匹配配置,以及原始图像的特性,例如它是否具有每像素alpha (需要配置)。图像加载默认的配置argb_8888。 另外:色彩模式,默认argb_8888,一个像素4byte。如果对透明不做要求,采用rgb_565,一个像素2byte | alpha_8:每个像素1byte argb_444:每个像素2byte argb_8888:每个像素4byte rgb_565:每个像素2byte 场景:如果一张图片分辨率1024*768, 采用argb_8888,占用空间为1024*768*4=3M; 如果采用argb_444内存就能减半 |
inPremultiplied | 默认true,返回的bitmap颜色通道上预先附加透明通道 | 透明通道是计算机图形学术语,指的是“非彩色”通道, 8位灰度通道,使用256级灰度来记录图像中的透明信息, 定义透明、不透明和半透明。如32位存储的图片, 8红+8绿+8蓝+8透明; |
inDither | 抖动解码,默认false,标识不采用抖动解码 | Bitmap解码是根据它所记录的节点,按照一定的算法来 补充两个节点之间的数据,可理解为补充像素点的颜色。 一张颜色丰富的图用一个位数比较低的颜色模式解码的话, 会感觉颜色不够用,颜色渐变区域有明显断裂带。 因为一些丰富的颜色在位数较低的颜色模式下并没有, 只能用相近的颜色补充,可能一大片没有,那么这大片 都用一个颜色填充,就形成了断裂色带;如果采用 抖动解码,就会在这些颜色上采用随机噪声色来填充,这样 显示效果更好,色带不那么明显。如果不想有这些色带,就需要采用抖动解码 |
inScaled | 设置这个bitmap是否可以被缩放,默认值为true | |
inDensity | 表示这个bitmap的像素密度 | |
inTargetDensity | 目标位图的像素密度将被绘制到 | |
inScreenDensity | 正在使用的实际屏幕的像素密度 | inDensity,inTargetDensity,inScreenDensity 这三个值的目的就是为了确定这个Bitmap的宽高和density。详细算法可以查看 setDensityFromOptions()方法源码实现; |
inPurgeable/inInputShareable | 一般一起使用,设置为true时,表示空间不够可以被释放, 后者表示是否可以共享引用。Android5.0后被弃用 | |
outWidth/outHeight | 表示bitmap的宽和高,一般和inJustDecodeBounds一起使用获取Bitmap的宽高,但不加载到内存中 |
2、BitmapFactory.Options实战
String fileName = "/sdcard/aa.jpg";
BitmapFactory.Options options = getBitmapFactory(fileName,400,400);
mImage2.setImageBitmap(BitmapFactory.decodeFile(fileName,options));
private BitmapFactory.Options getBitmapFactory(String fileName,int pixelW,int pixelH)
BitmapFactory.Options options = new BitmapFactory.Options();
File file = new File(fileName);
if (file.exists())
//inJustDecodeBounds为true,不返回bitmap,只返回这个bitmap的尺寸
options.inJustDecodeBounds = true;
//设置图片色彩
options.inPreferredConfig = Bitmap.Config.RGB_565;
//预加载图片
Bitmap bitmap = BitmapFactory.decodeFile(fileName,options);
//获取原始图片宽高
int originalW = options.outWidth;
int originalH = options.outHeight;
//上面设置为true获取bitmap尺寸大小,在这里一定要重新设置为false,否则位图加载不出来
options.inJustDecodeBounds = false;
options.inSampleSize = getSampleSize(originalW,originalH,pixelW,pixelH);
return options;
return null;
/**
*
* @param originalW 原图宽
* @param originalH 原图高
* @param pixelW 指定图片宽度
* @param pixelH 指定图片高度
* @return 返回原图缩放大小
*/
private int getSampleSize(int originalW, int originalH, int pixelW, int pixelH)
int simpleSize = 1;
if (originalW > originalH && originalW > pixelW)
simpleSize = originalW / pixelW;
else if (originalH > originalW && originalH > pixelH)
simpleSize = originalH / pixelH;
if (simpleSize <=0)
simpleSize = 1;
return simpleSize;
以上是关于Android Bitmap使用的主要内容,如果未能解决你的问题,请参考以下文章
Bitmap处理--BitmapShader、目标大小Bitmap、遮罩图层