#!/usr/bin/perl

use strict;

use SWF::File;
use SWF::Element;
use Image::Magick;
use Compress::Zlib;
use Getopt::Std;

my %opt;
getopts('ft', \%opt);

my ($imagefile, $swffile) = @ARGV;

unless (defined $imagefile) {
    print STDERR <<USAGE;
img2swf.plx - convert an image to a swf.
  perl img2swf.plx [-f] [-t] imagefile [swffile]
   -f: Force to convert to full color bitmap.
   -t: Keep transparency.
USAGE

    exit(1);
}

($swffile = $imagefile) =~s/\.[^.]+$/.swf/ unless defined $swffile;

my $image = Image::Magick->new;
$image->Read($imagefile);

my $height = $image->Get('height');
my $width = $image->Get('width');
die "Can't open $imagefile." if ($height == 0 and $width == 0);

my ($lossless, $tp);
if ($opt{t} and $image->Get('matte')) {
    $lossless = SWF::Element::Tag::DefineBitsLossless2->new;
    $tp=1;
} else {
    $lossless = SWF::Element::Tag::DefineBitsLossless->new;
    $tp=0;
}
$lossless->configure
    ( CharacterID => 1,
      BitmapWidth => $width,
      BitmapHeight => $height,
    );

if ((my $colors = $image->Get('colors'))>=256 or $opt{f}) {

    $lossless->BitmapFormat(5); # fullcolor

    my $d = deflateInit() or die "Can't open zlib stream."; 

    for(my $y = 0; $y<$height; $y++) {
	for(my $x = 0; $x<$width; $x++) {
	    my @rgba = split /,/, $image->Get("pixel[$x,$y]");
	    if (!$tp) {
		pop @rgba;
		unshift @rgba, 0;
	    } else {
		$rgba[3] = 255-$rgba[3];
		@rgba=@rgba[3,0..2];
	    }

	    my ($output, $status) = $d->deflate(pack('CCCC',@rgba)); # 4 bytes per pixel.
	    die "Compress error." unless $status == Z_OK;
	    $lossless->ZlibBitmapData->add($output);
	}
    }

    my ($output, $status) = $d->flush();
    die "Compress error." unless $status == Z_OK;
    $lossless->ZlibBitmapData->add($output);

} else {

    $lossless->BitmapFormat(3); # bitmap with colormap
    $lossless->BitmapColorTableSize($colors-1);

    my (%colors, $pixels);
    my $index = 0;
    my $pad = "\x00" x (4 - $width % 4);
    my $d = deflateInit() or die "Can't open zlib stream."; 

    for(my $y = 0; $y<$height; $y++) {
	for(my $x = 0; $x<$width; $x++) {
	    my $rgba;
	    unless (exists $colors{$rgba = $image->Get("pixel[$x,$y]")}) {
		$colors{$rgba} = pack('C',$index++);
	    }
	    $pixels .= $colors{$rgba};
	}
	$pixels .= $pad;
    }
    %colors = reverse %colors;
    $tp = $tp ? 'CCCC':'CCC';
    for my $k (sort keys %colors) {
	my @rgba = split /,/, $colors{$k};
	$rgba[3] = 255-$rgba[3];
	my ($output, $status) = $d->deflate(pack($tp, @rgba));
	die "Compress error." unless $status == Z_OK;
	$lossless->ZlibBitmapData->add($output);
    }
    my ($output, $status) = $d->deflate($pixels);
    die "Compress error." unless $status == Z_OK;
    $lossless->ZlibBitmapData->add($output);
    ($output, $status) = $d->flush();
    die "Compress error." unless $status == Z_OK;
    $lossless->ZlibBitmapData->add($output);
}

# create SWF.

my $swf = SWF::File->new($swffile);
$swf->FrameRate(15);
$swf->FrameSize(0,0,$width*20,$height*20);   # It can't set the same size???

SWF::Element::Tag::SetBackgroundColor->new(
     BackgroundColor => [
      Red => 128,
      Green => 255,
      Blue => 255,
     ],
)->pack($swf);

# lossless tag is packed here.

$lossless->pack($swf);

# define the same size rectangle filled with the bitmap.

SWF::Element::Tag::DefineShape2->new(
     ShapeID => 2,
     ShapeBounds => [
      Xmin => 0,
      Ymin => 0,
      Xmax => $width,
      Ymax => $height
     ],
     Shapes => [
      FillStyles => [
       FillStyleType => 0x40,
       BitmapID => 1,
      ],
      ShapeRecords => [
       [MoveDeltaX => 0, MoveDeltaY => 0, FillStyle0 => 1],
       [DeltaX => $width],
       [DeltaY => $height],
       [DeltaX => -$width],
       [DeltaY => -$height]
      ],
     ],
)->pack($swf);

SWF::Element::Tag::PlaceObject2->new(
     CharacterID => 2,
     Depth => 1,
     Matrix => [
      TranslateX => 0,
      TranslateY => 0,
      ScaleX => 20,
      ScaleY => 20,
     ],
)->pack($swf);

my $sf = SWF::Element::Tag::ShowFrame->new;
$sf->pack($swf);

SWF::Element::Tag::DoAction->new(
     Actions => [[Tag => 'ActionStop']],
)->pack($swf);

$sf->pack($swf);

SWF::Element::Tag::End->new->pack($swf);

$swf->close;