ppmtoCI.perl
3.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
#! /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 ========