png などの画像上に drawText() で文字を書こうとして、
以下のような処理を記述すると、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);
}
}