2024年7月23日火曜日

MLEのJavaScriptでコードを記述したプロセスを作成しデータベースでJPEG画像のリサイズを行なう

Oracle Database 23aiではMLEとしてGraalVMが組み込まれ、サーバー側でJavaScriptのコードを実行できるようになっています。Oracle Database 23ai上で実行されているOracle APEXでは、今までPL/SQLを記述できたほとんどの箇所で、PL/SQLの代わりにJavaScriptを記述できるようになりました。

本記事では、MLE JavaScriptを使った例として、JPEG画像のリサイズを行なうアプリケーションを作成します。JPEG画像のデコード、エンコードおよびリサイズはMLEのJavaScriptで実行します。

作成したアプリケーションは以下のように動作します。


以下より作成手順を紹介します。

最初にJPEG画像を操作するMLEモジュールを作成します。

SQLワークショップのオブジェクト・ブラウザを開きます。


MLEモジュール - JavaScriptをクリックし、MLEモジュールの作成を始めます。

最初にnpmのjpeg-jsを元にしたMLEモジュールを作成します。

名前はESM_JPEG_JS_0_4_4、バージョンは0.4.4、ソース・タイプにURLを選択し、URLとして以下を指定します。

https://cdn.jsdelivr.net/npm/jpeg-js@0.4.4/+esm

MLEモジュールの作成をクリックします。


MLEモジュールESM_JPEG_JS_0_4_4が作成されます。


MLEモジュールの作成を続けます。

最初にnpmのbufferを元にしたMLEモジュールを作成します。

名前はESM_BUFFER_6_0_3、バージョンは6.0.3、ソース・タイプにURLを選択し、URLとして以下を指定します。

https://cdn.jsdelivr.net/npm/buffer@6.0.3/+esm


モジュールbufferが参照しているモジュールbase64-jsとieee754を、それぞれMLEモジュールとして作成します。

base64-jsのMLEモジュールを作成します。

名前はESM_BASE64_JS_1_5_1、バージョンは1.5.1、ソース・タイプにURLを選択し、URLとして以下を指定します。

https://cdn.jsdelivr.net/npm/base64-js@1.5.1/+esm


ieee754のMLEモジュールを作成します。

名前はESM_IEEE754_1_2_1、バージョンは1.2.1、ソース・タイプにURLを選択し、URLとして以下を指定します。

https://cdn.jsdelivr.net/npm/ieee754@1.2.1/+esm


画像のリサイズを行なうMLEモジュールを作成します。

名前はRESIZE、ソース・タイプにURLを選択し、URLとして以下を指定します。

https://cdn.jsdelivr.net/npm/@jimp/plugin-resize@0.22.12/es/modules/resize.js


以上で必要なMLEモジュールが作成できました。


作成したMLEモジュールをインポートとして含むMLE環境を作成します。


作成するMLE環境の名前はIMAGE_ENVとします。

MLE環境の作成をクリックします。


MLE環境IMAGE_ENVが作成されます。インポートの追加をクリックします。


モジュール所有者にAPEXワークスペース・スキーマを選択します。

モジュール名としてESM_JPEG_JS_0_4_4を選択します。インポート名は/npm/jpeg-js@0.4.4/+esmとします。

作成をクリックします。


同様に、以下のモジュール名とインポート名の組みを作成します。インポート名は、jsDelivr.comによって自動生成されたESモジュールに含まれるimport文の参照と一致する必要があります。モジュールresizeは自動生成されたコードではないため、インポート名はそのままresizeとしています。

モジュール名:ESM_BUFFER_6_0_3、インポート名:/npm/buffer@6.0.3/+esm
モジュール名:ESM_BASE64_JS_1_5_1、インポート名:/npm/base64-js@1.5.1/+esm
モジュール名:ESM_IEEE754_1_2_1、インポート名:/npm/ieee754@1.2.1/+esm
モジュール名:RESIZE、インポート名:resize

MLE環境IMAGE_ENVに5つのMLEモジュールがインポートとして登録されていれば、MLE環境の準備は完了です。


APEXのアプリケーションを作成します。

リサイズ前のオリジナルの画像とリサイズ後の画像を保存する表として、EBMJ_IMAGESを作成します。以下のDDLを実行します。
create table ebmj_images (
    id                 number generated by default on null as identity
                       constraint ebmj_images_id_pk primary key,
    title              varchar2(80 char) not null,
    image              blob,
    image_mimetype     varchar2(80 char),
    image2             blob,
    image2_mimetype    varchar2(80 char)
);

アプリケーション作成ウィザードを起動し、空のアプリケーションを作成します。名前はImage Resizeとします。


元画像を登録するためのページを作成します。

表EBMJ_IMAGESをソースとしたフォーム付き対話モード・レポートのページを作成します。


ページ・タイプとして対話モード・レポートを選択します。

対話モード・レポートのページ番号は2、名前はImagesとします。フォーム・ページを含めるにチェックを入れます。

フォーム・ページ番号は3、フォーム・ページ名はImage、フォーム・ページ・モードはドロワーを選択します。

データ・ソースの表/ビューの名前としてEBMJ_IMAGESを選択します。

次へ進みます。


主キー列1としてID (Number)を選択します。

ページの作成を実行します。


対話モード・レポートとフォームのページが作成されます。

ページ・デザイナで対話モード・レポートのページを開き、画像を保存しているBLOB列の属性を調整します。

列IMAGEを選択し、BLOB属性のMIMEタイプ列としてIMAGE_MIMETYPEを設定します。


同様に列IMAGE2を選択し、BLOB属性のMIMEタイプ列としてIMAGE2_MIMETYPEを設定します。


ページ・デザイナでフォームのページを開きます。

ページ・アイテムP3_IMAGEを選択し、ストレージのMIMEタイプ列としてIMAGE_MIMETYPEを設定します。


列IMAGE_MIMETYPE、IMAGE2、IMAGE2_MIMETYPEに対応するページ・アイテムP3_IMAGE_MIMETYPE、P3_IMAGE2、P3_IMAGE2_MIMETYPEはサーバー側で設定し、画面からは設定しません。

これらのページ・アイテムを選択し、コメント・アウトします。


以上で元画像を登録するページは完成です。


アプリケーションを実行し、リサイズの元画像となるJPEG画像を登録します。

Imagesのページを開き、作成をクリックします。


ドロワーが開きます。Titleを入力し、ImageにJPEG画像を選択します。

作成をクリックします。


作成したJPEG画像が一覧されます。同様の手順を繰り返し、JPEG画像をいくつか登録します。


ページ・デザイナでホーム・ページを開きます。画像のリサイズを行なうUIを実装します。

リサイズの元画像を選択するページ・アイテムを作成します。

識別の名前はP1_ID、タイプは選択リスト、ラベルはImageとします。設定の選択時のページ・アクションとして値のリダイレクトと設定を選択します。

LOVのタイプはSQL問合せ、SQL問合せとして以下を記述します。

select title d, id r from ebmj_images

追加値の表はオフ、NULL値の表示はオン、NULL表示値として- Select Image -を記述します。

セッション・ステートのストレージはセッションごと(永続)を選択します。


縮小する比率を指定するページ・アイテムを作成します。例えば10を指定すると、画像の横と縦がそれぞれ1/10となり、面積としては1/100になります。

識別の名前はP1_SCALE、タイプは数値フィールド、ラベルはScaleとします。外観のテンプレートとしてRequired - Floartingを選択します。検証の必須の値をオン、デフォルトのタイプを静的とし、静的値に10を設定します。セッション・ステートのストレージとしてセッションごと(永続)を選択します。


リサイズを実行するボタンを作成します。

識別のボタン名はRESIZE、ラベルはResizeとします。外観のホットはオン、テンプレート・オプションのWidthにStretchを選択します。

動作のアクションはデフォルトのページの送信です。


リサイズ前の画像を表示するページ・アイテムを作成します。

識別の名前はP1_IMAGE、タイプはイメージの表示、ラベルはOriginalとします。設定の基準としてSQL文で戻されたBLOB列を選択し、SQL文として以下を記述します。

select image from ebmj_images where id = :P1_ID

セッション・ステートのストレージはリクエストごと(メモリーのみ)とします。


リサイズ後の画像を表示するページ・アイテムを作成します。

識別の名前はP1_IMAGE2、タイプはイメージの表示、ラベルはResizedとします。設定の基準としてSQL文で戻されたBLOB列を選択し、SQL文として以下を記述します。

select image2 from ebmj_images where id = :P1_ID

元の画像の右隣に配置するため、レイアウトの新規行の開始はオフにします。

セッション・ステートのストレージはリクエストごと(メモリーのみ)とします。


JPEG画像のリサイズを行なうプロセスを作成します。

識別の名前はResize JPEG、タイプはコードの実行です。

ソースの言語にJavaScript (MLE)を選択し、JavaScriptコードとして以下を記述します。

サーバー側の条件のボタン押下時にRESIZEを指定します。


最後に、アプリケーション定義のセキュリティを開き、データベース・セッションのMLE環境としてIMAGE_ENVを設定します。

変更の適用をクリックすると、アプリケーションは完成です。


アプリケーションを実行すると、記事の先頭にあるGIF動画のように動作します。

GIF動画ではScaleの10を指定し、横と縦の幅がそれぞれ1/10となるように設定していますが、それほど小さくなっていないように見えます。これは、元の画像がブラウザの画面サイズに合わせて縮小されて表示されているためです。

今回作成したAPEXアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/mle-image-resize.zip

Oracle APEXのアプリケーション作成の参考になれば幸いです。

完