ppmtoCI.perl 3.98 KB
#! /usr/sbin/perl
#---------------------------------------------------------------------
#	Copyright (C) 1997, Nintendo.
#	
#	File		ppmtoCI.perl
#	Coded    by	Yoshitaka Yasumoto.	Apr  8, 1997.
#	Modified by	
#	Comments	
#	
#	$Id: ppmtoCI.perl,v 1.1.1.1 2002/05/02 03:27:17 blythe Exp $
#---------------------------------------------------------------------
#
#  [使用方法]
#	perl ppmtoCI.perl width height txtrlabel [tlutoffset] [xlucolor]
#
#       width:      出力する幅
#       height:     出力する高さ
#	txtrlabel:  テクスチャのラベル
#	tlutoffset: Index 値として tlutoffset 以降の値を使用します.
#		    Default は 1 です.
#	xlucolor:   透過色. 透過色を指定した場合, 透過色と同じ色の
#		    ピクセルの Index 値には 0 が設定されます. 透過
#		    色は #rrggbb と指定してください.
#

$argWidth    = $ARGV[0];
$argHeight   = $ARGV[1];
$argLavel    = $ARGV[2];
$argTLUTofs  = $ARGV[3];
$argXLUcolor = $ARGV[4];

# ppm ファイルのヘッダの解析
$i = 0;
while (<STDIN>){
	s/#.*$//;	# コメントの処理
	s/^\s+//;	# 空白の除去
	while (s/^\S+//){
		$param[$i ++] = $&;	# パラメータの保存
		s/^\s+//;		# 空白の除去
	}	
	last if ($i == 4);
}
die "This is not P6 ppm format!!\n" if ($param[0] ne "P6");

$width  = $param[1];
$height = $param[2];
$pixel  = $param[1] * $param[2];
$size   = $pixel * 3;

# TULT オフセット値の取得
if ($argTLUTofs ne ""){
    $offset = $argTLUTofs;
    $offset = hex($offset) if $offset =~ /^0[xX]/;
} else {
    $offset = 1;
}

# 透過色の取得
if ($argXLUcolor ne ""){
    if ($argXLUcolor =~ /^#([0-9a-fA-F]{6})/){
	$_ = hex($1);
        $xlucolor = &RGB32to16(($_>>16)&0xff, ($_>>8)&0xff, $_&0xff, 1);
    } else {
	die "Illegal XLU color format. must be \"#rrggbb\".\n";
    }
} else {
    $xlucolor = 0xffffffff;
}

# 高さと幅の出力
printf( "/*==========================*\n".
	"    Name  : $argLavel\n".
	"    Width : %d\n".
	"    Height: %d\n".
	" *==========================*/\n", $argWidth, $argHeight);

# テクスチャデータの出力
printf("unsigned char %s[] = {\n", $argLavel);

# もしサイズが大きいなら枠を黒にするためにパレットをリザーブする
$c = $offset;
$col = 0;
if ($width < $argWidth || $height < $argHeight){
    $tlut[$c] = 0x0001;
    $pal{0x0001} = $c;
    $c ++;
}

$x0 = ($width  - $argWidth ) / 2;
$y0 = ($height - $argHeight) / 2;

# パレットへの変換およびインデックスの出力
# パレット 0 は透過色に固定
for ($y = $y0; $y < $y0 + $argHeight; $y ++){
    for ($x = $x0; $x < $x0 + $argWidth; $x ++){
	# 範囲外かの判定
	if ($y < 0 || $y >= $height || $x < 0 || $x >= $width){
	    # 黒の出力
	    $index = $offset;
	} else {
	    # 1 Pixel 分のデータの取得
	    read(STDIN, $buf, 3) == 3 || die "Too short file\n";
	    @tmp = unpack("C3", $buf);
	    
	    # カラー値の取得
	    $color = &RGB32to16($tmp[0], $tmp[1], $tmp[2], 1);
	    
	    # 透過色の判定
	    if ($color == $xlucolor){
		$index = 0;
	    } else {
		# カラー値とパレットエントリの比較
		$index = $pal{$color};
		if ($index == 0){
		    # パレットに登録
		    $index = $pal{$color} = $c;
		    $tlut[$c] = $color;
		    $c ++;
		}
	    }
	}
	# 出力
	printf("    ") if $col == 0;    # 先頭カラムならインデント  
	printf("0x%02x,", $index);
	if (($col % 4) == 3){
	    printf(" ");
	}
	if ($col ++ == 11){
	    printf("\n");
	    $col = 0;
	}
    }
}
# 最終行桁あわせ
if ($col != 0){
    printf("\n");
}
printf("};\n\n");

# パレットの範囲の出力
printf( "/*==========================*\n".
	"    Name      : $argLavel_pal\n".
	"    Index from: 0x%02x (%d)\n".
	"    Index to  : 0x%02x (%d)\n".
	" *==========================*/\n", $offset, $offset, $c-1, $c-1);

# パレットデータの出力
printf("unsigned short %s_pal[] = {", $argLavel);
$col = 0;
for ($i = $offset; $i < $c; $i ++){
    if (($col % 8) == 0){
	printf("\n    ");
    }
    printf("0x%04x, ", $tlut[$i]);
    $col ++;
}
if ($col != 0){
    printf("\n");
}
printf("};\n\n");


#
#  RGB 32bit から RGB 16bit への変換ルーチン
#
sub RGB32to16 {
   local($r, $g, $b, $a) = @_;
   $r = ($r & 0xf8) << 8;
   $g = ($g & 0xf8) << 3;
   $b = ($b & 0xf8) >> 2;
   $_ = $r | $g | $b | $a;
}

#======== End of ppmtoCI.perl ========