Kotlin で簡単な画像処理 Android アプリ作成をしてみよう

Android Studioをインストールして早速簡単な画像処理AndroidアプリをAndroid Studio & Kotlinで作成してみました。その作成手順・ソースコードを解説します。

Android Studioのインストールやアプリ作成の簡単な手順は下の記事で解説していますので、興味のある方やこの記事読んでも理解できない部分があれば読んでみてください。

Android Studio をインストールして電卓アプリをKotlinで作成してみよう Android Studio をインストールして電卓アプリをKotlinで作成してみよう

作成アプリの実行画面は ↓ のような感じになります。

プロジェクト作成

まず新しいプロジェクトを作成します。プロジェクト名は今回は「EasyImageProcessing」としました。Kotlinでプログラミングを行うので「include Kotlin Support」にチェックをつけておきます。」

動作させる端末はスマフォ・タブレットを想定するので、「Phone and Tablet」にチェックをつけ、Androi 9.0 Pie のOSで動作させることを考えてAPI 28を選択しました。

Activityのタイプは「Empty Activity」とし、また、ActivityとLayoutの名前はデフォルトのままでプロジェクトを作成します。

画像の準備

続いて画像処理を行う画像の準備を行います。画像処理を行うファイルをまずコピーします。ここでは画像サイズ640 x 427のJPEGファイルを選択しています(あまり画像が大きいと動かないかも・・・)。

コピーした画像を「res/drawable」にペーストします。

貼り付け先ディレクトリは「res/drawable」のままとします。

名前は好きなものをつけましょう。ここでは「cat.jpg」としています。

これにより「res/drawable」に「cat.jpg」が追加されます。

これで画像の準備は完了です。

スポンサーリンク

画面レイアウト作成

activity_main.xmlのTextタブでXMLファイルを下記のように編集します。

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

    <ImageView
            android:layout_width="310dp"
            android:layout_height="313dp" app:srcCompat="@drawable/cat"
            android:id="@+id/cat" app:layout_constraintTop_toTopOf="parent"
            android:layout_marginTop="32dp" app:layout_constraintBottom_toBottomOf="parent"
            android:layout_marginBottom="128dp" app:layout_constraintStart_toStartOf="parent"
            android:layout_marginStart="32dp"
    />
    <Button
            android:text="右へ回転"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/rotate" android:layout_marginTop="48dp"
            app:layout_constraintTop_toBottomOf="@+id/cat" app:layout_constraintStart_toStartOf="parent"
            android:layout_marginStart="16dp"/>
    <Button
            android:text="モノクロ"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/mono" android:layout_marginTop="48dp"
            app:layout_constraintTop_toBottomOf="@+id/cat" app:layout_constraintEnd_toStartOf="@+id/reset"
            android:layout_marginEnd="44dp" app:layout_constraintStart_toEndOf="@+id/rotate"
            android:layout_marginStart="44dp"/>
    <Button
            android:text="リセット"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/reset" android:layout_marginTop="48dp"
            app:layout_constraintTop_toBottomOf="@+id/cat" app:layout_constraintEnd_toEndOf="parent"
            android:layout_marginEnd="16dp"/>
</android.support.constraint.ConstraintLayout>

Designタブを開くと下記のようなUI画面が生成されていることを確認できると思います。

画像部分の情報は下記に記載されています。

    <ImageView
            android:layout_width="310dp"
            android:layout_height="313dp" app:srcCompat="@drawable/cat"
            android:id="@+id/cat" app:layout_constraintTop_toTopOf="parent"
            android:layout_marginTop="32dp" app:layout_constraintBottom_toBottomOf="parent"
            android:layout_marginBottom="128dp" app:layout_constraintStart_toStartOf="parent"
            android:layout_marginStart="32dp"
    />

画像のソースが「drawable/cat」であり、IDが「cat」となっているところがポイントです。画像の準備で設定した画像名が「cat.jpg」以外の方はここを編集してください。

ソースコード作成

MainActivity.ktを下記のように編集します。

/* ↓ はパッケージ名に合わせて編集 */
package com.daeudaeu.easyimageprocessing

import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.widget.ImageView
import android.widget.Button
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Color


class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val imageFrame : ImageView = findViewById(R.id.cat)
        val rotateButton : Button = findViewById(R.id.rotate)
        val monoButton : Button = findViewById(R.id.mono)
        val resetButton : Button = findViewById(R.id.reset)


        /* bitmap1は元画像 */
        /* cute_catはactivity_main.xmlのImageViewのsrcに書いてあるid */
        var bitmap1 : Bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.cat)

        /* bitmap2は表示中のBitmap */
        /* まずbitmapインスタンスを生成 */
        var bitmap2 : Bitmap = Bitmap.createBitmap(bitmap1)

        rotateButton.setOnClickListener {
            val bitmap3 : Bitmap = Bitmap.createBitmap(bitmap2.height, bitmap2.width, Bitmap.Config.ARGB_8888)
            rotateBitmap(bitmap3, bitmap2)

            imageFrame.setImageBitmap(bitmap3)
            bitmap2 = bitmap3
        }

        monoButton.setOnClickListener {
            var bitmap3 : Bitmap = Bitmap.createBitmap(bitmap2.width, bitmap2.height, Bitmap.Config.ARGB_8888)
            monoBitmap(bitmap3, bitmap2)
            imageFrame.setImageBitmap(bitmap3)
            bitmap2 = bitmap3
        }

        resetButton.setOnClickListener {
            imageFrame.setImageBitmap(bitmap1)
            bitmap2 = bitmap1
        }


    }

    private fun monoBitmap(outBitmap : Bitmap, inBitmap : Bitmap) {
        val width : Int = outBitmap.width
        val height : Int = outBitmap.height

        var color : Int
        var mono : Int

        for(j in 0..height - 1 step 1) {
            for (i in 0..width - 1 step 1) {
                color = inBitmap.getPixel(i, j)
                mono = (Color.red(color) + Color.green(color) + Color.blue(color)) / 3
                outBitmap.setPixel(i, j, Color.rgb(mono, mono, mono))
            }
        }
    }

    private fun rotateBitmap(outBitmap : Bitmap, inBitmap : Bitmap) {
        val width : Int = inBitmap.width
        val height : Int = inBitmap.height

        var color : Int

        for(j in 0..height - 1 step 1) {
            for (i in 0..width - 1 step 1) {
                color = inBitmap.getPixel(i, j)
                outBitmap.setPixel(height - 1 - j, i, color)
            }
        }
    }
}

コメントにも記載しているように1行目はパッケージ名に合わせて変更してください。

ソースコードのポイント説明

・画像オブジェクト生成

下記でcat.jpgをビットマップ化したオブジェクトを生成しています。

var bitmap1 : Bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.cat)

また下記ではbitmap1と同じBitmapオブジェクトを生成しています。

var bitmap2 : Bitmap = Bitmap.createBitmap(bitmap1)

さらに下記では指定したパラメータに応じたビットマップオブジェクトを生成しています。

var bitmap3 : Bitmap = Bitmap.createBitmap(bitmap2.width, bitmap2.height, Bitmap.Config.ARGB_8888)

・画像の回転/モノクロ化

まず画像の回転処理について説明します。下記は「右へ回転」ボタンを押した時の動作を記述したソースコードになります。

        rotateButton.setOnClickListener {
            val bitmap3 : Bitmap = Bitmap.createBitmap(bitmap2.height, bitmap2.width, Bitmap.Config.ARGB_8888)
            rotateBitmap(bitmap3, bitmap2)

            imageFrame.setImageBitmap(bitmap3)
            bitmap2 = bitmap3
        }

まずビットマップオブジェクトbitmap3を生成し、下記で画像を回転するrotateBitmap関数を実行しています。bitmap3が回転後の画像を表すオブジェクトとなります。

rotateBitmap(bitmap3, bitmap2)

さらに、下記でImageViewオブジェクト(imageFrame)のビットマップ情報をbitmap3にセットします。これにより画面に表示される画像が変化します。

imageFrame.setImageBitmap(bitmap3)

このプログラムでは表示中のビットマップオブジェクトをbitmap2としていますので、表示しているビットマップオブジェクトbitmap3をbitmap2にセットして「右へ回転」ボタン押下時の処理を終了します。

bitmap2 = bitmap3

続いて画像のモノクロ化処理について説明します。下記は「モノクロ」ボタンを押した時の動作を記述したソースコードになります。

        monoButton.setOnClickListener {
            var bitmap3 : Bitmap = Bitmap.createBitmap(bitmap2.width, bitmap2.height, Bitmap.Config.ARGB_8888)
            monoBitmap(bitmap3, bitmap2)
            imageFrame.setImageBitmap(bitmap3)
            bitmap2 = bitmap3
        }

異なるのは実行している関数のみです。ここでは画像をモノクロ化するmonoBitmap関数を実行しています。

monoBitmap(bitmap3, bitmap2)

今回はビットマップデータを回転する関数rotateBitmapとモノクロ化する関数monoBitmapを自作していますが、これらはAndroid Developersが提供するAPIを利用することで簡単に実現可能です。それに関しては下記で紹介していますので是非みてみてください。

Kotlin & Android Studioでの Matrix と ColorMatrix の使用方法解説

アプリの動作確認

Runボタンを押してアプリの動作確認を行いましょう。実行する仮想端末には「Pixel API 28 (Android 9, API 28)」を選択します。仮想端末って何?という方はコチラを参考にしてください。

実行すると下記のような画面が表示されるはずです。

「右へ回転」ボタンを押すと画像が右へ90度回転し、「モノクロ」ボタンを押すと画像がモノクロ化されます。また「リセット」ボタンを押すと画像が元の画像に戻ることも確認できます。

 

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です