Android で OpenCL を使って画像変換する

[Android で OpenCL を試す](https://qiita.com/ohwada/items/66c5dacb56bab80c3d52)
の続きです

### 概要

インテルが Android で OpenCL を使うチュートリアルとサンプルコードを公開してます。
今回は、これを試す。

[Tutorial: Getting Started with OpenCL™ on Android* OS(https://software.intel.com/en-us/android/articles/opencl-basic-sample-for-android-os)

前提
Android端末に OpenCL ランタイムが必要です。

使い方
アプリを起動すると、組み込みの画像が表示される。

画面をタッチすると、
タッチした座標を中心とした円が表示され、
どんどん大きくなるアニメーションを行う。
円の内側にある画像を白黒に変換する。
すべての画像が白黒になると、アニメーションは終了する。

### アプリを作成する

まず、下記を読んでください。

[Android で OpenCL を試す](https://qiita.com/ohwada/items/66c5dacb56bab80c3d52)

(1) プロジェクトを作成する

(2) OpenCLのライブラリを用意する

(3) app/src/main/cpp　フォルダーに　C++ のプログラムファイルを配置する

(4) app/src/main/Assets フォルダーにOPenCLのカーネルプログラムファイルを配置する

(5) app/src/main/cpp/res/drawableフォルダーに画像を配置する

(6) レイアウトファイルに ImageView を配置する

```activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

    <ImageView
        android:id="@+id/outputImageView"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:src="@drawable/picture" />
```

(7) MainActivity に JNIインターフェイスを記載する

```MainActivity.java
public class MainActivity extends Activity

    private native void nativeStepOpenCL (
//　詳細　略
```


(8) C++ のプログラムにJNIインターフェイスを記載する

```step.cpp
extern "C" void Java_com_intel_sample_androidbasicocl_MainActivity_nativeStepOpenCL
(
//　詳細　略
```

(9) app/src/main/cpp フォルダーに CMakeLists.txt を作成する

```CMakeLists.txt
add_library( # Sets the name of the library.
             step

             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
             step.cpp )
```

(10)  app/build.gradle を変更する

```build.gradle
    externalNativeBuild {
        cmake {
            path 'src/main/cpp/CMakeLists.txt'
        }
    }
```

### アプリの動作

Java から OPenCLのカーネルプログラムへ画像を渡す

JNI の引数に Java の Bitmap を使う


MainActivity
```
    public void onWindowFocusChanged(boolean hasFocus)
    {
//　アプリが起動すると
BackgroundThread　を開始する
            startBackgroundThread();

    private void startBackgroundThread ()
    {
BackgroundThread　を開始すると、step()　を繰り返し実行する
        backgroundThread = new Thread(new Runnable() {
            public void run() {
                while(!isShuttingDown)
                {
                        step();

    private void step ()
    {
//ネィテブコードを実行する
        nativeStepOpenCL(
        //　詳細　略
        );

//ネィテブコードへのインターフェイス
    private native void nativeStepOpenCL (
        //　詳細　略
```

画面にタッチすると、画像を変換する

MainActivity
```
    public boolean onTouchEvent(MotionEvent event)
    {
//　画面にタッチすると、座標を取得する
        xTouchUI = (int)(event.getX());
        yTouchUI = (int)(event.getY());
```


step.cpp
```
nativeStepOpenCL
(
    JNIEnv* env,
    jobject thisObject,
    jint stepCount,
    jint xTouch,
    jint yTouch,
    jint radius,
    jboolean updateInputBitmap,
    jobject inputBitmap,
    jobj
)
{

// Bitmap から画素を取得する
        void* inputPixels = 0;
        AndroidBitmap_lockPixels(env, inputBitmap, &inputPixels);

// Buffer　を作成する
            clCreateBuffer
            (
                openCLObjects.context,
                CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
                bufferSize,   // Buffer size in bytes.
                inputPixels,  // Bytes for initialization.
                &err
            );
```

[NDK eference : Bitmap](https://developer.android.com/ndk/reference/group/bitmap)

[OpenCL clCreateBuffer](https://www.khronos.org/registry/OpenCL/sdk/1.0/docs/man/xhtml/clCreateBuffer.html)

### アプリを実行する

analyze apk により下記の２つが同封されていることが確認できる。
- libstep.so
- libOpenCL.so
![opencl4_analyze_apk.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64075/eccfdd63-0b46-752a-01f8-f596c32bcbad.png)


スクリーンショット

画面にタッチし、画像変換する例
![opencl4_touch.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64075/848b449a-d1a9-5850-8875-85ba08908a75.png)

サンプルコードをgithub に公開した。
https://github.com/ohwada/Android_Samples/tree/master/OpenCL4