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 10 #include <getopt.h> 11 #include <stdbool.h> 12 #include <stdio.h> 13 #include <stdlib.h> 14 #include <string.h> 15 16 #pragma pack(1) 17 18 /*#define ENABLE_ASCII_BANNERS */ 19 20 typedef struct { 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; 33 } tga_header_t; 34 35 typedef struct { 36 unsigned char r, g, b; 37 } rgb_t; 38 39 typedef struct { 40 unsigned char b, g, r; 41 } bgr_t; 42 43 typedef struct { 44 unsigned char Cb, y1, Cr, y2; 45 } yuyv_t; 46 47 typedef struct { 48 void *data, *palette; 49 int width, height, pixels, bpp, pixel_size, size, palette_size, yuyv; 50 } image_t; 51 52 void StringUpperCase (char *str) 53 { 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 } 63 } 64 65 void StringLowerCase (char *str) 66 { 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 } 76 } 77 void pixel_rgb_to_yuyv (rgb_t * rgb_pixel, yuyv_t * yuyv_pixel) 78 { 79 unsigned int pR, pG, pB; 80 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; 85 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; 90 91 return; 92 } 93 94 void printlogo_rgb (rgb_t * data, int w, int h) 95 { 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 } 107 } 108 109 void printlogo_yuyv (unsigned short *data, int w, int h) 110 { 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 } 121 } 122 123 static inline unsigned short le16_to_cpu (unsigned short val) 124 { 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]; 132 } 133 134 int image_load_tga (image_t * image, char *filename) 135 { 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; 164 165 default: 166 printf ("Format not supported!\n"); 167 return -1; 168 } 169 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); 175 176 if (image->bpp != 24) { 177 printf ("Bpp not supported: %d!\n", image->bpp); 178 return -1; 179 } 180 181 fread (image->data, image->size, 1, file); 182 183 /* Swapping R and B values */ 184 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 } 191 192 /* Swapping image */ 193 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; 199 200 printf ("S"); 201 if (temp == NULL) { 202 printf ("Cannot alloc temp buffer!\n"); 203 return -1; 204 } 205 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); 210 211 free (temp); 212 } 213 #ifdef ENABLE_ASCII_BANNERS 214 printlogo_rgb (image->data, image->width, image->height); 215 #endif 216 217 fclose (file); 218 return 0; 219 } 220 221 void image_free (image_t * image) 222 { 223 free (image->data); 224 free (image->palette); 225 } 226 227 int image_rgb_to_yuyv (image_t * rgb_image, image_t * yuyv_image) 228 { 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) { 247 pixel_rgb_to_yuyv (rgb_ptr++, &yuyv); 248 249 if ((count & 1) == 0) /* Was == 0 */ 250 memcpy (dest, ((void *) &yuyv) + 2, sizeof (short)); 251 else 252 memcpy (dest, (void *) &yuyv, sizeof (short)); 253 254 dest++; 255 } 256 257 #ifdef ENABLE_ASCII_BANNERS 258 printlogo_yuyv (yuyv_image->data, yuyv_image->width, 259 yuyv_image->height); 260 #endif 261 return 0; 262 } 263 264 int image_save_header (image_t * image, char *filename, char *varname) 265 { 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); 290 StringUpperCase (def_name); 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; 330 } 331 332 if (col) 333 fprintf (file, "%s\n", str); 334 335 /* End of declaration */ 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); 345 346 fclose (file); 347 348 return 0; 349 } 350 351 #define DEF_FILELEN 256 352 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 371 int main (int argc, char *argv[]) 372 { 373 int c; 374 bool use_rgb = false; 375 char inputfile[DEF_FILELEN], 376 outputfile[DEF_FILELEN], varname[DEF_FILELEN]; 377 378 image_t rgb_logo, yuyv_logo; 379 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; 392 } 393 } 394 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 } 411 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"); 418 } 419 420 /* Make sure the output is sent as soon as we printf() */ 421 setbuf(stdout, NULL); 422 423 printf ("Doing '%s' (%s) from '%s'...", 424 outputfile, varname, inputfile); 425 426 /* Import TGA logo */ 427 428 printf ("L"); 429 if (image_load_tga (&rgb_logo, inputfile) < 0) { 430 printf ("input file not found!\n"); 431 exit (1); 432 } 433 434 /* Convert it to YUYV format if wanted */ 435 436 if (!use_rgb) { 437 printf ("C"); 438 image_rgb_to_yuyv (&rgb_logo, &yuyv_logo); 439 } 440 441 /* Save it into a header format */ 442 443 printf ("S"); 444 image_save_header (use_rgb ? &rgb_logo : &yuyv_logo, outputfile, varname); 445 446 /* Free original image and copy */ 447 448 image_free (&rgb_logo); 449 if (!use_rgb) 450 image_free (&yuyv_logo); 451 452 printf ("\n"); 453 454 return 0; 455 } 456