Androidはワンツーパンチ 三歩進んで二歩下がる

プログラミングやどうでもいい話

Bitmapをバイト配列としてserializeする方法

例えばBitmapのデータをSQLiteのデータベースに保存したい場合、BLOB型としてバイトデータをそのまま保存することが考えられます。

cursorとやり取りするときのフィールド定義は↓こんな感じのバイト型の配列になると思います。

private byte[] icon_bitmap;

オブジェクトをバイト配列に変換するには、ファイルを使わない場合ByteArrayOutputStream を使うと出来ます。

こちらのサイト様を参考にさせていただきました。

JAVAでオブジェクト(Class)をバイト配列に変換する方法 - 異邦人になってみた〜上海の人

 ByteArrayOutputStream byteos = new ByteArrayOutputStream();
 ObjectOutputStream objos = new ObjectOutputStream(byteos);
 objos.writeObject(ここにBitmapオブジェクトを入れる);
  //以下省略

ですが、上記のようにBitmapを変換しようとするとjava.io.NotSerializableExceptionが発生してしまいます。
BitmapクラスがSerializableを実装していないからなのですが、こうした場合Serializableを実装したクラス内でBitmapオブジェクトを保持すれば変換することが出来ます。

こちら↓のページを参考にしました。
serializable - How to fix a java.io.NotSerializableException: android.graphics.Bitmap - Stack Overflow

以上をコードで書きますと次のような感じです。
Bitmapをバイト配列に変換してDB保存→DBから取り出したバイト配列をBitmapに戻す処理を念頭に書いております。

まず、Serializableをimplementsしたクラスを作成します。(追記:こちらのクラスは↑の参考サイトのクラスそのままです。適宜編集して下さい。この記事ではクラス内のwriteObject、readObjectメソッドは使ってません。)
CachedBitmap.java

public class CachedBitmap  implements Serializable {

    private static final long serialVersionUID = -6298516694275121291L;

    public Bitmap getBitmap() {
        return bitmap;
    }

    transient Bitmap bitmap;

    public CachedBitmap(){};

    public CachedBitmap(Bitmap b){
        bitmap = b;
    }

    private void writeObject(ObjectOutputStream oos) throws IOException{
        oos.defaultWriteObject();
        if(bitmap!=null){
            ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
            boolean success = bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteStream);
            if(success){
                oos.writeObject(byteStream.toByteArray());
            }
        }
    }

    private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException{
        ois.defaultReadObject();
        byte[] image = (byte[]) ois.readObject();
        if(image != null && image.length > 0){
            bitmap = BitmapFactory.decodeByteArray(image, 0, image.length);
        }
    }
}

このクラスをバイト配列に変換する時に使います

    /**
     * Bitmapオブジェクトをbyte配列に変換
     * @param bitmap
     * @return
     * @throws IOException
     */
    public static byte[] getByteObject(final Bitmap bitmap) throws IOException
    {
        ByteArrayOutputStream byteos = new ByteArrayOutputStream();
        ObjectOutputStream out = new ObjectOutputStream(byteos);

        CachedBitmap cachedBitmap = new CachedBitmap(bitmap);
        out.writeObject(cachedBitmap);

        return byteos.toByteArray();
    }

このメソッドの戻り値をDBに保存します。

DBから取り出したバイト配列をBitmapオブジェクトに変換するには、やはり先程のCachedBitmapクラスを使います。

    /**
     * byte配列をBitmapオブジェクトに変換
     * @param objByte
     * @return
     * @throws IOException
     * @throws ClassNotFoundException
     */
    public static Bitmap getBitmapObject(final byte[] objByte) throws IOException, ClassNotFoundException
    {
        ByteArrayInputStream byteis = new ByteArrayInputStream(objByte);
        ObjectInputStream in = new ObjectInputStream(byteis);

        CachedBitmap cachedBitmap = (CachedBitmap) in.readObject();

        return cachedBitmap.getBitmap();
    }

以上です。