]>
Commit | Line | Data |
---|---|---|
fe8c2806 WD |
1 | /* |
2 | ** Easylogo TGA->header converter | |
3 | ** ============================== | |
4 | ** (C) 2000 by Paolo Scaffardi (arsenio@tin.it) | |
5 | ** AIRVENT SAM s.p.a - RIMINI(ITALY) | |
6 | ** | |
7 | ** This is still under construction! | |
8 | */ | |
9 | ||
edfed1d9 MF |
10 | #include <getopt.h> |
11 | #include <stdbool.h> | |
fe8c2806 | 12 | #include <stdio.h> |
38d299c2 MF |
13 | #include <stdlib.h> |
14 | #include <string.h> | |
fe8c2806 WD |
15 | |
16 | #pragma pack(1) | |
17 | ||
18 | /*#define ENABLE_ASCII_BANNERS */ | |
19 | ||
20 | typedef struct { | |
6007f325 WD |
21 | unsigned char id; |
22 | unsigned char ColorMapType; | |
23 | unsigned char ImageTypeCode; | |
24 | unsigned short ColorMapOrigin; | |
25 | unsigned short ColorMapLenght; | |
26 | unsigned char ColorMapEntrySize; | |
27 | unsigned short ImageXOrigin; | |
28 | unsigned short ImageYOrigin; | |
29 | unsigned short ImageWidth; | |
30 | unsigned short ImageHeight; | |
31 | unsigned char ImagePixelSize; | |
32 | unsigned char ImageDescriptorByte; | |
fe8c2806 WD |
33 | } tga_header_t; |
34 | ||
35 | typedef struct { | |
6007f325 WD |
36 | unsigned char r, g, b; |
37 | } rgb_t; | |
fe8c2806 WD |
38 | |
39 | typedef struct { | |
6007f325 WD |
40 | unsigned char b, g, r; |
41 | } bgr_t; | |
fe8c2806 WD |
42 | |
43 | typedef struct { | |
6007f325 WD |
44 | unsigned char Cb, y1, Cr, y2; |
45 | } yuyv_t; | |
fe8c2806 WD |
46 | |
47 | typedef struct { | |
6007f325 WD |
48 | void *data, *palette; |
49 | int width, height, pixels, bpp, pixel_size, size, palette_size, yuyv; | |
50 | } image_t; | |
fe8c2806 WD |
51 | |
52 | void StringUpperCase (char *str) | |
53 | { | |
6007f325 WD |
54 | int count = strlen (str); |
55 | char c; | |
56 | ||
57 | while (count--) { | |
58 | c = *str; | |
59 | if ((c >= 'a') && (c <= 'z')) | |
60 | *str = 'A' + (c - 'a'); | |
61 | str++; | |
62 | } | |
fe8c2806 WD |
63 | } |
64 | ||
65 | void StringLowerCase (char *str) | |
66 | { | |
6007f325 WD |
67 | int count = strlen (str); |
68 | char c; | |
69 | ||
70 | while (count--) { | |
71 | c = *str; | |
72 | if ((c >= 'A') && (c <= 'Z')) | |
73 | *str = 'a' + (c - 'A'); | |
74 | str++; | |
75 | } | |
fe8c2806 | 76 | } |
6007f325 | 77 | void pixel_rgb_to_yuyv (rgb_t * rgb_pixel, yuyv_t * yuyv_pixel) |
fe8c2806 | 78 | { |
6007f325 | 79 | unsigned int pR, pG, pB; |
fe8c2806 | 80 | |
6007f325 WD |
81 | /* Transform (0-255) components to (0-100) */ |
82 | pR = rgb_pixel->r * 100 / 255; | |
83 | pG = rgb_pixel->g * 100 / 255; | |
84 | pB = rgb_pixel->b * 100 / 255; | |
fe8c2806 | 85 | |
6007f325 WD |
86 | /* Calculate YUV values (0-255) from RGB beetween 0-100 */ |
87 | yuyv_pixel->y1 = yuyv_pixel->y2 = 209 * (pR + pG + pB) / 300 + 16; | |
88 | yuyv_pixel->Cb = pB - (pR / 4) - (pG * 3 / 4) + 128; | |
89 | yuyv_pixel->Cr = pR - (pG * 3 / 4) - (pB / 4) + 128; | |
fe8c2806 | 90 | |
6007f325 | 91 | return; |
fe8c2806 WD |
92 | } |
93 | ||
6007f325 | 94 | void printlogo_rgb (rgb_t * data, int w, int h) |
fe8c2806 | 95 | { |
6007f325 WD |
96 | int x, y; |
97 | ||
98 | for (y = 0; y < h; y++) { | |
99 | for (x = 0; x < w; x++, data++) | |
100 | if ((data->r < | |
101 | 30) /*&&(data->g == 0)&&(data->b == 0) */ ) | |
102 | printf (" "); | |
103 | else | |
104 | printf ("X"); | |
105 | printf ("\n"); | |
106 | } | |
fe8c2806 WD |
107 | } |
108 | ||
109 | void printlogo_yuyv (unsigned short *data, int w, int h) | |
110 | { | |
6007f325 WD |
111 | int x, y; |
112 | ||
113 | for (y = 0; y < h; y++) { | |
114 | for (x = 0; x < w; x++, data++) | |
115 | if (*data == 0x1080) /* Because of inverted on i386! */ | |
116 | printf (" "); | |
117 | else | |
118 | printf ("X"); | |
119 | printf ("\n"); | |
120 | } | |
fe8c2806 WD |
121 | } |
122 | ||
fc6414ec MF |
123 | static inline unsigned short le16_to_cpu (unsigned short val) |
124 | { | |
6007f325 WD |
125 | union { |
126 | unsigned char pval[2]; | |
127 | unsigned short val; | |
128 | } swapped; | |
129 | ||
130 | swapped.val = val; | |
131 | return (swapped.pval[1] << 8) + swapped.pval[0]; | |
fc6414ec MF |
132 | } |
133 | ||
6007f325 | 134 | int image_load_tga (image_t * image, char *filename) |
fe8c2806 | 135 | { |
6007f325 WD |
136 | FILE *file; |
137 | tga_header_t header; | |
138 | int i; | |
139 | unsigned char app; | |
140 | rgb_t *p; | |
141 | ||
142 | if ((file = fopen (filename, "rb")) == NULL) | |
143 | return -1; | |
144 | ||
145 | fread (&header, sizeof (header), 1, file); | |
146 | ||
147 | /* byte swap: tga is little endian, host is ??? */ | |
148 | header.ColorMapOrigin = le16_to_cpu (header.ColorMapOrigin); | |
149 | header.ColorMapLenght = le16_to_cpu (header.ColorMapLenght); | |
150 | header.ImageXOrigin = le16_to_cpu (header.ImageXOrigin); | |
151 | header.ImageYOrigin = le16_to_cpu (header.ImageYOrigin); | |
152 | header.ImageWidth = le16_to_cpu (header.ImageWidth); | |
153 | header.ImageHeight = le16_to_cpu (header.ImageHeight); | |
154 | ||
155 | image->width = header.ImageWidth; | |
156 | image->height = header.ImageHeight; | |
157 | ||
158 | switch (header.ImageTypeCode) { | |
159 | case 2: /* Uncompressed RGB */ | |
160 | image->yuyv = 0; | |
161 | image->palette_size = 0; | |
162 | image->palette = NULL; | |
163 | break; | |
fe8c2806 WD |
164 | |
165 | default: | |
6007f325 WD |
166 | printf ("Format not supported!\n"); |
167 | return -1; | |
168 | } | |
fe8c2806 | 169 | |
6007f325 WD |
170 | image->bpp = header.ImagePixelSize; |
171 | image->pixel_size = ((image->bpp - 1) / 8) + 1; | |
172 | image->pixels = image->width * image->height; | |
173 | image->size = image->pixels * image->pixel_size; | |
174 | image->data = malloc (image->size); | |
fe8c2806 | 175 | |
6007f325 WD |
176 | if (image->bpp != 24) { |
177 | printf ("Bpp not supported: %d!\n", image->bpp); | |
178 | return -1; | |
179 | } | |
fe8c2806 | 180 | |
6007f325 | 181 | fread (image->data, image->size, 1, file); |
fe8c2806 WD |
182 | |
183 | /* Swapping R and B values */ | |
184 | ||
6007f325 WD |
185 | p = image->data; |
186 | for (i = 0; i < image->pixels; i++, p++) { | |
187 | app = p->r; | |
188 | p->r = p->b; | |
189 | p->b = app; | |
190 | } | |
fe8c2806 WD |
191 | |
192 | /* Swapping image */ | |
193 | ||
6007f325 WD |
194 | if (!(header.ImageDescriptorByte & 0x20)) { |
195 | unsigned char *temp = malloc (image->size); | |
196 | int linesize = image->pixel_size * image->width; | |
197 | void *dest = image->data, | |
198 | *source = temp + image->size - linesize; | |
fe8c2806 | 199 | |
6007f325 WD |
200 | printf ("S"); |
201 | if (temp == NULL) { | |
202 | printf ("Cannot alloc temp buffer!\n"); | |
203 | return -1; | |
204 | } | |
fe8c2806 | 205 | |
6007f325 WD |
206 | memcpy (temp, image->data, image->size); |
207 | for (i = 0; i < image->height; | |
208 | i++, dest += linesize, source -= linesize) | |
209 | memcpy (dest, source, linesize); | |
fe8c2806 | 210 | |
6007f325 WD |
211 | free (temp); |
212 | } | |
fe8c2806 | 213 | #ifdef ENABLE_ASCII_BANNERS |
6007f325 | 214 | printlogo_rgb (image->data, image->width, image->height); |
fe8c2806 WD |
215 | #endif |
216 | ||
6007f325 WD |
217 | fclose (file); |
218 | return 0; | |
fe8c2806 WD |
219 | } |
220 | ||
edfed1d9 | 221 | void image_free (image_t * image) |
fe8c2806 | 222 | { |
edfed1d9 MF |
223 | free (image->data); |
224 | free (image->palette); | |
fe8c2806 WD |
225 | } |
226 | ||
6007f325 | 227 | int image_rgb_to_yuyv (image_t * rgb_image, image_t * yuyv_image) |
fe8c2806 | 228 | { |
6007f325 WD |
229 | rgb_t *rgb_ptr = (rgb_t *) rgb_image->data; |
230 | yuyv_t yuyv; | |
231 | unsigned short *dest; | |
232 | int count = 0; | |
233 | ||
234 | yuyv_image->pixel_size = 2; | |
235 | yuyv_image->bpp = 16; | |
236 | yuyv_image->yuyv = 1; | |
237 | yuyv_image->width = rgb_image->width; | |
238 | yuyv_image->height = rgb_image->height; | |
239 | yuyv_image->pixels = yuyv_image->width * yuyv_image->height; | |
240 | yuyv_image->size = yuyv_image->pixels * yuyv_image->pixel_size; | |
241 | dest = (unsigned short *) (yuyv_image->data = | |
242 | malloc (yuyv_image->size)); | |
243 | yuyv_image->palette = 0; | |
244 | yuyv_image->palette_size = 0; | |
245 | ||
246 | while ((count++) < rgb_image->pixels) { | |
fe8c2806 WD |
247 | pixel_rgb_to_yuyv (rgb_ptr++, &yuyv); |
248 | ||
6007f325 WD |
249 | if ((count & 1) == 0) /* Was == 0 */ |
250 | memcpy (dest, ((void *) &yuyv) + 2, sizeof (short)); | |
fe8c2806 | 251 | else |
6007f325 | 252 | memcpy (dest, (void *) &yuyv, sizeof (short)); |
fe8c2806 | 253 | |
6007f325 | 254 | dest++; |
fe8c2806 WD |
255 | } |
256 | ||
257 | #ifdef ENABLE_ASCII_BANNERS | |
6007f325 WD |
258 | printlogo_yuyv (yuyv_image->data, yuyv_image->width, |
259 | yuyv_image->height); | |
fe8c2806 | 260 | #endif |
6007f325 | 261 | return 0; |
fe8c2806 WD |
262 | } |
263 | ||
6007f325 | 264 | int image_save_header (image_t * image, char *filename, char *varname) |
fe8c2806 | 265 | { |
6007f325 WD |
266 | FILE *file = fopen (filename, "w"); |
267 | char app[256], str[256] = "", def_name[64]; | |
268 | int count = image->size, col = 0; | |
269 | unsigned char *dataptr = image->data; | |
270 | ||
271 | if (file == NULL) | |
272 | return -1; | |
273 | ||
274 | /* Author information */ | |
275 | fprintf (file, | |
276 | "/*\n * Generated by EasyLogo, (C) 2000 by Paolo Scaffardi\n *\n"); | |
277 | fprintf (file, | |
278 | " * To use this, include it and call: easylogo_plot(screen,&%s, width,x,y)\n *\n", | |
279 | varname); | |
280 | fprintf (file, | |
281 | " * Where:\t'screen'\tis the pointer to the frame buffer\n"); | |
282 | fprintf (file, " *\t\t'width'\tis the screen width\n"); | |
283 | fprintf (file, " *\t\t'x'\t\tis the horizontal position\n"); | |
284 | fprintf (file, " *\t\t'y'\t\tis the vertical position\n */\n\n"); | |
285 | ||
286 | /* Headers */ | |
287 | fprintf (file, "#include <video_easylogo.h>\n\n"); | |
288 | /* Macros */ | |
289 | strcpy (def_name, varname); | |
fe8c2806 | 290 | StringUpperCase (def_name); |
6007f325 WD |
291 | fprintf (file, "#define DEF_%s_WIDTH\t\t%d\n", def_name, |
292 | image->width); | |
293 | fprintf (file, "#define DEF_%s_HEIGHT\t\t%d\n", def_name, | |
294 | image->height); | |
295 | fprintf (file, "#define DEF_%s_PIXELS\t\t%d\n", def_name, | |
296 | image->pixels); | |
297 | fprintf (file, "#define DEF_%s_BPP\t\t%d\n", def_name, image->bpp); | |
298 | fprintf (file, "#define DEF_%s_PIXEL_SIZE\t%d\n", def_name, | |
299 | image->pixel_size); | |
300 | fprintf (file, "#define DEF_%s_SIZE\t\t%d\n\n", def_name, | |
301 | image->size); | |
302 | /* Declaration */ | |
303 | fprintf (file, "unsigned char DEF_%s_DATA[DEF_%s_SIZE] = {\n", | |
304 | def_name, def_name); | |
305 | ||
306 | /* Data */ | |
307 | while (count) | |
308 | switch (col) { | |
309 | case 0: | |
310 | sprintf (str, " 0x%02x", *dataptr++); | |
311 | col++; | |
312 | count--; | |
313 | break; | |
314 | ||
315 | case 16: | |
316 | fprintf (file, "%s", str); | |
317 | if (count > 0) | |
318 | fprintf (file, ","); | |
319 | fprintf (file, "\n"); | |
320 | ||
321 | col = 0; | |
322 | break; | |
323 | ||
324 | default: | |
325 | strcpy (app, str); | |
326 | sprintf (str, "%s, 0x%02x", app, *dataptr++); | |
327 | col++; | |
328 | count--; | |
329 | break; | |
fe8c2806 WD |
330 | } |
331 | ||
332 | if (col) | |
6007f325 WD |
333 | fprintf (file, "%s\n", str); |
334 | ||
53677ef1 | 335 | /* End of declaration */ |
6007f325 WD |
336 | fprintf (file, "};\n\n"); |
337 | /* Variable */ | |
338 | fprintf (file, "fastimage_t %s = {\n", varname); | |
339 | fprintf (file, " DEF_%s_DATA,\n", def_name); | |
340 | fprintf (file, " DEF_%s_WIDTH,\n", def_name); | |
341 | fprintf (file, " DEF_%s_HEIGHT,\n", def_name); | |
342 | fprintf (file, " DEF_%s_BPP,\n", def_name); | |
343 | fprintf (file, " DEF_%s_PIXEL_SIZE,\n", def_name); | |
344 | fprintf (file, " DEF_%s_SIZE\n};\n", def_name); | |
fe8c2806 WD |
345 | |
346 | fclose (file); | |
347 | ||
6007f325 | 348 | return 0; |
fe8c2806 WD |
349 | } |
350 | ||
351 | #define DEF_FILELEN 256 | |
352 | ||
edfed1d9 MF |
353 | static void usage (int exit_status) |
354 | { | |
355 | puts ( | |
356 | "EasyLogo 1.0 (C) 2000 by Paolo Scaffardi\n" | |
357 | "\n" | |
358 | "Syntax: easylogo [options] inputfile [outputvar [outputfile]]\n" | |
359 | "\n" | |
360 | "Options:\n" | |
361 | " -r Output RGB instead of YUYV\n" | |
362 | " -h Help output\n" | |
363 | "\n" | |
364 | "Where: 'inputfile' is the TGA image to load\n" | |
365 | " 'outputvar' is the variable name to create\n" | |
366 | " 'outputfile' is the output header file (default is 'inputfile.h')" | |
367 | ); | |
368 | exit (exit_status); | |
369 | } | |
370 | ||
fe8c2806 WD |
371 | int main (int argc, char *argv[]) |
372 | { | |
edfed1d9 MF |
373 | int c; |
374 | bool use_rgb = false; | |
6007f325 WD |
375 | char inputfile[DEF_FILELEN], |
376 | outputfile[DEF_FILELEN], varname[DEF_FILELEN]; | |
377 | ||
378 | image_t rgb_logo, yuyv_logo; | |
379 | ||
edfed1d9 MF |
380 | while ((c = getopt(argc, argv, "hr")) > 0) { |
381 | switch (c) { | |
382 | case 'h': | |
383 | usage (0); | |
384 | break; | |
385 | case 'r': | |
386 | use_rgb = true; | |
387 | puts ("Using 24-bit RGB Output Fromat"); | |
388 | break; | |
389 | default: | |
390 | usage (1); | |
391 | break; | |
6007f325 | 392 | } |
edfed1d9 | 393 | } |
fe8c2806 | 394 | |
edfed1d9 MF |
395 | c = argc - optind; |
396 | if (c > 4 || c < 1) | |
397 | usage (1); | |
398 | ||
399 | strcpy (inputfile, argv[optind]); | |
400 | ||
401 | if (c > 1) | |
402 | strcpy (varname, argv[optind + 1]); | |
403 | else { | |
404 | /* transform "input.tga" to just "input" */ | |
405 | char *dot; | |
406 | strcpy (varname, inputfile); | |
407 | dot = strchr (varname, '.'); | |
408 | if (dot) | |
409 | *dot = '\0'; | |
410 | } | |
fe8c2806 | 411 | |
edfed1d9 MF |
412 | if (c > 2) |
413 | strcpy (outputfile, argv[optind + 2]); | |
414 | else { | |
415 | /* just append ".h" to input file name */ | |
416 | strcpy (outputfile, inputfile); | |
417 | strcat (outputfile, ".h"); | |
6007f325 | 418 | } |
fe8c2806 | 419 | |
edfed1d9 MF |
420 | /* Make sure the output is sent as soon as we printf() */ |
421 | setbuf(stdout, NULL); | |
422 | ||
6007f325 WD |
423 | printf ("Doing '%s' (%s) from '%s'...", |
424 | outputfile, varname, inputfile); | |
fe8c2806 | 425 | |
6007f325 | 426 | /* Import TGA logo */ |
fe8c2806 | 427 | |
6007f325 WD |
428 | printf ("L"); |
429 | if (image_load_tga (&rgb_logo, inputfile) < 0) { | |
430 | printf ("input file not found!\n"); | |
431 | exit (1); | |
432 | } | |
fe8c2806 | 433 | |
edfed1d9 | 434 | /* Convert it to YUYV format if wanted */ |
fe8c2806 | 435 | |
edfed1d9 MF |
436 | if (!use_rgb) { |
437 | printf ("C"); | |
438 | image_rgb_to_yuyv (&rgb_logo, &yuyv_logo); | |
439 | } | |
fe8c2806 | 440 | |
6007f325 | 441 | /* Save it into a header format */ |
fe8c2806 | 442 | |
6007f325 | 443 | printf ("S"); |
edfed1d9 | 444 | image_save_header (use_rgb ? &rgb_logo : &yuyv_logo, outputfile, varname); |
fe8c2806 | 445 | |
6007f325 | 446 | /* Free original image and copy */ |
fe8c2806 | 447 | |
6007f325 | 448 | image_free (&rgb_logo); |
edfed1d9 MF |
449 | if (!use_rgb) |
450 | image_free (&yuyv_logo); | |
fe8c2806 | 451 | |
6007f325 | 452 | printf ("\n"); |
fe8c2806 | 453 | |
6007f325 | 454 | return 0; |
fe8c2806 | 455 | } |