OSDN Git Service

commit local dev ver
[rec10/rec10-git.git] / epgdump / clt2png.c
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
3 \r
4 #include <stdio.h>\r
5 #include <stdlib.h>\r
6 #include <string.h>\r
7 \r
8 #define bool char\r
9 #define true  1\r
10 #define false 0\r
11 #define inline\r
12 \r
13 typedef unsigned char byte;\r
14 typedef unsigned short uint16;\r
15 typedef unsigned long uint32;\r
16 \r
17 typedef struct _rgb_color {\r
18         byte r;\r
19         byte g;\r
20         byte b;\r
21         byte a;\r
22 } rgb_color;\r
23 \r
24 typedef struct _color_map_data {\r
25         byte clut_type;\r
26         byte depth;\r
27         byte region_flag;\r
28         byte start_end_flag;\r
29         byte reserved_future_use;\r
30         uint16 top_left_x;\r
31         uint16 top_left_y;\r
32         uint16 bottom_right_x;\r
33         uint16 bottom_right_y;\r
34         uint16 start_index;\r
35         uint16 end_index;\r
36         rgb_color color_map[0x10000];\r
37 } color_map_data;\r
38 \r
39 static const rgb_color default_colormap[128] = {\r
40         {  0,     0,      0,    255},\r
41         {255,     0,      0,    255},\r
42         {  0,   255,      0,    255},\r
43         {255,   255,      0,    255},\r
44         {  0,     0,      0,    255},\r
45         {255,     0,    255,    255},\r
46         {  0,   255,    255,    255},\r
47         {255,   255,    255,    255},\r
48         {  0,     0,      0,      0},\r
49         {170,     0,      0,    255},\r
50         {  0,   170,      0,    255},\r
51         {170,   170,      0,    255},\r
52         {  0,     0,    170,    255},\r
53         {170,     0,    170,    255},\r
54         {  0,   170,    170,    255},\r
55         {170,   170,    170,    255},\r
56         {  0,     0,     85,    255},\r
57         {  0,    85,      0,    255},\r
58         {  0,    85,     85,    255},\r
59         {  0,    85,    170,    255},\r
60         {  0,    85,    255,    255},\r
61         {  0,   170,     85,    255},\r
62         {  0,   170,    255,    255},\r
63         {  0,   255,     85,    255},\r
64         {  0,   255,    170,    255},\r
65         { 85,     0,      0,    255},\r
66         { 85,     0,     85,    255},\r
67         { 85,     0,    170,    255},\r
68         { 85,     0,    255,    255},\r
69         { 85,    85,      0,    255},\r
70         { 85,    85,     85,    255},\r
71         { 85,    85,    170,    255},\r
72         { 85,    85,    255,    255},\r
73         { 85,   170,      0,    255},\r
74         { 85,   170,     85,    255},\r
75         { 85,   170,    170,    255},\r
76         { 85,   170,    255,    255},\r
77         { 85,   255,      0,    255},\r
78         { 85,   255,     85,    255},\r
79         { 85,   255,    170,    255},\r
80         { 85,   255,    255,    255},\r
81         {170,     0,     85,    255},\r
82         {170,     0,    255,    255},\r
83         {170,    85,      0,    255},\r
84         {170,    85,     85,    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
89         {170,   255,      0,    255},\r
90         {170,   255,     85,    255},\r
91         {170,   255,    170,    255},\r
92         {170,   255,    255,    255},\r
93         {255,     0,     85,    255},\r
94         {255,     0,    170,    255},\r
95         {255,    85,      0,    255},\r
96         {255,    85,     85,    255},\r
97         {255,    85,    170,    255},\r
98         {255,    85,    255,    255},\r
99         {255,   170,      0,    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
105         {  0,     0,      0,    128},\r
106         {255,     0,      0,    128},\r
107         {  0,   255,      0,    128},\r
108         {255,   255,      0,    128},\r
109         {  0,     0,    255,    128},\r
110         {255,     0,    255,    128},\r
111         {  0,   255,    255,    128},\r
112         {255,   255,    255,    128},\r
113         {170,     0,      0,    128},\r
114         {  0,   170,      0,    128},\r
115         {170,   170,      0,    128},\r
116         {  0,     0,    170,    128},\r
117         {170,     0,    170,    128},\r
118         {  0,   170,    170,    128},\r
119         {170,   170,    170,    128},\r
120         {  0,     0,     85,    128},\r
121         {  0,    85,      0,    128},\r
122         {  0,    85,     85,    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
129         { 85,     0,      0,    128},\r
130         { 85,     0,     85,    128},\r
131         { 85,     0,    170,    128},\r
132         { 85,     0,    255,    128},\r
133         { 85,    85,      0,    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
145         {170,     0,     85,    128},\r
146         {170,     0,    255,    128},\r
147         {170,    85,      0,    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
157         {255,     0,     85,    128},\r
158         {255,     0,    170,    128},\r
159         {255,    85,      0,    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
168 };\r
169 \r
170 \r
171 /*\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
175 */\r
176 \r
177 inline byte ycbcr_to_r(int y,int cb,int cr)\r
178 {\r
179         int r=(76309*(y-16)+104597*(cr-128)+32768)/65536;\r
180         return (byte)(r<0?0:r>255?255:r);\r
181 }\r
182 \r
183 inline byte ycbcr_to_g(int y,int cb,int cr)\r
184 {\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
187 }\r
188 \r
189 inline byte ycbcr_to_b(int y,int cb,int cr)\r
190 {\r
191         int b=(76309*(y-16)+132201*(cb-128)+32768)/65536;\r
192         return (byte)(b<0?0:b>255?255:b);\r
193 }\r
194 \r
195 \r
196 byte read_byte(void *fp, int *index_fp)\r
197 {\r
198         int data = *((unsigned char*)fp + *index_fp++);\r
199         return (byte)data;\r
200 }\r
201 \r
202 \r
203 uint16 read_word(void *fp, int *index_fp)\r
204 {\r
205         byte data=read_byte(fp, index_fp);\r
206 \r
207         return ((uint16)data<<8)|(uint16)read_byte(fp, index_fp);\r
208 }\r
209 \r
210 \r
211 uint32 read_dword(void *fp, int *index_fp)\r
212 {\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
217 \r
218         return ((uint32)data1<<24)|((uint32)data2<<16)|((uint32)data3<<8)|(uint32)data4;\r
219 }\r
220 \r
221 \r
222 void read_data(void *fp,int *index_fp,void *data,size_t size)\r
223 {\r
224         memcpy(data,fp + *index_fp, size);\r
225         *index_fp += size;\r
226 }\r
227 \r
228 \r
229 void write_dword(void **fp, int *index_fp,uint32 value)\r
230 {\r
231         byte data[4];\r
232 \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
239         *index_fp += 4;\r
240 }\r
241 \r
242 \r
243 void write_data(void **fp,int *index_fp,void *data,size_t size)\r
244 {\r
245         *fp = realloc(*fp, *index_fp + size);\r
246         memcpy(*fp + *index_fp, data, size);\r
247         *index_fp += size;\r
248 }\r
249 \r
250 \r
251 uint32 calc_crc(const byte *data,size_t size)\r
252 {\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
318         };\r
319         uint32 crc;\r
320 \r
321         crc=0xFFFFFFFFUL;\r
322         for (size_t i=0;i<size;i++)\r
323                 crc=(crc>>8)^crc_table[(crc^data[i])&0x000000FFUL];\r
324         return ~crc;\r
325 }\r
326 \r
327 \r
328 int clt2png(void* input, void** output, int* output_size)\r
329 {\r
330         int input_index = 0, output_index = 0;\r
331 \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
335 \r
336         if (input!=NULL) {\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
343                         return 1;\r
344                 }\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
353                 }\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
365                         }\r
366                 } else {\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
372                         }\r
373                 }\r
374                 for (uint16 i=colormap.start_index;i<=colormap.end_index;i++) {\r
375                         if (colormap.clut_type==0) {\r
376                                 int y,cb,cr;\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
383                         } else {\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
387                         }\r
388                         colormap.color_map[i].a=read_byte(input, &input_index);\r
389                 }\r
390                 input_index = 0;\r
391         }\r
392 \r
393         // Open PNG file\r
394 \r
395         byte buffer[8];\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
399                 return 1;\r
400         }\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
404         while (true) {\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
408                         byte header[13];\r
409                         read_data(input,&input_index,header,13);\r
410                         bit_depth=header[8];\r
411                         color_type=header[9];\r
412                         input_index -= 13;\r
413                 } else if (memcmp(buffer+4,"PLTE",4)==0) {\r
414                         has_palette=true;\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
419                                 int i;\r
420                                 uint32 crc;\r
421 \r
422                                 // tRNS\r
423                                 for (i=0;i<num_colors;i++) {\r
424                                         if (colormap.color_map[i].a<255)\r
425                                                 break;\r
426                                 }\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
435                                 }\r
436 \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
445                                 }\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
449                         }\r
450                 }\r
451                 // Copy chunk\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
456                 free(data);\r
457                 if (memcmp(buffer+4,"IEND",4)==0)\r
458                         break;\r
459         }\r
460 \r
461         *output_size = output_index;\r
462 \r
463         return 0;\r
464 }\r
465 \r