Androidで画像合成

Androidアプリ作成中に画像合成が必要になったので、画像合成方法についてまとめていきます。
方法としては下記2つの方法があります。

・2つの画像を重ねて表示させる
・2枚の画像を合成して1枚の画像にする

今回は、今後のことを考えて合成に挑戦しています。

「メイン画面」は合成元の2枚の写真を表示して、合成ボタンを押すことで合成した画像がポップアップ表示される単純なサンプルを作成しました。




メイン画面
f:id:nlinks:20151113143059p:plain

ポップアップダイアログ
f:id:nlinks:20151113143045p:plain


① まずはメイン画面を作成します

 1)レイアウトファイル(fragment_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" 
  android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivityFragment">

    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:layout_marginLeft="10dp"
            android:layout_marginRight="10dp"
            android:text="最下層のレイヤー画像"
            android:id="@+id/textView"
            android:layout_alignParentTop="true"
            android:layout_alignParentLeft="true"
            android:layout_alignParentStart="true"
            android:layout_alignParentRight="true"
            android:layout_alignParentEnd="true"
            android:gravity="center_horizontal" />

        <ImageView
            android:layout_width="200dp"
            android:layout_height="139dp"
            android:layout_marginTop="10dp"
            android:layout_marginLeft="10dp"
            android:layout_marginRight="10dp"
            android:id="@+id/imageView"
            android:background="@drawable/base"
            android:layout_gravity="center_horizontal" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:layout_marginLeft="10dp"
            android:layout_marginRight="10dp"
            android:text="写真フレーム画像"
            android:id="@+id/textView2"
            android:layout_alignParentTop="true"
            android:layout_alignParentLeft="true"
            android:layout_alignParentStart="true"
            android:layout_alignParentRight="true"
            android:layout_alignParentEnd="true"
            android:gravity="center_horizontal" />

        <ImageView
            android:layout_width="200dp"
            android:layout_height="139dp"
            android:layout_marginTop="10dp"
            android:layout_marginLeft="10dp"
            android:layout_marginRight="10dp"
            android:id="@+id/imageView2"
            android:background="@drawable/frame"
            android:layout_gravity="center_horizontal" />

        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="合成"
            android:id="@+id/button"
            android:onClick="onClickComposition" />

    </LinearLayout>
</RelativeLayout>

 2)MainActivity.java

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);

        Window varWindow = getWindow();
        varWindow.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
        getSupportActionBar().hide();

        setContentView(R.layout.activity_main);
    }

    // ボタン押下時の処理
    public void onClickComposition(View view)
    {
        PopupDialogFlagment popupDialogFlagment = new PopupDialogFlagment();
        popupDialogFlagment.show(getSupportFragmentManager(), 
                "CompositionBitmapDialog");
    }
}


② 次にポップアップ画面を作成します。ポップアップ画面作成時に2つの画像を合成してImageViewに表示するように処理を書いてあります。

 1) レイアウトファイル(popuplayout.xml)

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    <!-- コンテンツ -->

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_marginTop="6dp"
        android:layout_marginLeft="6dp"
        android:layout_marginRight="6dp"
        android:background="#d8d8d8"
        android:gravity="center_horizontal"
        android:orientation="vertical"
        android:weightSum="1"
        android:id="@+id/linearLayout2">
        <!-- タイトル -->
        <TableLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:stretchColumns="0">

            <TableRow
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="#FFFFFF">


                <ImageView
                    android:layout_width="300dp"
                    android:layout_height="209dp"
                    android:id="@+id/imageView3"
                    android:layout_gravity="center"
                    android:layout_marginTop="30dp"
                    android:layout_marginBottom="30dp" />
            </TableRow>

        </TableLayout>
        <Button
            android:id="@+id/ok_button"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="#FFFFFF"
            android:layout_marginTop="1dp"
            android:text="OK"
            android:textColor="@android:color/black" />
    </LinearLayout>

</RelativeLayout>

 2) PopupDialogFlagment.java

public class PopupDialogFlagment extends DialogFragment
{
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState)
    {
        Dialog dialog = new Dialog(getActivity());
        // タイトル非表示
        dialog.getWindow().requestFeature(Window.FEATURE_NO_TITLE);
        // フルスクリーン
        dialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, 
                  WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
        // layoutの読み込み
        dialog.setContentView(R.layout.popuplayout);
        // 背景を透明にする
        dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));

        // Bitmap合成
        // Bitmapの枠を作成
        Bitmap baseBitmap = Bitmap.createBitmap(400, 278, Bitmap.Config.ARGB_8888);
        // BaseになるBitmapの生成
        Canvas canvas = new Canvas(baseBitmap);

        // 表示画面の取得 & 設定
        Bitmap baseImage = BitmapFactory.decodeResource(getResources(), R.drawable.base);
        baseImage = Bitmap.createScaledBitmap(baseImage, 400, 278, false);
        canvas.drawBitmap(baseImage, 0, 0, null);

        Bitmap frameBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.frame);
        frameBitmap = Bitmap.createScaledBitmap(frameBitmap, 400, 278, false);
        canvas.drawBitmap(frameBitmap, 0, 0, null);

        ((ImageView)dialog.findViewById(R.id.imageView3)).setImageBitmap(baseBitmap);

        // OK ボタンのリスナ
        dialog.findViewById(R.id.ok_button).setOnClickListener(new OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                dismiss();
            }
        });

        // Dialogを返す
        return dialog;
    }
}

画像合成は部分の実装は以下の通りです。
ベースになるビットマップを用意して、画像をどんどん追加していきます。

        Bitmap baseImage = BitmapFactory.decodeResource(getResources(), R.drawable.base);
        baseImage = Bitmap.createScaledBitmap(baseImage, 400, 278, false);
        canvas.drawBitmap(baseImage, 0, 0, null);

        Bitmap frameBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.frame);
        frameBitmap = Bitmap.createScaledBitmap(frameBitmap, 400, 278, false);
        canvas.drawBitmap(frameBitmap, 0, 0, null);

        ((ImageView)dialog.findViewById(R.id.imageView3)).setImageBitmap(baseBitmap);


こんな感じで簡単に画像合成が行えます。皆さんも挑戦してみてください。