swfimagedump

Sazesaki さんの記事(id:sasezaki:20090913)を真似して
swfimagedump を書いてみました。

Jpeg に加えて Lossless 画像が png ファイルに落ちます。

<?php

if ($argc < 2) {
    fprintf(STDERR, "Usage: swfimagedump <swf_file>\n");
    exit(1);
}

$swf_filename = $argv[1];
$swfdata = file_get_contents($swf_filename);

$obj = new SWFEditor();
if ($obj->input($swfdata) == false) {
    fprintf(STDERR, "input failed\n");
    exit(1);
}

$tags = $obj->getTagList();
foreach ($tags as $k => $tag) {
    $tagName = $tag['tagName'];
    if (strncmp($tagName, 'DefineBitsJPEG', 14) == 0) {
        $detail = $obj->getTagDetail($k);
        $imageId = $detail["image_id"];
        file_put_contents($imageId.'.jpg', $obj->getJpegData($imageId));
    } elseif (strncmp($tagName, 'DefineBitsLossless', 18) == 0) {
        $detail = $obj->getTagDetail($k);
        $imageId = $detail["image_id"];
        file_put_contents($imageId.'.png', $obj->getPNGData($imageId));
    }
}

Iterator に慣れてない古い人間なので、とりあえず foreach してます。
実は、自分で作っておきながら getTagList の戻り値が foreach 出来るの知りませんでしたw

Sazesaki さん有難う御座います。\(^O^)/

備考

あと、SWF ファイルから画像を抜き出すときの注意なのですけど、

実は少なくとも DefineBitsLossless2 についてαチャネルに半透明(0 より
大きく 255 より小さな値)のデータを含む場合、厳密には原理的に元画像を
復元するすべがありません。

仕様書(swf spec ver10 の p154)によると、

BitmapPixelData ARGB[image data size] Array of pixel colors.

Number of entries is BitmapWidth * BitmapHeight. The RGB data
must already be multiplied by the alpha channel value.

なんだそうです。割った数をかけても元に戻りません。
詳しくは以前書いた日記で ↓