Bitmapのカドを丸くする

「アイコン画像を角丸にしてくれ」 とか、割とよくある話だと思うんです

	public static Bitmap clip_radius(Bitmap src,int out_w,int out_h,float radius_x,float radius_y){
		// 入力と出力の矩形
		Rect rect_in = new Rect(0,0,src.getWidth(),src.getHeight());
		RectF rect_out = new RectF(0,0,out_w,out_h);
		// 出力ビットマップとその描画オブジェクトを作成する
		Bitmap dst = Bitmap.createBitmap(out_w,out_h,Bitmap.Config.ARGB_8888);
		Canvas c = new Canvas(dst);
		Paint paint = new Paint();
		paint.setAntiAlias(true);
		paint.setFilterBitmap(true);
		// ゼロフィルして
		c.drawARGB(0,0,0,0);
		// 角丸矩形を書いて
		paint.setColor(0xffffffff);
		c.drawRoundRect (rect_out,radius_x,radius_y,paint);
		// 転送モードを工夫してから
		paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
		// ビットマップをコピー スケーリングあり
		c.drawBitmap(src,rect_in,rect_out,paint);
		//
		return dst;
	}

注意点

Bitmapはネイティブヒープというリソースを消費していて、これが解放されるのはrecycleが呼ばれるか、finalizeが呼ばれるかした時です。ただしjavaではファイナライズが呼び出されることは保証されていません。

purgeable bitmap の場合はOS側が適当なタイミングでネイティブヒープ側のリソースを管理してくれます。BitmapFactory.decode* で作った場合かビットマップか、レイアウトXMLで指定したdrawable resourceから自動的にbitmap drawableが生成された場合はビットマップをpurgeable bitmap にすることができます。参照と解放がそれほど頻繁でない場合は、OSによるpurgeに頼っても特に問題はありません。

Bitmap#createBitmap や Bitmap#copy で作ったビットマップはpurgeable にはできないので、自動ではネイティブヒープの解放は行われません。参照されなくなったビットマップは必ずUI階層からの参照を切って明示的にrecycle()する必要があります。地味に管理と検証が面倒くさいです。