bmpをpngに変換する

a.bmpをa.pngに変換する。ただし、a.bmpは24bitフルカラービットマップに限定される。作成されるpngもまたトゥルーカラーパレット無しになる。
速度もメモリ効率も度外視。バッドノウハウの集合だけれども。

use strict;
use warnings;
use GD;

open ( IN, 'a.bmp' );
binmode ( IN );

# サイズの取得
my $dummy = undef;
read ( IN, $dummy, 18 ); # 先頭を削除

read ( IN, $dummy, 1 );
my $width = ord($dummy);
read ( IN, $dummy, 1 );
$width += ord($dummy) * 256;

read ( IN, $dummy, 2 ); # 間を削除

read ( IN, $dummy, 1 );
my $height = ord($dummy);
read ( IN, $dummy, 1 );
$height += ord($dummy) * 256;

read ( IN, $dummy, 30 ); # ヘッダーの残りを削除

# 本編

my $im = GD::Image->newTrueColor($width, $height);
my $line = $width * 3;
while ( $line % 4 > 0 ) { $line ++; }

my $line_count = 0;
my $r;
my $g;
my $b;
my $index;
for ( my $y = $height-1 ; $y > -1 ; $y -- ) {
	for ( my $x = 0 ; $x < $width ; $x ++ ) {
		read ( IN, $dummy, 3 );
		( $b, $g, $r ) = unpack ( "C*", $dummy );
		$index = $im->colorResolve( $r, $g, $b );
		$im->setPixel($x, $y, $index);
		$line_count += 3;
	}
	while ( $line_count < $line ) {
		read ( IN, $dummy, 1 );
		$line_count ++;
	}
	$line_count = 0;
}

close ( IN );
open ( OUT, '>a.png' );
binmode ( OUT );
print OUT $im->png();
close ( OUT );