以下のような処理を記述すると、4行目の drawText() で、タイトルの例外メッセージが発生します。
Resources r = getResources(); Bitmap bitmap = BitmapFactory.decodeResource(r, R.drawable.icon); Canvas canvas = new Canvas(bitmap); canvas.drawText(...);
bitmap が immutable (変えられない) ことが原因です。
mutable か immutable かは、bitmap.isMutable() で true か false かで確認できます。
じゃあ、どうやって mutable にするかというと、
bitmap.copy(Bitmap.Config config, boolean isMutable) を使って、
mutable な Bitmap を新規に作成します。
(青字部分が修正内容)
Resources r = getResources(); Bitmap bitmap = BitmapFactory.decodeResource(r, R.drawable.icon); Bitmap copy = bitmap.copy(Bitmap.Config.ARGB_8888, true); Canvas canvas = new Canvas(copy); canvas.drawText(...);
こうすると、うまく処理できます。
ちなみに、、
bitmap.copy(Bitmap.Config config, boolean isMutable) の第1引数ですが、
ALPHA_8、ARGB_4444、ARGB_8888、RGB_565 のいずれかを選択できます。
ARGB_4444 や RGB_565 を使えば、画像のバイト数を節約できそうです。
画質優先の場合には、ARGB_8888 を使う、というところでしょうか。
ALPHA_8 は、よく分かりません。。
項目 | 1 ピクセルあたりのバイト数 | コピー内容(多分。確証はありません。) |
ALPHA_8 | 1 バイト | アルファ値のみ 8 ビット。 |
ARGB_4444 | 2 バイト | ARGB それぞれ 4 ビットずつ。 |
ARGB_8888 | 4 バイト | ARGB それぞれ 8 ビットずつ。 |
RGB_565 | 2 バイト | RGB が 5/6/5 ビット。 |
以下は、比較用に作成したサンプルです。
上から、以下の画像を表示させています。
- オリジナル画像
- ALPHA_8 (表示されていませんが。。)
- ARGB_4444
- ARGB_8888
- RGB_565
以下は、ソースです。
main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <ImageView android:id="@+id/imageview1" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <ImageView android:id="@+id/imageview2" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <ImageView android:id="@+id/imageview3" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <ImageView android:id="@+id/imageview4" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <ImageView android:id="@+id/imageview5" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout>
BitmapCopyActivity.java
package jp.sample.rtaki; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.os.Bundle; import android.widget.ImageView; public class BitmapCopyActivity extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Paint paint = new Paint(); paint.setColor(Color.BLUE); //paint.setAlpha(200); paint.setTextSize(12); ImageView v1= (ImageView) findViewById(R.id.imageview1); Bitmap image = BitmapFactory.decodeResource(getResources(), R.drawable.flag); v1.setImageBitmap(image); ImageView v2 = (ImageView) findViewById(R.id.imageview2); Bitmap copy1 = image.copy(Bitmap.Config.ALPHA_8, true); Canvas c2 = new Canvas(copy1); c2.drawText("ALPHA_8 - " + copy1.getRowBytes()/copy1.getWidth()*1.0, 25, 33, paint); v2.setImageBitmap(copy1); ImageView v3 = (ImageView) findViewById(R.id.imageview3); Bitmap copy2 = image.copy(Bitmap.Config.ARGB_4444, true); Canvas c3 = new Canvas(copy2); c3.drawText("ARGB_4444 - " + copy2.getRowBytes()/copy2.getWidth()*1.0, 25, 33, paint); v3.setImageBitmap(copy2); ImageView v4 = (ImageView) findViewById(R.id.imageview4); Bitmap copy3 = image.copy(Bitmap.Config.ARGB_8888, true); Canvas c4 = new Canvas(copy3); c4.drawText("ARGB_8888 - " + copy3.getRowBytes()/copy3.getWidth()*1.0, 25, 33, paint); v4.setImageBitmap(copy3); ImageView v5 = (ImageView) findViewById(R.id.imageview5); Bitmap copy4 = image.copy(Bitmap.Config.RGB_565, true); Canvas c5 = new Canvas(copy4); c5.drawText("RGB_565 - " + copy4.getRowBytes()/copy4.getWidth()*1.0, 25, 33, paint); v5.setImageBitmap(copy4); } }