PHPで、リクエストに応じて動的に画像を作成する

このエントリーをはてなブックマークに追加
1nobodyさん
PHPで、UAからのリクエストに応じて
動的に画像を作成する方法について話すスレッドです。
例えば
  ?color=red&width=10&height=10
  というクエリを受け取り、
  高さと幅が10で、中が赤で塗りつぶされたPNGファイルを返す
というスクリプトを作ることを最終目的とします。
「夜勤の巣」のグラフと同じようなものが出来たら、上出来です。

今のところ仕入れた資料一覧
http://tech.millto.net/~pngnews/kndh/PngSpec1.2/PNGcontents.html
http://de3.php.net/manual/ja/function.pack.php

そういえばみなさんのお勧めバイナリエディタは何ですか?
私はStirlingを使っているのですが。
http://www.vector.co.jp/soft/win95/util/se079072.html

2 :03/12/11 14:36 ID:???
終了
31:03/12/11 14:44 ID:???
しょうがない。
何かアクションを起こすか。
45:03/12/11 14:49 ID:???
5!!!
5nobodyさん:03/12/11 15:24 ID:???
6!!!
6nobodyさん:03/12/11 15:35 ID:???

echo "<img src='bar-$color.png' height='$height' width='$width' />";
7nobodyさん:03/12/11 15:49 ID:???
# 個人的に、画像フォーマットには興味あるんだけど。

PHPにimage関連の関数があるのになぁ。
http://de3.php.net/manual/ja/ref.image.php
8nobodyさん:03/12/11 15:53 ID:???
どうみても単質スレ。終了
91 ◆ImKIddF2kc :03/12/11 15:56 ID:???
>>6
レスありがとう。
確かにそれは手っ取り早い解決手段です。
実際私も考えたのですが、
その方法だと、UAに依存しますよね。
img内のheight,widthの取り扱いは各ブラウザによって異なります。

古いブラウザではPNGが実装されていないため
PNGを扱うこと自体、UAを選ぶことになっていますが、
UA間のPNGの実装の度合いと、
imgタグのheight/widthの取り扱いの差の度合いを比較すると
やはり動的にバイナリデータを作成して返してやるほうが
ベターだろう、と考えています。
101 ◆ImKIddF2kc :03/12/11 16:18 ID:???
>>7
知らなかった……。調査不足でした。
もう少し調べてみます。
でも、もうバイナリの仕様を勉強し始めたところだし、
一からバイナリファイルを返すスクリプトを
作ってみたいと思います。

>>8
ごめんなさい。
この技術は、単質の部類に入るほど初心者向きで簡単な分野だったってことですね。
11nobodyさん:03/12/11 16:22 ID:???
ま た 本 7 か
12nobodyさん:03/12/11 17:09 ID:???
なんでこう単発質問スレ立てるんだろうね
こういう自分勝手な奴には適当にウソ教えるのも一興か
13nobodyさん:03/12/11 17:48 ID:???
<?php

define("IMAGE_MAX_WIDTH", 1024);
define("IMAGE_MAX_HEIGHT", 640);

$IMAGE_COLOR_TABLE = array(
    "red"   => array(255,   0,   0),
    "blue"  => array(  0, 255,   0),
    "green" => array(  0,   0, 255),
    "white" => array(255, 255, 255),
    "black" => array(  0,   0,   0)
);

function get_colorcode($color) {
    global $IMAGE_COLOR_TABLE;

    if (is_array($IMAGE_COLOR_TABLE[$color])) {
        return $IMAGE_COLOR_TABLE[$color];
    }
    elseif (ereg("^\#?([0-9a-fA-F]{6})$", $color, $matched)) {
        $r = hexdec(substr($matched[1], 0, 2));
        $g = hexdec(substr($matched[1], 2, 2));
        $b = hexdec(substr($matched[1], 4, 2));
        return array($r, $g, $b);
    }
    else {
        return array(255, 255, 255);
    }
}
14nobodyさん:03/12/11 17:48 ID:???

if (is_numeric($_GET['width']) && is_numeric($_GET['height'])) {
    $width  = intVal($_GET['width']);
    $height = intVal($_GET['height']);
    $color  = strToLower($_GET['color']);

    list($code_r, $code_g, $code_b) = get_colorcode($color);

    if (0 < $width  && $width  < IMAGE_MAX_WIDTH and
        0 < $height && $height < IMAGE_MAX_HEIGHT) {

        header("Content-type: image/png");

        $img = @imageCreate($width, $height)
            or die("Cannot initialize new GD image stream");
        imageColorAllOcate($img, $code_r, $code_g, $code_b);
        imagePng($img);
        imageDestroy($img);
    }
    else {
        echo "Error, invalid param";
    }
}
else {
    echo "Error, no param";
}
?>

最終目的達成...これでこのスレ終り?
15nobodyさん:03/12/16 22:27 ID:???
PHPで、リクエストに応じてさくらたん画像を動的に作成する
だったら盛り上がったのにな
16HTTP/1.1 200 OK:03/12/20 21:35 ID:???
color=blue
にしたら緑の画像が表示された。
17nobodyさん:03/12/22 21:46 ID:???
あぁ。恥ずかしい間違いしてる(汗
1の人いるかな?w3cにPNGのSpec新しい?ドキュメントが出てたよ。
画像付きで解説されてて解りやすかった。

gzcompress使ってるので要 zlib
<?php
function png_sig() {
    return pack("C8",137,80,78,71,13,10,26,10);
}
function png_chunk($type, $data) {
    $chunk  = NULL;
    $chunk .= pack("N", sizeof(unpack("C*",$data))); // length
    $chunk .= $type;
    $chunk .= $data;
    $chunk .= pack("N", crc32($type.$data));
    
    return $chunk;
}
$COLOR_TABLE = array(
    "white" => array(255, 255, 255),
    "red"   => array(255,   0,   0),
    "green" => array(0,   255,   0),
    "blue"  => array(0,     0, 255),
    "black" => array(0,     0,   0)
);
18nobodyさん:03/12/22 21:47 ID:???
function get_color_code($color)
{
    global $COLOR_TABLE;

    if (is_array($COLOR_TABLE[$color])) {
        return $COLOR_TABLE[$color];
    }
    elseif (eregi("^#?([0-9a-f]{6})$", $color, $matched)) {
        $r = hexdec(substr($matched[1], 0, 2));
        $g = hexdec(substr($matched[1], 2, 2));
        $b = hexdec(substr($matched[1], 4, 2));
        return array($r, $g, $b);
    }
    else {
        return array(0, 0, 0); // defauld black
    }
}

$width  = intval($_GET['width']);
$height = intval($_GET['height']);
$color  = strtolower($_GET['color']);
list($r,$g,$b) = get_color_code($color);
$data   = NULL;
for ($i=0; $i<$height; ++$i) {
    $data .= pack("C", 0); // filter
    for ($j=0; $j<$width; ++$j) {
        $data .= pack("C3", $r, $g, $b);
    }
}
19nobodyさん:03/12/22 21:55 ID:???

header("Content-type: image/png");
print png_sig();
print png_chunk("IHDR", pack("NNC5",$width,$height,8,2,0,0,0));
print png_chunk("IDAT", gzcompress($data));
print png_chunk("IEND", NULL);

?>

これで最後。動的にPNGのchunkを生成するPHPスクリプトです。
// PNGフォーマットの学習用。


20nobodyさん:03/12/23 00:08 ID:???
こんなスレにマジレスしてるなんて、ほんと恥ずかしいな。
21nobodyさん:03/12/29 03:42 ID:???
方形の単色画像なんだったらhtmlでtableのwidthとheightと背景色指定して代用
221
>>17
あぁ、まさにそういうのです!
ありがとうございます〜〜!!

LZ77圧縮のアルゴリズムの実装にあきらめかけて、
もはやスレを見捨てようとしているところでした。
圧縮をライブラリに任せれば、これほど簡単にできるなんて。

もうちょっと研究続けてみます。
アウトプットは必ず出します。