生成AIお絵描きマジックアプリ

このチュートリアルでは、手書きのイラストをGoogle Gemini APIで加工・改良し、美しく仕上げた画像を表示するアプリを作ります。

Google Gemini APIの呼び出しにはGoogle Apps Script(GAS)を使います。GASのスクリプトはGoogle Gemini 2.5 Proで書いています。バイブコーディングです。

Google AI Studio で作るGemini APIは課金方法を登録しなくても以下の範囲ならば無料で使えます。

  • 1 分あたりのリクエスト数: 5
  • 1 日あたりのリクエスト数: 250,000
  • 1 分あたりのトークン数(入力): 100

Google Apps Scriptの設定

API呼び出し処理を行うサーバー側のプログラムをGoogle Apps Scriptに設定します。

Gemini 2.5 Pro を使って Google Apps Script を書く

無料のアカウントでもこちらからGemini 2.5 Proが使えます。

プロンプト

App inventorのキャンバスに描いた絵を解析して改良した絵を出力させたい。改良した絵はbase64エンコードした文字列で受け取ってオリジナルの下のキャンバスに表示したい。
Google Apps Script からGoogle ai studio のAPIを呼び出して使う。キャンバスに描いた絵はエクステンションでbase64エンコードしてJSONでアップロードするのでGASでbase64が正しいか確認し、必要であれば修正する。結果はJSONで戻す。APIキーはスクリプトプロパティから読む。
App inventor部分は自分でやるから、それ以外の部分を教えて。

返答

Google Apps Scriptだけではなく、Gemini APIの設定からウェブアプリとしてのデプロイ方法、使い方まで詳しく教えてくれます。

App InventorとGoogle AIのGeminiモデルを連携させるためのGoogle Apps Script(GAS)ですね。承知いたしました。

App Inventorから送られてくる手描きの絵(Base64文字列)をGemini APIで解析・改良し、新しい画像を生成してApp Inventorに返すためのGASコードを作成します。

このスクリプトは、以下の処理を行います。

POSTリクエストの受付: App Inventorから送信されたJSONデータ(画像データとプロンプトを含む)を受け取ります。

Base64データの整形: 受け取ったBase64文字列から不要なヘッダー(data:image/png;base64,など)を削除します。

Gemini APIの呼び出し:

スクリプトプロパティに保存されたAPIキーを安全に読み込みます。

入力された画像とプロンプトをgemini-2.0-flash-preview-image-generationモデルに送信し、画像の改良を依頼します。このモデルは、入力画像を解釈し、指示に基づいて新しい画像を生成できます。

結果の返却: 生成された新しい画像のBase64文字列をJSON形式でApp Inventorに返します。

以下のドキュメントに、GASのコードと設定方法の詳細を記載します。

画像改良GAS for App Inventor

/**
 * App InventorからのPOSTリクエストを処理するメイン関数
 * @param {Object} e - App Inventorから送信されるイベントオブジェクト
 * @returns {ContentService.TextOutput} - 処理結果(新しい画像のBase64文字列 or エラーメッセージ)をJSON形式で返す
 */
function doPost(e) {
  // レスポンスの基本構造
  let response = {
    status: 'error',
    message: 'An unknown error occurred.',
    imageData: null
  };

  try {
    // POSTされたJSONデータをパース
    if (!e || !e.postData || !e.postData.contents) {
      throw new Error('Invalid request: No data received.');
    }
    const jsonData = JSON.parse(e.postData.contents);
    const base64Data = jsonData.imageData;
    const prompt = jsonData.prompt || 'この手描きの絵を、より洗練された高品質なデジタルアートにしてください。';

    // 入力データの検証
    if (!base64Data || typeof base64Data !== 'string') {
      throw new Error('Invalid request: imageData is missing or not a string.');
    }

    // Base64データからヘッダーを削除
    const cleanedBase64 = cleanBase64String(base64Data);

    // スクリプトプロパティからAPIキーを取得
    const apiKey = PropertiesService.getScriptProperties().getProperty('GEMINI_API_KEY');
    if (!apiKey) {
      throw new Error('Configuration error: API key is not set in Script Properties.');
    }

    // Gemini APIを呼び出して新しい画像を生成
    const generatedBase64 = callGeminiApi(apiKey, cleanedBase64, prompt);

    // 成功レスポンスを作成
    response = {
      status: 'success',
      message: 'Image generated successfully.',
      imageData: generatedBase64
    };

  } catch (error) {
    // エラーレスポンスを作成
    console.error(error.toString());
    response.message = error.message;
  }

  // 結果をJSON形式で返す
  return ContentService.createTextOutput(JSON.stringify(response))
    .setMimeType(ContentService.MimeType.JSON);
}

/**
 * Base64文字列からヘッダー部分(例: "data:image/png;base64,")を削除する
 * @param {string} base64String - 元のBase64文字列
 * @returns {string} - ヘッダーが削除されたBase64文字列
 */
function cleanBase64String(base64String) {
  // "data:[<mime-type>];base64," という形式のヘッダーを正規表現で探して削除
  return base64String.replace(/^data:image\/[a-z]+;base64,/, '');
}

/**
 * Gemini API (Image Generation) を呼び出して画像を生成する
 * @param {string} apiKey - Google AI StudioのAPIキー
 * @param {string} base64Image - 解析・改良の元となる画像のBase64文字列
 * @param {string} prompt - 画像をどのように改良するかを指定する指示文
 * @returns {string} - 生成された新しい画像のBase64文字列
 */
function callGeminiApi(apiKey, base64Image, prompt) {
  // Geminiの画像生成モデルのエンドポイント
  const model = 'gemini-2.0-flash-preview-image-generation';
  const url = `https://generativelanguage.googleapis.com/v1beta/models/${model}:generateContent?key=${apiKey}`;

  // APIに送信するペイロード(リクエストボディ)
  const payload = {
    contents: [{
      parts: [
        // 1. 指示テキスト
        { text: prompt },
        // 2. 入力画像
        {
          inlineData: {
            mimeType: 'image/png', // App InventorのCanvasはPNG形式
            data: base64Image
          }
        }
      ]
    }],
    generationConfig: {
      // レスポンスとして画像とテキストの両方を要求する
      responseModalities: ['IMAGE', 'TEXT'] 
    },
  };

  // APIリクエストのオプション
  const options = {
    method: 'post',
    contentType: 'application/json',
    payload: JSON.stringify(payload),
    muteHttpExceptions: true // HTTPエラー時に例外をスローさせず、レスポンスを直接受け取る
  };

  // APIにリクエストを送信
  const response = UrlFetchApp.fetch(url, options);
  const responseCode = response.getResponseCode();
  const responseBody = response.getContentText();

  // レスポンスを解析
  if (responseCode === 200) {
    const jsonResponse = JSON.parse(responseBody);
    
    // レスポンスの中から画像データ部分を探す
    const imagePart = jsonResponse?.candidates?.[0]?.content?.parts?.find(p => p.inlineData);
    
    if (imagePart && imagePart.inlineData.data) {
      // 画像のBase64データを返す
      return imagePart.inlineData.data;
    } else {
      // 画像が見つからない場合のエラー
      console.error('API response did not contain image data. Response: ' + responseBody);
      // テキスト部分があれば、それをエラーメッセージとして利用
      const textPart = jsonResponse?.candidates?.[0]?.content?.parts?.find(p => p.text);
      const errorMessage = textPart ? textPart.text : 'No image data in response.';
      throw new Error(`API Error: ${errorMessage}`);
    }
  } else {
    // APIがエラーを返した場合
    console.error('API Error. Code: ' + responseCode + '. Body: ' + responseBody);
    throw new Error(`API request failed with status code ${responseCode}. Details: ${responseBody}`);
  }
}

設定と使用方法
Google Apps Scriptプロジェクトの作成:

Googleドライブで「新規」>「その他」>「Google Apps Script」を選択して、新しいプロジェクトを作成します。

上記のコードをコピーして、コード.gsファイルに貼り付けます。

APIキーの設定:

GASエディタの左側のメニューから「プロジェクトの設定」(歯車アイコン)をクリックします。

「スクリプト プロパティ」のセクションで、「スクリプト プロパティを追加」をクリックします。

プロパティに GEMINI_API_KEY と入力します。

値に、ご自身のGoogle AI StudioのAPIキーを貼り付けます。

「スクリプト プロパティを保存」をクリックします。

デプロイ:

エディタ右上の「デプロイ」ボタンをクリックし、「新しいデプロイ」を選択します。

種類の選択で「ウェブアプリ」を選択します。

「アクセスできるユーザー」を**「全員」**に設定します。(App Inventorから呼び出すために必要です)

「デプロイ」ボタンをクリックします。初回は承認を求められるので、許可してください。

表示されるウェブアプリのURLをコピーします。このURLをApp Inventorから呼び出すことになります。

App Inventor側の実装(ヒント)
App Inventor側では、以下の手順でこのGASと連携します。

Webコンポーネントを配置します。

描画完了のボタンなどが押されたら、CanvasのSaveAsブロックを使って描画内容をファイルに保存し、そのファイルパスを取得します。

エクステンション(例: TaifunFileエクステンションなど)を使って、保存したファイルをBase64形式にエンコードします。

WebコンポーネントのPostTextブロックを使います。

url: 上記でコピーしたGASのウェブアプリURLを設定します。

text: joinブロックやBuildJsonブロック(Dictionaryを使うと便利)を使い、以下のようなJSON文字列を作成して渡します。

JSON

{"imageData": "(ここにBase64文字列)", "prompt": "プロのイラストレーター風にしてください"}
WebコンポーネントのGotTextイベントで、GASからの応答を受け取ります。

responseContentをJSONとしてパース(JsonTextDecodeブロック)します。

statusがsuccessであることを確認します。

imageDataキーの値(改良された画像のBase64文字列)を取得します。

取得したBase64文字列を、結果表示用の下のキャンバスのBackgroundImageプロパティなどに設定します。(data:image/png;base64,を先頭に付ける必要があるかもしれません)

これで、App Inventorで描いた絵をAIで改良して表示する仕組みが完成します。ご不明な点があれば、お気軽にご質問ください。

プロンプト

Gemini APIのAPIキーの取り方を生成AIお絵描きコーチアプリチュートリアルから転記します。

残りのコンテンツを表示するにはログインする必要がありますどうぞ . 会員ではないですか ? 入会のご案内