ApplicationPronama-chanWeb Service

Blender を使った Web サービス「プロ生ちゃんTシャツジェネレーター」を作ったよ

暮井 慧

暮井 慧: こんにちは! 私、暮井 慧。今回は、3DCG アニメーション作成の統合環境アプリ Blender のコマンドラインレンダリングを使って、Web サービスを作ってみたよ!。これは、Blender Advent Calendar 2016 12日目と、プロ生ちゃん Advent Calendar 2016 12日目の投稿だよ。

Web サービス構想

私の 3D モデルデータは、Blender 製で、Tシャツモデルはテクスチャ画像を編集して、簡単にTシャツをデザインできるようになってるんだよね。

Tシャツ

Tシャツ

というわけで、ユーザーがアップロードした画像をテクスチャ画像に合成して、Blender のレンダリング結果を返す Web サービスを作ってみるよ。

Blender のインストール

Blenderのインストール(Linux) < インストール | Blender入門(2.7版) を参考に Linux サーバーにインストール!

私の環境だと yum install blender でインストールできなかったので、公式バイナリを展開してインストール、必要なライブラリを yum コマンドでインストールしたよ。

コマンドラインでレンダリング

Blender の GUI を起動せずにレンダリングする方法は、Doc:JA/2.6/Manual/Render/Command Line - BlenderWiki をチェック!

静止画のレンダリングは、次のようになるよ。

blender -b pronama-chan.blend -o //out# -F PNG -x 1 -f 1

  • -b: GUI を起動せず実行
  • -o: 出力パスとファイル名 // は blend ファイルからの相対位置指定。# の部分にフレーム数が入る。
  • -F: 画像形式指定
  • -x 1: 出力ファイル名に拡張子を付ける
  • -f 1: 1フレーム目をレンダリング

Web サービス化!

Blender のインストールと、コマンドラインでの実行方法はわかったから、後はユーザーがアップロードした画像をテクスチャ画像に合成して、Blender を実行、出力ファイルを結果として返すって感じのコードを書いて Web サービスに仕上げよう!

PHP 部分。

blendtest.php
<?php
$result = "";
if (isset($_FILES['file']['error']) && is_int($_FILES['file']['error'])) {
	$file = $_FILES['file']['tmp_name'];

	$dir = sys_get_temp_dir();
	$id = uniqid();

	exec("cp -R /home/pronamajp/blendfiles/ $dir/$id"); // Blender データファイル一式を一時フォルダーへコピー
	createTshirtTex($file, "$dir/$id/Tsyatu.png"); // アップロードされた画像をTシャツテクスチャ画像へ合成

	exec("/usr/local/blender/blender -b $dir/$id/pronama-chan.blend -o //out# -F PNG -x 1 -f 1"); // レンダリング実行
	exec("mv $dir/$id/out1.png /home/pronamajp/DocumentRoot/blendertest/out/$id.png"); // 出力画像を移動
	exec("rm -rf $dir/$id"); // 一時フォルダーを削除

	$result = "http://pronama.jp/blendertest/out/$id.png"; // 出力画像の URL
}

// Tシャツテクスチャ画像への合成
function createTshirtTex($filename, $out_filename)
{
	// Tシャツのテクスチャ画像
	$tex_filename = "/home/pronamajp/DocumentRoot/blendertest/Tsyatu.png";
	// Tシャツのデザイン位置・サイズ
	$offset_x = 164;
	$offset_y = 516;
	$width = 220;
	$height = 320;

	// アップロード画像をリサイズ
	$resized_im = resizeImage($filename, $width, $height);
	$w = imagesx($resized_im);
	$h = imagesy($resized_im);

	// テクスチャ画像にアップロード画像を描画して指定先に保存
	$tex_im = imagecreatefrompng($tex_filename);
	imagecopy($tex_im, $resized_im, $offset_x + floor(($width - $w) / 2), $offset_y + floor(($height - $h) / 2), 0, 0, $w, $h);
	imagepng($tex_im, $out_filename);

	imagedestroy($tex_im);
	imagedestroy($resized_im);
}

// 指定サイズに画像をリサイズ
function resizeImage($filename, $max_width, $max_height)
{
    list($orig_width, $orig_height) = getimagesize($filename);

    $width = $orig_width;
    $height = $orig_height;

    if ($height > $max_height) {
	    // taller
        $width = ($max_height / $height) * $width;
        $height = $max_height;
	}
    if ($width > $max_width) {
    	// wider
        $height = ($max_width / $width) * $height;
        $width = $max_width;
    }

    $image_p = imagecreatetruecolor($width, $height);
	imagealphablending($image_p, false);
	imagesavealpha($image_p, true);

	$image = imagecreatefromstring(file_get_contents($filename));

    imagecopyresampled($image_p, $image, 0, 0, 0, 0, $width, $height, $orig_width, $orig_height);

	imagedestroy($image);

    return $image_p;
}
?>

パスはフェイクで、実際に動いているコードは、不正リクエストチェックも入っているよ。ファイルアップロードの例外処理はこれぐらいしないと気が済まない - Qiita を参考にしたよ。

HTML 部分。

blendtest.php
<h1>プロ生ちゃんTシャツジェネレーター</h1>
<form action="./" method="POST" enctype="multipart/form-data">
  <input type="file" name="file">
  <input type="submit" value="画像ファイルをアップロードする">
</form>
<?php
if ($result) {
	echo '<img src="' . $result .'" />';
}
?>

完成!

サイトのデザインを整えたら、プロ生ちゃんTシャツジェネレーター の完成だよ! いろいろな画像で試してみてね。

プロ生ちゃんTシャツジェネレーター
プロ生ちゃんTシャツジェネレーター

Blender ファイルダウンロード

3D モデルのファイルも公開するよ。使うときは、利用ガイドライン を守ってね。

アキバで見かけた萌えキャラコンテスト(12/17 〆切)

AKIBA PC Hotline! の 「アキバで見かけた萌えキャラコンテスト」読者投票 にエントリーされているから、投票して応援してね。

アキバで見かけた萌えキャラコンテスト