ICP Rust CDK学習メモ
  • ICP Rust CDK学習メモ
  • ⚙️開発環境準備
  • 開発
    • テンプレート生成 (dfx new)
    • Frontend開発
      • 1. シンプルなHTML
      • 2. Canister呼び出し
    • Backend開発
      • 1. Hello
      • 2. データ更新/参照
      • 3. ic_cdk::caller()
      • 4. ic_cdk::call()
      • 5. 動的画像生成
      • 6. staticファイル参照
      • 7. HTTPS outcalls
      • 8. Threshold ECDSA
    • Bootcamp
      • Calculator ➕✖️➖➗
      • Homework diary 📔
      • Student wall 🎨
      • MotoCoin 🪙
      • The Verifier 👨‍🏫
      • The Dapp 🚀
  • サンプル
    • 📔Diary
  • 技術情報
    • 🪪Principal
    • 🪪Internet Identity
    • 🪙Token
    • 🖼️NFT
    • 🗝️VetKey
  • ツール
    • dfx
      • dfx identity
    • quill
  • 参考情報
    • 🔗リンク集
GitBook提供
このページ内
  • 1. テンプレート生成
  • 2. プロジェクト資材修正
  • (1) dfx.jsonの編集
  • (2) didファイルの編集
  • (3) Backendプログラムの編集
  • (4) Rust依存モジュールの追加
  • (5) Backend呼び出し用のJavaScriptソース生成
  • (6) index.htmlの編集
  • (7) index.jsの編集
  • (8) dfxサービス起動
  • (9) Backend、Frontendのローカル配備
  • 実行例
  • 参考

役に立ちましたか?

GitHubで編集
  1. 開発
  2. Backend開発

5. 動的画像生成

Internet ComputerのBackend Canisterで動的に画像生成してみます。

ここで解説するサンプルは、Frontendから渡した画像サイズをもとにBackendで動的に画像データを生成して返すだけのシンプルなものです。

生成画像はBackend側のデータを利用しないため、厳密にはBackendを呼び出さずともFrontend内で生成可能なのですが、あえてBackendで動的生成させています。

Backendで動的に画像生成する仕組みを応用することで、Blockchainに刻まれたデータに基づいて動的に画像データを生成するといったこともできるでしょう。

1. テンプレート生成

生成した画像を表示するためのFrontendも用意しますので、手っ取り早くテンプレート生成を使うことにします。

$ dfx new --type=rust fractal
$ cd fractal

コマンドが成功すると、以下のようなディレクトリ構造でファイルが生成されていると思います。

fractal
├── Cargo.lock
├── Cargo.toml
├── README.md
├── dfx.json
├── node_modules
├── package-lock.json
├── package.json
├── src
│   ├── fractal_backend
│   │   ├── Cargo.toml
│   │   ├── fractal_backend.did
│   │   └── src
│   │       └── lib.rs
│   └── fractal_frontend
│       ├── assets
│       │   ├── favicon.ico
│       │   ├── logo2.svg
│       │   ├── main.css
│       │   └── sample-asset.txt
│       └── src
│           ├── index.html
│           └── index.js
└── webpack.config.js

2. プロジェクト資材修正

(1) dfx.jsonの編集

テンプレート生成されたものがそのまま使えるのでとくに修正は必要ありません。

(2) didファイルの編集

Backendを呼び出すためのI/Fを定義します。

引数として画像サイズ (x, y) を渡して、pngデータ (バイナリ)を返すことを考えます。サンプルですのでつくりを単純化するため、Backend側からエラーは返さないものとします。

service : {
    "fractal": (nat32, nat32) -> (blob) query;
}

(3) Backendプログラムの編集

I/Fに合わせてプログラムを用意します。

今回はBackendで動的に画像を生成する方法の検証が目的ですので、生成する画像にはこだわりません。

使用するimage createのページを見ると『Julia fractals』のコード例がありましたので、今回はこれを使ってみることにしましょう。

描画ロジックの詳細については聞かないでください。

// An example of generating julia fractals.
// https://crates.io/crates/image
use std::io::Cursor;

#[ic_cdk::query]
fn fractal(imgx:u32, imgy:u32) -> Vec<u8> {
  ︙
  let mut result = vec![];
  imgbuf.write_to(&mut Cursor::new(&mut result), image::ImageOutputFormat::Png).unwrap();
  result
}

(4) Rust依存モジュールの追加

Julia fractalsでは計算に複素平面を使用するため、num-complex crateを使います。また、Rust上で画像を扱いpngフォーマットへの変換するために、image crateを追加します。

$ cargo add num-complex
$ cargo add --features png --no-default-features image

プロジェクトルートにあるCargo.tomlはWorkspaceの設定にすぎませんので、

[workspace]
members = [
    "src/fractal_backend",
]

実体があるsrc/fractal_backend/Cargo.tomlに依存ライブラリが追加されます。

︙
image = { version = "0.24.7", default-features = false, features = ["png"] }
num-complex = "0.4.4"

(5) Backend呼び出し用のJavaScriptソース生成

FrontendからBackendを呼び出せるようにJavaScriptソースを生成します。

$ npm run generate

※コマンドの実体はdfx generate fractal_backendです。

(6) index.htmlの編集

あくまでもサンプルですので、画像サイズ (x, y) を入力する<input>タグ、画像生成する<button>タグ、生成した画像を表示させる<img>タグ のみのシンプルなものとし、素のHTMLとJavaScriptで記述することにします。

<!DOCTYPE html>
<html>
  <head>
    <title>fractal</title>
  </head>
  <body>
    Size:
    <input id="x" type="number" min="100" max="1000" step="1" value="512">
    <input id="y" type="number" min="100" max="1000" step="1" value="512">
    <button id="button">Generate</button>
    <br/><br/>
    <img id="fractal">
  </body>
</html>

(7) index.jsの編集

buttonがクリックされた場合に、Backendのfractal()関数を呼び出し、取得できたpngデータを<img>タグに表示する例です。

<img>タグにpngデータを直接流し込むことはできないため、convertToDataUrl()関数を用意してDataUrl形式に変換し、src属性に設定する方法で実現しています。

import { fractal_backend } from "../../declarations/fractal_backend";

document.getElementById("button").addEventListener("click", async (e) => {
  e.preventDefault();
  const x = parseInt(document.getElementById("x").value);
  const y = parseInt(document.getElementById("y").value);

  const png = await fractal_backend.fractal(x, y);
  const blob = new Blob([png], { type: "image/png" });
  const url = await convertToDataUrl(blob);

  button.removeAttribute("disabled");
  document.getElementById("fractal").src = url;

  return false;
});
// Converts the given blob into a data url such that it can be assigned as a
// target of a link of as an image source.
function convertToDataUrl(blob) {
  return new Promise((resolve, _) => {
    const fileReader = new FileReader();
    fileReader.readAsDataURL(blob);
    fileReader.onloadend = function () {
      resolve(fileReader.result);
    }
  });
}

(8) dfxサービス起動

$ dfx start --background --clean

(9) Backend、Frontendのローカル配備

$ dfx deploy

実行例

参考

前へ4. ic_cdk::call()次へ6. staticファイル参照

最終更新 1 年前

役に立ちましたか?

-

convertToDataUrl()関数はDfinityのを流用しています。

src/fractal_backend/fractal_backend.did
https://crates.io/crates/image
src/fractal_backend/src/lib.rs
Cargo.toml
src/fractal_backend/Cargo.toml
公式サンプル
QR code generator on the Internet Computer