android畫圖之Bitmap

一、相關概念

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) //設置下劃線




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章