/*
*  This program was created by AXELL CORPORATION.
*  Copyright (C) 2017 AXELL CORPORATION, all rights reserved.
*/
#include "gfx_sample.h"

/* VGImageオブジェクト */
static VGImage image;

/* 3x3コンボリューションフィルタ用カーネル */
static VGint kernel3x3[] = {
    -1, -1, -1,
    -1,  8, -1,
    -1, -1, -1
};
/* 3x3コンボリューションフィルタ用スケール・バイアス */
#define SCALE3x3  1
#define BIAS3x3   0
#define CONV3_SCALE (SCALE3x3 / 511.0F)
#define CONV3_BIAS  (BIAS3x3 / 255.0F)
static VGfloat colorTransform3x3[] = {
    CONV3_SCALE, CONV3_SCALE, CONV3_SCALE, 0.0F,
    CONV3_BIAS, CONV3_BIAS, CONV3_BIAS, 1.0F
};

/* 5x5コンボリューションフィルタ用カーネル */
static VGint kernel5x5[] = {
    1,  4,  7,  4, 1,
    4, 16, 26, 16, 4,
    7, 26, 41, 26, 7,
    4, 16, 26, 16, 4,
    1,  4,  7,  4, 1
};
/* 5x5コンボリューションフィルタ用スケール・バイアス */
#define SCALE5x5  (1.0F/273)
#define BIAS5x5   0
#define CONV5_SCALE (SCALE5x5 / 511.0F)
#define CONV5_BIAS  (BIAS5x5 / 255.0F)
static VGfloat colorTransform5x5[] = {
    CONV5_SCALE, CONV5_SCALE, CONV5_SCALE, 0.0F,
    CONV5_BIAS, CONV5_BIAS, CONV5_BIAS, 1.0F
};

static void *image_data;

static void TestInit(int width, int height)
{
    VGfloat ClearColor[4]  = {1.0F, 1.0F, 1.0F, 1.0F};

    /* 画像を読込 */
    image_data = GfxGetFreeArea(FILTER_WIDTH, FILTER_HEIGHT, FILTER_BPP<<3);
    GfxFsRead((int8_t*)FILTER_NAME, FILTER_STRIDE * FILTER_HEIGHT, (void*)image_data);

    /* 描画サーフェスのクリアカラーを指定 */
    vgSetfv(VG_CLEAR_COLOR, 4, ClearColor);

    /* 描画サーフェス全体をクリア */
    vgClear(0, 0, width, height);

    /* VGImageオブジェクトの生成 */
    image = vgCreateImage(VG_sRGBA_8888, FILTER_WIDTH, FILTER_HEIGHT,
                          VG_IMAGE_QUALITY_NONANTIALIASED | VG_IMAGE_QUALITY_FASTER | VG_IMAGE_QUALITY_BETTER);

    /* VGImageオブジェクトにイメージデータを登録 */
    vgImageSubData(image, image_data, FILTER_STRIDE, VG_sRGBA_8888, 0, 0, FILTER_WIDTH, FILTER_HEIGHT);

    /* 現在のマトリクスをIMAGE_USER_TO_SURFACEに設定 */
    vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
}

static void DrawWithConvolution(void)
{
    /* コンボリューションフィルタを無効 */
    vgSetiEXT(VG_EXT_CONVOLUTION_FILTER, VG_FALSE);

    /* 描画 */
    vgLoadIdentity();
    vgTranslate(220, 280);
    vgDrawImage(image);

    /* コンボリューションフィルタを有効 */
    vgSetiEXT(VG_EXT_CONVOLUTION_FILTER, VG_TRUE);

    /* 3x3コンボリューションフィルタの設定 */
    vgSetivEXT(VG_EXT_CONVOLUTION_KERNEL, 9, kernel3x3);

    /* スケールとバイアスの設定はカラートランスフォームのパラメータを使用 */
    vgSetfv(VG_COLOR_TRANSFORM_VALUES, 8, colorTransform3x3);

    /* 描画 */
    vgLoadIdentity();
    vgTranslate(50, 50);
    vgDrawImage(image);

    /* 5x5コンボリューションフィルタの設定 */
    vgSetivEXT(VG_EXT_CONVOLUTION_KERNEL, 25, kernel5x5);

    /* スケールとバイアスの設定はカラートランスフォームのパラメータを使用 */
    vgSetfv(VG_COLOR_TRANSFORM_VALUES, 8, colorTransform5x5);

    /* 描画 */
    vgTranslate(340, 0);
    vgDrawImage(image);

    /* コンボリューションフィルタを無効 */
    vgSetiEXT(VG_EXT_CONVOLUTION_FILTER, VG_FALSE);
}

static void TestTerm(void)
{
    GfxReleaseFreeArea(image_data);

    /* オブジェクトの破棄 */
    vgDestroyImage(image);
}

void ConvolutionMain(void)
{
    /* 初期化処理 */
    TestInit(GFX_WIDTH, GFX_HEIGHT);

    /* コンボリューションフィルタ処理 */
    DrawWithConvolution();

    /* バッファスワップ */
    GfxSwapBuffer();

    /* 終了処理 */
    TestTerm();
}
