1 //
\83f
\81[
\83^
\95ú
\91\97\97p
\83v
\83\8d\83O
\83\89\83\80\8bl
\82ß
\8d\87\82í
\82¹
\82»
\82Ì2
\82æ
\82è
\97¬
\97p
\r
2 //
\83J
\83\89\81[
\83}
\83b
\83v
\83f
\81[
\83^
\82ðPNG
\82É
\93K
\97p
\82·
\82é
\r
13 typedef unsigned char byte;
\r
14 typedef unsigned short uint16;
\r
15 typedef unsigned long uint32;
\r
17 typedef struct _rgb_color {
\r
24 typedef struct _color_map_data {
\r
28 byte start_end_flag;
\r
29 byte reserved_future_use;
\r
32 uint16 bottom_right_x;
\r
33 uint16 bottom_right_y;
\r
36 rgb_color color_map[0x10000];
\r
39 static const rgb_color default_colormap[128] = {
\r
46 { 0, 255, 255, 255},
\r
47 {255, 255, 255, 255},
\r
54 { 0, 170, 170, 255},
\r
55 {170, 170, 170, 255},
\r
62 { 0, 170, 255, 255},
\r
64 { 0, 255, 170, 255},
\r
71 { 85, 85, 170, 255},
\r
72 { 85, 85, 255, 255},
\r
74 { 85, 170, 85, 255},
\r
75 { 85, 170, 170, 255},
\r
76 { 85, 170, 255, 255},
\r
78 { 85, 255, 85, 255},
\r
79 { 85, 255, 170, 255},
\r
80 { 85, 255, 255, 255},
\r
85 {170, 85, 170, 255},
\r
86 {170, 85, 255, 255},
\r
87 {170, 170, 85, 255},
\r
88 {170, 170, 255, 255},
\r
90 {170, 255, 85, 255},
\r
91 {170, 255, 170, 255},
\r
92 {170, 255, 255, 255},
\r
97 {255, 85, 170, 255},
\r
98 {255, 85, 255, 255},
\r
100 {255, 170, 85, 255},
\r
101 {255, 170, 170, 255},
\r
102 {255, 170, 255, 255},
\r
103 {255, 225, 85, 255},
\r
104 {225, 225, 170, 255},
\r
108 {255, 255, 0, 128},
\r
110 {255, 0, 255, 128},
\r
111 { 0, 255, 255, 128},
\r
112 {255, 255, 255, 128},
\r
115 {170, 170, 0, 128},
\r
117 {170, 0, 170, 128},
\r
118 { 0, 170, 170, 128},
\r
119 {170, 170, 170, 128},
\r
123 { 0, 85, 170, 128},
\r
124 { 0, 85, 255, 128},
\r
125 { 0, 170, 85, 128},
\r
126 { 0, 170, 255, 128},
\r
127 { 0, 255, 85, 128},
\r
128 { 0, 255, 170, 128},
\r
131 { 85, 0, 170, 128},
\r
132 { 85, 0, 255, 128},
\r
134 { 85, 85, 85, 128},
\r
135 { 85, 85, 170, 128},
\r
136 { 85, 85, 255, 128},
\r
137 { 85, 170, 0, 128},
\r
138 { 85, 170, 85, 128},
\r
139 { 85, 170, 170, 128},
\r
140 { 85, 170, 255, 128},
\r
141 { 85, 255, 0, 128},
\r
142 { 85, 255, 85, 128},
\r
143 { 85, 255, 170, 128},
\r
144 { 85, 255, 255, 128},
\r
146 {170, 0, 255, 128},
\r
148 {170, 85, 85, 128},
\r
149 {170, 85, 170, 128},
\r
150 {170, 85, 255, 128},
\r
151 {170, 170, 85, 128},
\r
152 {170, 170, 255, 128},
\r
153 {170, 255, 0, 128},
\r
154 {170, 255, 85, 128},
\r
155 {170, 255, 170, 128},
\r
156 {170, 255, 255, 128},
\r
158 {255, 0, 170, 128},
\r
160 {255, 85, 85, 128},
\r
161 {255, 85, 170, 128},
\r
162 {255, 85, 255, 128},
\r
163 {255, 170, 0, 128},
\r
164 {255, 170, 85, 128},
\r
165 {255, 170, 170, 128},
\r
166 {255, 170, 255, 128},
\r
167 {255, 255, 85, 128},
\r
172 Y = 0.2126 * R + 0.7152 * G + 0.0722 * B
\r
173 Cb = -(0.2126/1.8556)*(224/219) * R -(0.7152/1.8556)*(224/219) * G 0.5*(224/219) * B
\r
174 Cr = 0.5*(224/219) * R -(0.7152/1.5748)*(224/219) * G -(0.0722/1.5748)*(224/219) * B
\r
177 inline byte ycbcr_to_r(int y,int cb,int cr)
\r
179 int r=(76309*(y-16)+104597*(cr-128)+32768)/65536;
\r
180 return (byte)(r<0?0:r>255?255:r);
\r
183 inline byte ycbcr_to_g(int y,int cb,int cr)
\r
185 int g=(76309*(y-16)-25675*(cb-128)-53279*(cr-128)+32768)/65536;
\r
186 return (byte)(g<0?0:g>255?255:g);
\r
189 inline byte ycbcr_to_b(int y,int cb,int cr)
\r
191 int b=(76309*(y-16)+132201*(cb-128)+32768)/65536;
\r
192 return (byte)(b<0?0:b>255?255:b);
\r
196 byte read_byte(void *fp, int *index_fp)
\r
198 int data = *((unsigned char*)fp + *index_fp++);
\r
203 uint16 read_word(void *fp, int *index_fp)
\r
205 byte data=read_byte(fp, index_fp);
\r
207 return ((uint16)data<<8)|(uint16)read_byte(fp, index_fp);
\r
211 uint32 read_dword(void *fp, int *index_fp)
\r
213 byte data1=read_byte(fp, index_fp);
\r
214 byte data2=read_byte(fp, index_fp);
\r
215 byte data3=read_byte(fp, index_fp);
\r
216 byte data4=read_byte(fp, index_fp);
\r
218 return ((uint32)data1<<24)|((uint32)data2<<16)|((uint32)data3<<8)|(uint32)data4;
\r
222 void read_data(void *fp,int *index_fp,void *data,size_t size)
\r
224 memcpy(data,fp + *index_fp, size);
\r
229 void write_dword(void **fp, int *index_fp,uint32 value)
\r
233 data[0]=(byte)(value>>24);
\r
234 data[1]=(byte)((value>>16)&0xFF);
\r
235 data[2]=(byte)((value>>8)&0xFF);
\r
236 data[3]=(byte)(value&0xFF);
\r
237 *fp = realloc(*fp, *index_fp + 4);
\r
238 memcpy(*fp + *index_fp, data, 4);
\r
243 void write_data(void **fp,int *index_fp,void *data,size_t size)
\r
245 *fp = realloc(*fp, *index_fp + size);
\r
246 memcpy(*fp + *index_fp, data, size);
\r
251 uint32 calc_crc(const byte *data,size_t size)
\r
253 static const uint32 crc_table[256] = {
\r
254 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
\r
255 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
\r
256 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
\r
257 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
\r
258 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
\r
259 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
\r
260 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
\r
261 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
\r
262 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
\r
263 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
\r
264 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
\r
265 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
\r
266 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
\r
267 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
\r
268 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
\r
269 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
\r
270 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
\r
271 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
\r
272 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
\r
273 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
\r
274 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
\r
275 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
\r
276 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
\r
277 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
\r
278 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
\r
279 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
\r
280 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
\r
281 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
\r
282 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
\r
283 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
\r
284 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
\r
285 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
\r
286 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
\r
287 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
\r
288 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
\r
289 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
\r
290 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
\r
291 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
\r
292 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
\r
293 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
\r
294 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
\r
295 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
\r
296 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
\r
297 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
\r
298 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
\r
299 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
\r
300 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
\r
301 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
\r
302 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
\r
303 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
\r
304 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
\r
305 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
\r
306 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
\r
307 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
\r
308 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
\r
309 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
\r
310 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
\r
311 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
\r
312 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
\r
313 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
\r
314 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
\r
315 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
\r
316 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
\r
317 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D,
\r
322 for (size_t i=0;i<size;i++)
\r
323 crc=(crc>>8)^crc_table[(crc^data[i])&0x000000FFUL];
\r
328 int clt2png(void* input, void** output, int* output_size)
\r
330 int input_index = 0, output_index = 0;
\r
332 color_map_data colormap;
\r
333 memset(colormap.color_map,0,sizeof(colormap.color_map));
\r
334 memcpy(colormap.color_map,default_colormap,sizeof(default_colormap));
\r
337 // Parse color_map_data
\r
338 byte b=read_byte(input, &input_index);
\r
339 colormap.clut_type=(b&0x80)>>7;
\r
340 colormap.depth=(b&0x60)>>5;
\r
341 if (colormap.depth==3) {
\r
342 printf("Error : Unknown depth (%d)\n",colormap.depth);
\r
345 colormap.region_flag=(b&0x10)>>4;
\r
346 colormap.start_end_flag=(b&0x08)>>3;
\r
347 colormap.reserved_future_use=b&0x07;
\r
348 if (colormap.region_flag) {
\r
349 colormap.top_left_x=read_word(input, &input_index);
\r
350 colormap.top_left_y=read_word(input, &input_index);
\r
351 colormap.bottom_right_x=read_word(input, &input_index);
\r
352 colormap.bottom_right_y=read_word(input, &input_index);
\r
354 if (colormap.start_end_flag) {
\r
355 if (colormap.depth==0) {
\r
356 b=read_byte(input, &input_index);
\r
357 colormap.start_index=b>>4;
\r
358 colormap.end_index=b&0x0F;
\r
359 } else if (colormap.depth==1) {
\r
360 colormap.start_index=read_byte(input, &input_index);
\r
361 colormap.end_index=read_byte(input, &input_index);
\r
362 } else if (colormap.depth==2) {
\r
363 colormap.start_index=read_word(input, &input_index);
\r
364 colormap.end_index=read_word(input, &input_index);
\r
367 colormap.start_index=0;
\r
368 switch (colormap.depth) {
\r
369 case 0: colormap.end_index=15; break;
\r
370 case 1: colormap.end_index=255; break;
\r
371 case 2: colormap.end_index=65535; break;
\r
374 for (uint16 i=colormap.start_index;i<=colormap.end_index;i++) {
\r
375 if (colormap.clut_type==0) {
\r
377 y=read_byte(input, &input_index);
\r
378 cb=read_byte(input, &input_index);
\r
379 cr=read_byte(input, &input_index);
\r
380 colormap.color_map[i].r=ycbcr_to_r(y,cb,cr);
\r
381 colormap.color_map[i].g=ycbcr_to_g(y,cb,cr);
\r
382 colormap.color_map[i].b=ycbcr_to_b(y,cb,cr);
\r
384 colormap.color_map[i].r=read_byte(input, &input_index);
\r
385 colormap.color_map[i].g=read_byte(input, &input_index);
\r
386 colormap.color_map[i].b=read_byte(input, &input_index);
\r
388 colormap.color_map[i].a=read_byte(input, &input_index);
\r
396 read_data(input,&input_index,buffer,8);
\r
397 if (memcmp(buffer,"\x89PNG\r\n\x1A\n",8)!=0) {
\r
398 printf("Error : Not a PNG format\n");
\r
401 write_data(output,&output_index,buffer,8);
\r
402 int bit_depth=0,color_type=-1;
\r
403 bool has_palette=false;
\r
405 read_data(input,&input_index,buffer,8);
\r
406 uint32 data_size=((uint32)buffer[0]<<24)|((uint32)buffer[1]<<16)|((uint32)buffer[2]<<8)|(uint32)buffer[3];
\r
407 if (memcmp(buffer+4,"IHDR",4)==0) {
\r
409 read_data(input,&input_index,header,13);
\r
410 bit_depth=header[8];
\r
411 color_type=header[9];
\r
413 } else if (memcmp(buffer+4,"PLTE",4)==0) {
\r
415 } else if (memcmp(buffer+4,"IDAT",4)==0) {
\r
416 if (!has_palette && bit_depth<=8 && color_type==3) {
\r
417 int num_colors=1<<bit_depth;
\r
418 byte data[4+256*3];
\r
423 for (i=0;i<num_colors;i++) {
\r
424 if (colormap.color_map[i].a<255)
\r
427 if (i<num_colors) {
\r
428 write_dword(output,&output_index,num_colors);
\r
429 memcpy(data,"tRNS",4);
\r
430 for (int i=0;i<num_colors;i++)
\r
431 data[4+i]=colormap.color_map[i].a;
\r
432 write_data(output,&output_index,data,4+num_colors);
\r
433 crc=calc_crc(data,4+num_colors);
\r
434 write_dword(output,&output_index,crc);
\r
437 // Generate PLTE chunk
\r
438 uint32 palette_size=num_colors*3;
\r
439 write_dword(output,&output_index,palette_size);
\r
440 memcpy(data,"PLTE",4);
\r
441 for (i=0;i<num_colors;i++) {
\r
442 data[4+i*3+0]=colormap.color_map[i].r;
\r
443 data[4+i*3+1]=colormap.color_map[i].g;
\r
444 data[4+i*3+2]=colormap.color_map[i].b;
\r
446 write_data(output,&output_index,data,4+palette_size);
\r
447 crc=calc_crc(data,4+palette_size);
\r
448 write_dword(output,&output_index,crc);
\r
452 write_data(output,&output_index,buffer,8);
\r
453 void *data = malloc(data_size+4);
\r
454 read_data(input,&input_index,data,data_size+4);
\r
455 write_data(output,&output_index,data,data_size+4);
\r
457 if (memcmp(buffer+4,"IEND",4)==0)
\r
461 *output_size = output_index;
\r