Android Bitmap 与 Drawable之间的区别和转换
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android Bitmap 与 Drawable之间的区别和转换相关的知识,希望对你有一定的参考价值。
android bitmap和drawable的区别和转换如下:
1.bitmap 转换 drawable
Bitmap bitmap = new Bitmap(...); Drawable drawable = new BitmapDrawable(bitmap);//Drawable drawable = new FastBitmapDrawable(bitmap);
2.Drawable to Bitmap
BitmapDrawable, FastBitmapDrawable直接用getBitmap
b. 其他类型的Drawable用Canvas画到一个bitmap上
drawable.draw(canvas);
Drawable d = ImagesList.get(0); Bitmap bitmap = ((BitmapDrawable)d).getBitmap();
区别如下:
1.Bitmap - 称作位图,一般位图的文件格式后缀为bmp,当然编码器也有很多如RGB565、RGB888。作为一种逐像素的显示对象执行效率高,但是缺点也很明显存储效率低。
2.Drawable - 作为Android平下通用的图形对象,它可以装载常用格式的图像,比如GIF、PNG、JPG,当然也支持BMP,当然还提供一些高级的可视化对象,比如渐变、图形等。
另外还有如下相类似的格式:
Canvas - 名为画布,可以看作是一种处理过程,使用各种方法来管理Bitmap、GL或者Path路径,同时它可以配合Matrix矩阵类给图像做旋转、缩放等操作,同时Canvas类还提供了裁剪、选取等操作。
Paint - 可以把它看做一个画图工具,比如画笔、画刷。管理了每个画图工具的字体、颜色、样式。
参考技术A Bitmap - 称作位图,一般位图的文件格式后缀为bmp,当然编码器也有很多如RGB565、RGB888。作为一种逐像素的显示对象执行效率高,但是缺点也很明显存储效率低。我们理解为一种存储对象比较好。Drawable - 作为Android平下通用的图形对象,它可以装载常用格式的图像,比如GIF、PNG、JPG,当然也支持BMP,当然还提供一些高级的可视化对象,比如渐变、图形等。
A bitmap is a Drawable. A Drawable is not necessarily a bitmap. Like all thumbs are fingers but not all fingers are thumbs.
Bitmap是Drawable . Drawable不一定是Bitmap .就像拇指是指头,但不是所有的指头都是拇指一样.
The API dictates: API规定:
Though usually not visible to the application, Drawables may take a variety of forms: 尽管通常情况下对于应用是不可见的,Drawables 可以采取很多形式:
Bitmap: the simplest Drawable, a PNG or JPEG image. Bitmap: 简单化的Drawable, PNG 或JPEG图像.
Nine Patch: an extension to the PNG format allows it to specify
information about how to stretch it and place things inside of it.
Shape: contains simple drawing commands instead of a raw bitmap, allowing it to resize better in some cases.
Layers: a compound drawable, which draws multiple underlying drawables on top of each other.
States: a compound drawable that selects one of a set of drawables based on its state.
Levels: a compound drawable that selects one of a set of drawables based on its level.
Scale: a compound drawable with a single child drawable, whose overall size is modified based on the current level. 参考技术B bitmap 是位图,在Android中可以理解为 像素点组成的数组,drawable是一个指向ID。
下面是drawable转bitmap
public static Bitmap drawableToBitmap(Drawable drawable)
Bitmap bitmap = Bitmap.createBitmap(
drawable.getIntrinsicWidth(),
drawable.getIntrinsicHeight(),
drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888
: Bitmap.Config.RGB_565);
Canvas canvas = new Canvas(bitmap);
//canvas.setBitmap(bitmap);
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
drawable.draw(canvas);
return bitmap;
下面是bitmap转drawable
Drawable drawable =new BitmapDrawable(bmp); 参考技术C 一、相关概念
1、Drawable就是一个可画的对象,其可能是一张位图(BitmapDrawable),也可能是一个图形(ShapeDrawable),还有可能是一个图层(LayerDrawable),我们根据画图的需求,创建相应的可画对象
2、Canvas画布,绘图的目的区域,用于绘图
3、Bitmap位图,用于图的处理
4、Matrix矩阵
二、Bitmap
1、从资源中获取Bitmap
Java代码
Resources res = getResources();
Bitmap bmp = BitmapFactory.decodeResource(res, R.drawable.icon);
2、Bitmap → byte[]
Java代码
public byte[] Bitmap2Bytes(Bitmap bm)
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.PNG, 100, baos);
return baos.toByteArray();
3、byte[] → Bitmap
Java代码
public Bitmap Bytes2Bimap(byte[] b)
if (b.length != 0)
return BitmapFactory.decodeByteArray(b, 0, b.length);
else
return null;
4、Bitmap缩放
Java代码
public static Bitmap zoomBitmap(Bitmap bitmap, int width, int height)
int w = bitmap.getWidth();
int h = bitmap.getHeight();
Matrix matrix = new Matrix();
float scaleWidth = ((float) width / w);
float scaleHeight = ((float) height / h);
matrix.postScale(scaleWidth, scaleHeight);
Bitmap newbmp = Bitmap.createBitmap(bitmap, 0, 0, w, h, matrix, true);
return newbmp;
5、将Drawable转化为Bitmap
Java代码
public static Bitmap drawableToBitmap(Drawable drawable)
// 取 drawable 的长宽
int w = drawable.getIntrinsicWidth();
int h = drawable.getIntrinsicHeight();
// 取 drawable 的颜色格式
Bitmap.Config config = drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888
: Bitmap.Config.RGB_565;
// 建立对应 bitmap
Bitmap bitmap = Bitmap.createBitmap(w, h, config);
// 建立对应 bitmap 的画布
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, w, h);
// 把 drawable 内容画到画布中
drawable.draw(canvas);
return bitmap;
6、获得圆角图片
Java代码
public static Bitmap getRoundedCornerBitmap(Bitmap bitmap, float roundPx)
int w = bitmap.getWidth();
int h = bitmap.getHeight();
Bitmap output = Bitmap.createBitmap(w, h, Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final int color = 0xff424242;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, w, h);
final RectF rectF = new RectF(rect);
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
return output;
7、获得带倒影的图片
Java代码
public static Bitmap createReflectionImageWithOrigin(Bitmap bitmap)
final int reflectionGap = 4;
int w = bitmap.getWidth();
int h = bitmap.getHeight();
Matrix matrix = new Matrix();
matrix.preScale(1, -1);
Bitmap reflectionImage = Bitmap.createBitmap(bitmap, 0, h / 2, w,
h / 2, matrix, false);
Bitmap bitmapWithReflection = Bitmap.createBitmap(w, (h + h / 2),
Config.ARGB_8888);
Canvas canvas = new Canvas(bitmapWithReflection);
canvas.drawBitmap(bitmap, 0, 0, null);
Paint deafalutPaint = new Paint();
canvas.drawRect(0, h, w, h + reflectionGap, deafalutPaint);
canvas.drawBitmap(reflectionImage, 0, h + reflectionGap, null);
Paint paint = new Paint();
LinearGradient shader = new LinearGradient(0, bitmap.getHeight(), 0,
bitmapWithReflection.getHeight() + reflectionGap, 0x70ffffff,
0x00ffffff, TileMode.CLAMP);
paint.setShader(shader);
// Set the Transfer mode to be porter duff and destination in
paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
// Draw a rectangle using the paint with our linear gradient
canvas.drawRect(0, h, w, bitmapWithReflection.getHeight()
+ reflectionGap, paint);
return bitmapWithReflection;
三、Drawable
1、Bitmap转换成Drawable
Java代码
Bitmap bm=xxx; //xxx根据你的情况获取
BitmapDrawable bd= new BitmapDrawable(getResource(), bm);
因为BtimapDrawable是Drawable的子类,最终直接使用bd对象即可。
2、Drawable缩放
Java代码
public static Drawable zoomDrawable(Drawable drawable, int w, int h)
int width = drawable.getIntrinsicWidth();
int height = drawable.getIntrinsicHeight();
// drawable转换成bitmap
Bitmap oldbmp = drawableToBitmap(drawable);
// 创建操作图片用的Matrix对象
Matrix matrix = new Matrix();
// 计算缩放比例
float sx = ((float) w / width);
float sy = ((float) h / height);
// 设置缩放比例
matrix.postScale(sx, sy);
// 建立新的bitmap,其内容是对原bitmap的缩放后的图
Bitmap newbmp = Bitmap.createBitmap(oldbmp, 0, 0, width, height,
matrix, true);
return new BitmapDrawable(newbmp); 参考技术D Bitmap - 称作位图,一般位图的文件格式后缀为bmp,当然编码器也有很多如RGB565、RGB888。作为一种逐像素的显示对象执行效率高,但是缺点也很明显存储效率低。我们理解为一种存储对象比较好。
Drawable - 作为Android平下通用的图形对象,它可以装载常用格式的图像,比如GIF、PNG、JPG,当然也支持BMP,当然还提供一些高级的可视化对象,比如渐变、图形等。
A bitmap is a Drawable. A Drawable is not necessarily a bitmap. Like all thumbs are fingers but not all fingers are thumbs.
Bitmap是Drawable . Drawable不一定是Bitmap .就像拇指是指头,但不是所有的指头都是拇指一样.
The API dictates: API规定:
Though usually not visible to the application, Drawables may take a variety of forms: 尽管通常情况下对于应用是不可见的,Drawables 可以采取很多形式:
Bitmap: the simplest Drawable, a PNG or JPEG image. Bitmap: 简单化的Drawable, PNG 或JPEG图像.
Nine Patch: an extension to the PNG format allows it to specify information about how to stretch it and place things inside of it.
Shape: contains simple drawing commands instead of a raw bitmap, allowing it to resize better in some cases.
Layers: a compound drawable, which draws multiple underlying drawables on top of each other.
States: a compound drawable that selects one of a set of drawables based on its state.
Levels: a compound drawable that selects one of a set of drawables based on its level.
Scale: a compound drawable with a single child drawable, whose overall size is modified based on the current level.
小结:
对比项 显示清晰度 占用内存 支持缩放 支持色相色差调整 支持旋转 支持透明色 绘制速度 支持像素操作
Bitmap 相同 大 是 是 是 是 慢 是
Drawable 相同 小 是 否 是 是 快 否
Drawable在内存占用和绘制速度这两个非常关键的点上胜过Bitmap
//转换Bitmap to Drawable
Bitmap bitmap = new Bitmap (...);
Drawable drawable = new BitmapDrawable(bitmap);
//转换Drawable to Bitmap
Drawable d = ImagesList.get(0);
Bitmap bitmap = ((BitmapDrawable)d).getBitmap();
//1、Drawable → Bitmap
public static Bitmap drawableToBitmap(Drawable drawable)
Bitmap bitmap = Bitmap
.createBitmap(
drawable.getIntrinsicWidth(),
drawable.getIntrinsicHeight(),
drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888
: Bitmap.Config.RGB_565);
Canvas canvas = new Canvas(bitmap);
//canvas.setBitmap(bitmap);
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
drawable.draw(canvas);
return bitmap;
//2、从资源中获取Bitmap
Resources res=getResources();
Bitmap bmp=BitmapFactory.decodeResource(res, R.drawable.pic);
//3、Bitmap → byte[]
private byte[] Bitmap2Bytes(Bitmap bm)
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.PNG, 100, baos);
return baos.toByteArray();
//4、 byte[] → Bitmap
private Bitmap Bytes2Bimap(byte[] b)
if(b.length!=0)
return BitmapFactory.decodeByteArray(b, 0, b.length);
else
return null;
第5个回答 2016-04-02 Bitmap - 称作位图,一般位图的文件格式后缀为bmp,当然编码器也有很多如RGB565、RGB888。作为一种逐像素的显示对象执行效率高,但是缺点也很明显存储效率低。我们理解为一种存储对象比较好。
Drawable - 作为Android平下通用的图形对象,它可以装载常用格式的图像,比如GIF、PNG、JPG,当然也支持BMP,当然还提供一些高级的可视化对象,比如渐变、图形等。
A bitmap is a Drawable. A Drawable is not necessarily a bitmap. Like all thumbs are fingers but not all fingers are thumbs.
Bitmap是Drawable . Drawable不一定是Bitmap .就像拇指是指头,但不是所有的指头都是拇指一样.
The API dictates: API规定:
Though usually not visible to the application, Drawables may take a variety of forms: 尽管通常情况下对于应用是不可见的,Drawables 可以采取很多形式:
Bitmap: the simplest Drawable, a PNG or JPEG image. Bitmap: 简单化的Drawable, PNG 或JPEG图像.
Nine Patch: an extension to the PNG format allows it to specify information about how to stretch it and place things inside of it.
Shape: contains simple drawing commands instead of a raw bitmap, allowing it to resize better in some cases.
Layers: a compound drawable, which draws multiple underlying drawables on top of each other.
States: a compound drawable that selects one of a set of drawables based on its state.
Levels: a compound drawable that selects one of a set of drawables based on its level.
Scale: a compound drawable with a single child drawable, whose overall size is modified based on the current level.
小结:
对比项 显示清晰度 占用内存 支持缩放 支持色相色差调整 支持旋转 支持透明色 绘制速度 支持像素操作
Bitmap 相同 大 是 是 是 是 慢 是
Drawable 相同 小 是 否 是 是 快 否
Drawable在内存占用和绘制速度这两个非常关键的点上胜过Bitmap
Drawable与Bitmap详解
Drawable与Bitmap对比
定义对比:
- Bitmap:称作位图,一般的位图的文件格式扩展名为.bmp,当然编码器也有很多,RGB565,RGB8888,作为一种追个像素的显示对象,执行效率高,但是存储效率低,可以理解成一种存储对象
- Drawable:Android下的通用的图片形象,它可以装载常用格式的图像,比如GIF,PNG,JPG,BMP,提供一些高级的可视化方法。
属性对比:
属性名 | Bitmap | Drawable |
显示清晰度 | 相同 | 相同 |
占用内存 | 大 | 小 |
支持缩放 | 是 | 是 |
支持色相色差的调整 | 是 | 否 |
支持旋转 | 是 | 是 |
支持透明色 | 是 | 是 |
绘制速度 | 慢 | 快 |
支持像素操作 | 是 | 否 |
绘图的便利性比较:
- Drawable有很多的派生类,可以实现渐变,层叠的效果
- Bitmap一般用来做空白画布来进行绘图
简易性比较:
- Drawable是自带画笔的,更改画笔的属性是可以直接更新到ShapeDrawable上的,但是Drawable子类使用Canvas并不方便,只能用来完成一些固有的功能,如果要使用Drawable来绘图,可以自定义Drawable
- Bitmap上可以按照之前绘制那样设置画笔,然后进行绘制
使用方式对比:
- Bitmap主要靠在View中通过Canvas.drawBitmap()函数画出来
- Drawable可以在View中通过Drawable.draw(Canvas canvas)函数画出来,也可以通过setImageBackground()、setBackgroundDrawable()来设置Drawable资源
总结:
- Bitmap在占用内存和绘制速度上不如Drawable的优势
- Bitmap绘图方便,Drawable调用paint方便调用canvas不方便
- Drawable有一些子类,可以方便完成一些绘图功能
- 自定义View的使用:
- Bitmap只有一种情况
- 在View中需要自己生成图像时,才会使用Bitmap绘图,绘图后的结果保存在这个Bitmap中,比如根据Bitmap生成它的倒影,在使用Xfermode来融合倒转的图片原图与渐变的图片的时候,就需要根据图片的大小来生成一张同样大小的渐变图片,必须使用Bitmap
- 当使用Drawable的子类能完成一些固有的功能的时候,优先选择Drawable
- 当需要使用Drawable的setImageBackground(), setBackgroundDrawable()的设置drawable资源函数的时候,只能选择Draawable
- 当在自定义View中在指定位置显示图像功能的时候,既可以使用Drawable,也可以使用Bitmap
- 除drawable和bitmap以外的地方,都可以使用自定义View来实现
Bitmap
- 之前绘制图像的时候,Canvas中保存着一个Bitmap对象,我们调用Canvas的各种绘制函数的时候,最终时绘制到其保存的Bitmap上,在onDraw(Canvas canvas)函数中,View对应一个Bitmap对象,canvas是通过这个Bitmap创建出来的,所以可以通过直接调用Canvas的函数进行绘制
Bitmap概述
- Bitmap在绘图中的使用方式:
- 转换为BitmapDrawable对象使用
- 当作画布来使用
1.转换为BitmapDrawable对象使用
//先转换为BitmapDrawable对象, 再将其用作资源背景
Bitmap bitmap = BitmapFactory.decodeResource(res, R.drawable.picture);
BitmapDrawable bmp = new BitmapDrawable(bitmap);
image.setImagebackground(bmp);
2.当作画布使用
//方式一:使用默认的画布, 这里面View对应一个默认的Bitmap对象,canvas已经默认使用这个bitmap创建出来,最终绘制在这个Bitmap上
public void onDraw(Canvas canvas)
...
canvas.drawXXX();
//方式二:自建画布, 有的时候需要一块空白的画布进行加水印等操作,就需要自己创建画布
Bitmap bitmap = Bitmap.createBitmap(200, 100, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
canvas.drawColor(Color.YELLOW);
Bitmap格式
如何存储像素点:
- 一张位图所占用的内存:图片长度(px) x 图片宽度(px)x 一个像素点所占的字节数
- 在Android中,存储一个像素点所占用的字节数是使用枚举类型Bitmap.Config中的各个参数来表示的参数如下:
- ALPHA_8:表示8位Alpha位图,即A=8,不存储其他颜色,一个像素点占用1字节,只有透明度没有颜色
- ARGB_4444:表示16位ARGB图,A、R、G、B各占用4位,一个像素点占4+4+4+4=16位,2字节
- ARGB_8888:表示32位ARGB图,A、R、G、B各占用8位,一个像素点占8+8+8+8=32位,4字节
- RGB_565:表示16位RGB位图,即R占5位,G占6位,B占5位,没有透明度,一个像素点占5+6+5 = 16位,2字节
- 每个色值所占的位数越大,颜色越艳丽:
- 取值数越多,可以表示的颜色就越多,颜色也就越艳丽
注意
- 一般使用ARGB_8888的格式来存储Bitmap
- 由于ARGB_4444格式的画质太糟糕,在API13中遗弃
- 假如对图片的透明度没有要求,可以改成RGB_565的格式,相比于占用内存最大的ARGB_8888可以节省一半的内存开销
计算Bitmap所占内存的大小:
- 内存中存储的Bitmap对象与文件中存储 的Bitmap图片不是一个概念,文件中存储的Bitmap图像是经过图片压缩算法压缩过的,而内存中存储的Bitmap对象是通过BitmapFactory加载或者Bitmap.createBitmap()创建的,保存 于内存中,具有明确的宽和高,所以内存中的bitmap大小的计算:Bitmap.getWidth() * Bitmap.getHeight() * 每个像素所占的内存大小
- OOM的原因:我使用的手机是2340x1080的分辨率,所以创建一个整个屏幕的Bitmap画布,假设以ARGB_8888格式保存,大致需要2340* 1080* 32B = 80870400B = 77MB,如果循环创建这么大的画布,很容易造成OOM的发生
相关像素点之间可否进行压缩:
- 如果想要将Bitmap存储到硬盘上,一定存在压缩问题,在Android中压缩格式使用枚举类Bitmap.CompressFormat中的成员变量表示
- Bitmap.CompressFormat.JPEG
- Bitmap.CompressFormat.PNG
- Bitmap.CompressFormat.WEBP
创建Bitmap
BitmapFactory
- BitmapFactory用于从各种资源,文件,数据流和字节数组中创建Bitmap对象,BitmapFactory是一个工具类,提供了大量的函数,可以用于从不同的数据源中解析、创建Bitmap对象
public static Bitmap decodeResource(Resource res, int id);
public static Bitmap decodeResource(Resource res, int id, Options opts)
public static Bitmap decodeFile(String pathName);
public static Bitmap decodeFile(String pathName, Options opts);
public static Bitmap decodeByteArray(byte[] data, int offset, int length);
public static Bitmap decodeByteArray(byte[] data, int offset, int length, Options opts);
public static Bitmap decodeFileDescriptor(FileDescriptor fd);
public static Bitmap decodeFileDescriptor(FileDescriptor fd, Rect outPadding, Options opts);
public static Bitmap decodeStream(InputStream is);
public static Bitmap decodeStream(InputStream is, Rect outPadding, Options opts);
public static Bitmap decodeResourceStream(Resources res, TypeValue value, InputStream is, Rect padding, Options opts);
- BitmapFactory可以从资源,文件,字节数组、FileDescriptor和InputStream数据流解析出对应的Bitmap对象,如果解析不出来,则返回null,而且每个函数都有两个实现,区别可以很明显的看出
decodeResource(Resources res, int id)
//从资源中解码一张位图,主要以R.drawable.xxx的形式从本地资源中加载
//res:包含图像数据的资源对象,一般通过Context.getResource()函数获得
id:包含图像数据的资源id
public static Bitmap decodeResource(Resource res, int id);
eg:
Bitmap bitmap = Bitmap.decodeRespurce(getResource(), R.drawable.xxx);
decodeFile(String pathName)
//主要通过文件路径来加载图片
//pathName:解码文件的全路径名,必须是路径全名
public static Bitmap decodeFile(String pathName);
eg:
String filename = "/data/dataa/demo.jpg"
Bitmap bitmap = BitmapFactory.decodeFile(filename);
decodeByteArray(byte[] data, int offset, int length)
//根据byte数组 解析出来Bitmap
//data:压缩图像数据的字节数组
//offset:图像数据偏移量,用于解码器定位从哪里开始解析
//length:字节数,从偏移量开始,指定取多少字节进行解析
- 使用步骤:
- 开启线程去获取网络图片
- 网络返回InputStream
- 把InputStream转换成byte[]
- 解析:Bitmap bm = BitmapFactory.decodeByteArray(byte,0 , byte.length)
eg:
new Thread(new Runnable()
@Override
public void run()
try
byte[] data = getImage(path);
int length = data.length;
final Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, length);
....
catch(Exception e)
e.printStackTrace();
).start()
注意:
- 请求网络必须在子线程中
- 在子线程中不能对UI进行更新,可以使用View.post()函数来更新UI
public static byte[] readStream(InputStream in) throws Exception
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = -1;
while((len = in,read(buffer)) !=-1)
outputStream.write(buffer, 0, len)
outputStream.close();
in.close;
//因为data字节数组是把输入流转换为字节内存输出流的字节数组格式,如果不进行outputStream进行转换,则返回结果会一直为null
return outputStreamm.toByteArray();
public static byte[] getImage(String path) throws Exception
URL url = new URL(path);
HttpURLConnection httpURLconnection = (HttpURLConnection)url.openConnection();
httpURLconnection.setRequestMethod("GET");
httpURLconnection.setReadTimeout(1000);
InputStream in = null;
if(httURLconnection.getResponseCode() == 200)
in = httpURLconnection.getInputStream();
byte[] result = readStream(in);
in.close();
return result;
return null;
decodeFileDescriptor(FileDescriptor fd)
//fd:包含解码位图数据的文件路径
//outPadding:用于返回矩形的内边距,如果bitmap没有解析成功,则返回(-1, -1, -1, -1),如果不需要,可以传入null, 这个参数一般不使用
public static Bitmap decodeFileDescriptor(FileDescriptor fd);
public static Bitmap decodeFileDescriptor(FileDescriptor fd, Rect outPadding, Options opts);
eg:
String path = "/data/data/demo.jpg";
FileInputStream is = new FileInputStream(path);
bitmap = BitmapFactory.decodeFileDescriptor(is.getFD());
if(bitmap==null)
....
- 使用decodeFileDescriptor()比使用decodeFile()更加节省内存
- 原因:
- 首先看一些decodeFileDescriptor()的源码:
- 可以看出时调用Native里面的函数,被封装在SO里,直接从native中返回bitmap
public static Bitmap decodeFileDescriptor(FIleDescriptor fd, Rect outPadding, Options opts)
Bitmap bitmap = nativeDecodeFileDescriptor(fd, outPadding, opts);
if(bitmap == nnull && opts != null && opts.inBitmap != null)
throw new IllegalArgmentException("...");
return finishDecode(bitmap, outPadding,opts);
- 而decodeFile()函数的源码如下:
public static Bitmap decodeFile(String pathName, Options opts)
validate(opts);
Bitmap bm = null;
InputStream stream = null;
try
stream = new FileInputStream(pathName);
bm = decodeStream(stream, null, opts);
catch (Exception e)
/* do nothing.
If the exception happened on open, bm will be null.
*/
Log.e("BitmapFactory", "Unable to decode stream: " + e);
finally
if (stream != null)
try
stream.close();
catch (IOException e)
// do nothing here
return bm;
@Nullable
public static Bitmap decodeStream(@Nullable InputStream is, @Nullable Rect outPadding,
@Nullable Options opts)
if(!is.markSupported())
is = new BufferedInputSttream(is, 16 * 1024);
is.mark(1024);
Bitmap bmp;
byte[] tempStorage = null;
if(opts != null)
tempStorage = opts.inTempStorage;
if(tempStorage == null)
tempStorage = new byte[16 * 1024];
bmp = nativeDecodeStream(is, tempStorage, outPadding, opts);
return finishDecode(bmp, outPadding, opts);
- 可以从decodeStream的源码中看出在调用nativeDecodeDtream()之前,会申请两次内存, 就会增加OOM的风险:
is = new BufferedInnputStream(is, 16 * 1024);
tempStorage = new byte[16 * 1024];
decodeStream()
//is:用于解码位图的原始数据输入流
//outPadding:与decodeFileDescriptor中的 outPadding参数含义相同,用于返回矩形的内边距,如果没有解析成功,则返回(-1, -1, -1,-1),这个参数一般不使用,可以传入null
//一般用来从网络上获取图片
public static Bitmap decodeStream(InputStream is);
public static Bitmap decodeStream(InputStream is, Rect outPadding, Options opts);
eg:
new Thread(new Runnable()
@Override
public void run()
try
InputStream inputStream = getImage(path);
final Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
....
catch(Exception e)
e.printStackTrace();
).start()
//通过getImmage()函数返回一个InputStream对象
public static byte[] getImage(String path) throws Exception
URL url = new URL(path);
HttpURLConnection httpURLconnection = (HttpURLConnection)url.openConnection();
httpURLconnection.setRequestMethod("GET");
httpURLconnection.setReadTimeout(1000);
if(httURLconnection.getResponseCode() == 200)
return httpURLconnection.getInputStream();
return null;
以上是关于Android Bitmap 与 Drawable之间的区别和转换的主要内容,如果未能解决你的问题,请参考以下文章
Android中 Bitmap和Drawable相互转换的方法
如何在 android 中将 Bitmap 转换为 Drawable?