android画图之Bitmap

本文介绍了Android中Bitmap的操作,包括从资源、SD卡和网络加载Bitmap,如何旋转Bitmap以及如何处理内存问题。通过BitmapFactory、Matrix和Canvas进行图片处理,并讨论了Bitmap的内存管理和回收,防止OutOfMemoryError。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、相关概念

1、Drawable就是一个可画的对象,其可能是一张位图(BitmapDrawable),也可能是一个图形(ShapeDrawable),还有可能是一个图层(LayerDrawable),我们根据画图的需求,创建相应的可画对象
2、Canvas画布,绘图的目的区域,用于绘图
3、Bitmap位图,用于图的处理
4、Matrix矩阵
5、paint画笔


获取Bitmap的方法:

一、 使用BitmapFactory解析图片


// --> 使用BitmapFactory解析图片

public void myUseBitmapFactory(Canvas canvas){

// 定义画笔

Paint paint = new Paint();

// 获取资源流

Resources rec = getResources();

InputStream in = rec.openRawResource(R.drawable.haha);

// 设置图片

Bitmap bitmap =BitmapFactory.decodeStream(in);

// 绘制图片

canvas.drawBitmap(bitmap, 0,20, paint);

}

二、 使用BitmapDrawable解析图片


// --> 使用BitmapDrawable解析图片

public void myUseBitmapDrawable(Canvas canvas){

// 定义画笔

Paint paint = new Paint();

// 获得资源

Resources rec = getResources();

// BitmapDrawable

BitmapDrawable bitmapDrawable = (BitmapDrawable) rec.getDrawable(R.drawable.haha);

// 得到Bitmap

Bitmap bitmap = bitmapDrawable.getBitmap();

// 在画板上绘制图片

canvas.drawBitmap(bitmap, 20,120,paint);

}


三、 使用InputStream和BitmapDrawable绘制

// --> 使用InputStream和BitmapDrawable解析图片

public void myUseInputStreamandBitmapDrawable(Canvas canvas){

// 定义画笔

Paint paint = new Paint();

// 获得资源

Resources rec = getResources();

// InputStream得到资源流

InputStream in = rec.openRawResource(R.drawable.haha);

// BitmapDrawable 解析数据流

BitmapDrawable bitmapDrawable = new BitmapDrawable(in);

// 得到图片

Bitmap bitmap = bitmapDrawable.getBitmap();

// 绘制图片

canvas.drawBitmap(bitmap, 100, 100,paint);

}

-----------------------------------------
bitMap = BitmapFactory.decodeResource(this.getResources(),

R.drawable.image);


SD卡中的图片

Bitmap bmp = BitmapFactory.decodeFile("/sdcard/testBitmap/testImg.png")

把bitmap保存在SD卡中

File fImage = new File("/sdcard/testBitmap/testImg.png");  
fImage.createNewFile();
FileOutputStream iStream = new FileOutputStream(fImage);
bmp.compress(CompressFormat.PNG, 100, iStream);
iStream.close();
fImage.close();
iStream =null;
fImage =null;
//写到输出流里,就保存到文件了。


使用网络中的图片

//图片的链接地址  
String imgURLStr = "http://tx.bdimg.com/sys/portrait/item/990e6271796a7a6c170c.jpg";  
URL imgURL = new URL(imgURLStr);  
URLConnection conn = imgURL.openConnection();  
conn.connect();  
InputStream is = conn.getInputStream();  
BufferedInputStream bis = new BufferedInputStream(is);

//下载图片
Bitmap bmp = BitmapFactory.decodeStream(bis);

//关闭Stream
bis.close();  
is.close();
imgURL =null;


显示图片
1)转换为BitmapDrawable对象显示位图
// 转换为BitmapDrawable对象
BitmapDrawable bmpDraw=new BitmapDrawable(bmp);
// 显示位图
ImageView iv2 = (ImageView)findViewById(R.id.ImageView02);
iv2.setImageDrawable(bmpDraw);
2)使用Canvas类显示位图
canvas.drawBitmap(bmp, 0, 0, null);

缩放位图
1)将一个位图按照需求重画一遍,画后的位图就是我们需要的了,与位图的显示几乎一样:drawBitmap(Bitmap bitmap, Rect src, Rect

dst, Paint paint)。

2)在原有位图的基础上,缩放原位图,创建一个新的位图:CreateBitmap(Bitmap source, int x, int y, int width, int height,

Matrix m, boolean filter)

3)借助Canvas的scale(float sx, float sy) ,不过要注意此时整个画布都缩放了。

4)借助Matrix:

Matrix matrix=new Matrix();
matrix.postScale(0.2f, 0.2f);
Bitmap dstbmp=Bitmap.createBitmap(bmp,0,0,bmp.getWidth(),bmp.getHeight(),matrix,true);
canvas.drawBitmap(dstbmp, 10, 10, null); 


旋转位图
借助Matrix或者Canvas来实现。

Matrix matrix=new Matrix();
matrix.postRotate(45);
Bitmap dstbmp=Bitmap.createBitmap(bmp,0,0,bmp.getWidth(), bmp.getHeight(),matrix,true);
canvas.drawBitmap(dstbmp, 10, 10, null);

//释放bitmap资源,如在分页加载bitmap时候,如果加载下一页要先清理缓存中的上一页内容 就会用
 if (!dstbmp.isRecycled()) {          

 dstbmp.recycle();   

 }  

如:

for(int i = 0; i < list.size(); i++){   
        Bitmap bitmap = loadImageFromUrl(list.get(i));   
        ImageView imageView = new ImageView(this);   
        imageView.setImageBitmap(bitmap);   
        mImages[i] = imageView;   
    }  

这里对于Bitmap就没有很好回收和利用,就有可能出现out of memory问题,因为是循环,所以Bitmap就可以放到外部,让程序重复利用,而不需要每次都创建一个新的Bitmap对象,

而且如果在内部作好资源回收利用的话,那就不用担心内存溢出了。

Bitmap bitmap = null   
    for(int i = 0; i < list.size(); i++){   
        bitmap = loadImageFromUrl(list.get(i));   
        ImageView imageView = new ImageView(this);   
        imageView.setImageBitmap(bitmap);   
        mImages[i] = imageView;   
           
        if(!bitmap.isRecycled() && bitmap != null){   
            bitmap.recycle();   
            bitmap = null;   
        }   
    }  

bitmap与byte转换

Bitmap-->byte[]:

public static byte[] Bitmap2Bytes(Bitmap bm) {
	ByteArrayOutputStream baos = new ByteArrayOutputStream();
	bm.compress(Bitmap.CompressFormat.PNG, 100, baos);
	
        return baos.toByteArray();
}

byte[]-->Bitmap:

public static Bitmap Bytes2Bimap(byte[] b) {
	if (b.length == 0) {
		return null;
	}
		
	return BitmapFactory.decodeByteArray(b, 0, b.length);
}

Drawable转为bitmap

public static Bitmap drawableToBitmap(Drawable drawable) {
	try {
		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;
	} catch (OutOfMemoryError e) {
		e.printStackTrace();
		return null;
	}
}
Drawable d=xxx; //xxx根据自己的情况获取drawable
BitmapDrawable bd = (BitmapDrawable) d;
Bitmap bm = bd.getBitmap();

bitmap 转为 Drawable

因为BtimapDrawable是Drawable的子类,最终直接使用bd对象即可

  Bitmap bm=xxx; //xxx根据你的情况获取
  BitmapDrawable bd=BitmapDrawable(bm);

带倒影的图片

	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;
	}

获得圆角的图片:

	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;
	}

Paint类常用方法:

void setARGB(int a, int r, int g, int b) 设置Paint对象颜色,参数一为alpha透明通道

void setAlpha(int a) 设置alpha不透明度,范围为0~255

void setAntiAlias(boolean aa) //是否抗锯齿

void setColor(int color) //设置颜色,这里Android内部定义的有Color类包含了一些常见颜色定义

void setFakeBoldText(boolean fakeBoldText) //设置伪粗体文本

void setLinearText(boolean linearText) //设置线性文本

PathEffect setPathEffect(PathEffect effect) //设置路径效果

Rasterizer setRasterizer(Rasterizer rasterizer) //设置光栅化
            mShader = new LinearGradient(0, 0, 100, 70, new int[] {
                                         Color.RED, Color.GREEN, Color.BLUE },
                                         null, Shader.TileMode.MIRROR);
Shader setShader(Shader shader) //设置阴影

void setTextAlign(Paint.Align align) //设置文本对齐

void setTextScaleX(float scaleX) //设置文本缩放倍数,1.0f为原始

void setTextSize(float textSize) //设置字体大小

Typeface setTypeface(Typeface typeface) //设置字体,Typeface包含了字体的类型,粗细,还有倾斜、颜色等。

void setUnderlineText(boolean underlineText) //设置下划线




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值