]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - tools/easylogo/easylogo.c
easylogo: add lzma support
[karo-tx-uboot.git] / tools / easylogo / easylogo.c
index 080bea9bb8cfe5259746874a90d187cd4159b23e..4ba86bf76076fa0886dbdc4782d15c319c34f3db 100644 (file)
@@ -3,13 +3,19 @@
 ** ==============================
 ** (C) 2000 by Paolo Scaffardi (arsenio@tin.it)
 ** AIRVENT SAM s.p.a - RIMINI(ITALY)
+** (C) 2007-2008 Mike Frysinger <vapier@gentoo.org>
 **
 ** This is still under construction!
 */
 
+#include <errno.h>
+#include <getopt.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
 
 #pragma pack(1)
 
@@ -47,6 +53,17 @@ typedef struct {
        int width, height, pixels, bpp, pixel_size, size, palette_size, yuyv;
 } image_t;
 
+void *xmalloc (size_t size)
+{
+       void *ret = malloc (size);
+       if (!ret) {
+               fprintf (stderr, "\nerror: malloc(%zu) failed: %s",
+                       size, strerror(errno));
+               exit (1);
+       }
+       return ret;
+}
+
 void StringUpperCase (char *str)
 {
        int count = strlen (str);
@@ -169,7 +186,7 @@ int image_load_tga (image_t * image, char *filename)
        image->pixel_size = ((image->bpp - 1) / 8) + 1;
        image->pixels = image->width * image->height;
        image->size = image->pixels * image->pixel_size;
-       image->data = malloc (image->size);
+       image->data = xmalloc (image->size);
 
        if (image->bpp != 24) {
                printf ("Bpp not supported: %d!\n", image->bpp);
@@ -190,7 +207,7 @@ int image_load_tga (image_t * image, char *filename)
 /* Swapping image */
 
        if (!(header.ImageDescriptorByte & 0x20)) {
-               unsigned char *temp = malloc (image->size);
+               unsigned char *temp = xmalloc (image->size);
                int linesize = image->pixel_size * image->width;
                void *dest = image->data,
                        *source = temp + image->size - linesize;
@@ -216,15 +233,10 @@ int image_load_tga (image_t * image, char *filename)
        return 0;
 }
 
-int image_free (image_t * image)
+void image_free (image_t * image)
 {
-       if (image->data != NULL)
-               free (image->data);
-
-       if (image->palette != NULL)
-               free (image->palette);
-
-       return 0;
+       free (image->data);
+       free (image->palette);
 }
 
 int image_rgb_to_yuyv (image_t * rgb_image, image_t * yuyv_image)
@@ -242,7 +254,7 @@ int image_rgb_to_yuyv (image_t * rgb_image, image_t * yuyv_image)
        yuyv_image->pixels = yuyv_image->width * yuyv_image->height;
        yuyv_image->size = yuyv_image->pixels * yuyv_image->pixel_size;
        dest = (unsigned short *) (yuyv_image->data =
-                                  malloc (yuyv_image->size));
+                                  xmalloc (yuyv_image->size));
        yuyv_image->palette = 0;
        yuyv_image->palette_size = 0;
 
@@ -264,6 +276,43 @@ int image_rgb_to_yuyv (image_t * rgb_image, image_t * yuyv_image)
        return 0;
 }
 
+int image_rgb888_to_rgb565(image_t *rgb888_image, image_t *rgb565_image)
+{
+       rgb_t *rgb_ptr = (rgb_t *) rgb888_image->data;
+       unsigned short *dest;
+       int count = 0;
+
+       rgb565_image->pixel_size = 2;
+       rgb565_image->bpp = 16;
+       rgb565_image->yuyv = 0;
+       rgb565_image->width = rgb888_image->width;
+       rgb565_image->height = rgb888_image->height;
+       rgb565_image->pixels = rgb565_image->width * rgb565_image->height;
+       rgb565_image->size = rgb565_image->pixels * rgb565_image->pixel_size;
+       dest = (unsigned short *) (rgb565_image->data =
+                                  xmalloc(rgb565_image->size));
+       rgb565_image->palette = 0;
+       rgb565_image->palette_size = 0;
+
+       while ((count++) < rgb888_image->pixels) {
+
+               *dest++ = ((rgb_ptr->b & 0xF8) << 8) |
+                       ((rgb_ptr->g & 0xFC) << 3) |
+                       (rgb_ptr->r >> 3);
+               rgb_ptr++;
+       }
+
+       return 0;
+}
+
+enum comp_t {
+       COMP_NONE,
+       COMP_GZIP,
+       COMP_LZMA,
+};
+static enum comp_t compression = COMP_NONE;
+static bool bss_storage = false;
+
 int image_save_header (image_t * image, char *filename, char *varname)
 {
        FILE *file = fopen (filename, "w");
@@ -286,6 +335,81 @@ int image_save_header (image_t * image, char *filename, char *varname)
        fprintf (file, " *\t\t'x'\t\tis the horizontal position\n");
        fprintf (file, " *\t\t'y'\t\tis the vertical position\n */\n\n");
 
+       /* image compress */
+       if (compression != COMP_NONE) {
+               const char *errstr = NULL;
+               unsigned char *compressed;
+               const char *comp_name;
+               struct stat st;
+               FILE *compfp;
+               size_t filename_len = strlen(filename);
+               char *compfilename = xmalloc(filename_len + 20);
+               char *compcmd = xmalloc(filename_len + 50);
+
+               sprintf(compfilename, "%s.bin", filename);
+               switch (compression) {
+               case COMP_GZIP:
+                       strcpy(compcmd, "gzip");
+                       comp_name = "GZIP";
+                       break;
+               case COMP_LZMA:
+                       strcpy(compcmd, "lzma");
+                       comp_name = "LZMA";
+                       break;
+               default:
+                       errstr = "\nerror: unknown compression method";
+                       goto done;
+               }
+               strcat(compcmd, " > ");
+               strcat(compcmd, compfilename);
+               compfp = popen(compcmd, "w");
+               if (!compfp) {
+                       errstr = "\nerror: popen() failed";
+                       goto done;
+               }
+               if (fwrite(image->data, image->size, 1, compfp) != 1) {
+                       errstr = "\nerror: writing data to gzip failed";
+                       goto done;
+               }
+               if (pclose(compfp)) {
+                       errstr = "\nerror: gzip process failed";
+                       goto done;
+               }
+
+               compfp = fopen(compfilename, "r");
+               if (!compfp) {
+                       errstr = "\nerror: open() on gzip data failed";
+                       goto done;
+               }
+               if (stat(compfilename, &st)) {
+                       errstr = "\nerror: stat() on gzip file failed";
+                       goto done;
+               }
+               compressed = xmalloc(st.st_size);
+               if (fread(compressed, st.st_size, 1, compfp) != 1) {
+                       errstr = "\nerror: reading gzip data failed";
+                       goto done;
+               }
+               fclose(compfp);
+
+               unlink(compfilename);
+
+               dataptr = compressed;
+               count = st.st_size;
+               fprintf(file, "#define EASYLOGO_ENABLE_%s %i\n\n", comp_name, count);
+               if (bss_storage)
+                       fprintf (file, "static unsigned char EASYLOGO_DECOMP_BUFFER[%i];\n\n", image->size);
+
+ done:
+               free(compfilename);
+               free(compcmd);
+
+               if (errstr) {
+                       perror (errstr);
+                       return -1;
+               }
+       }
+
        /*      Headers */
        fprintf (file, "#include <video_easylogo.h>\n\n");
        /*      Macros */
@@ -303,8 +427,8 @@ int image_save_header (image_t * image, char *filename, char *varname)
        fprintf (file, "#define DEF_%s_SIZE\t\t%d\n\n", def_name,
                 image->size);
        /*  Declaration */
-       fprintf (file, "unsigned char DEF_%s_DATA[DEF_%s_SIZE] = {\n",
-                def_name, def_name);
+       fprintf (file, "unsigned char DEF_%s_DATA[] = {\n",
+                def_name);
 
        /*      Data */
        while (count)
@@ -335,7 +459,7 @@ int image_save_header (image_t * image, char *filename, char *varname)
        if (col)
                fprintf (file, "%s\n", str);
 
-       /*      End of declaration */
+       /*      End of declaration */
        fprintf (file, "};\n\n");
        /*      Variable */
        fprintf (file, "fastimage_t %s = {\n", varname);
@@ -353,84 +477,132 @@ int image_save_header (image_t * image, char *filename, char *varname)
 
 #define DEF_FILELEN    256
 
+static void usage (int exit_status)
+{
+       puts (
+               "EasyLogo 1.0 (C) 2000 by Paolo Scaffardi\n"
+               "\n"
+               "Syntax:        easylogo [options] inputfile [outputvar [outputfile]]\n"
+               "\n"
+               "Options:\n"
+               "  -r     Output RGB888 instead of YUYV\n"
+               "  -s     Output RGB565 instead of YUYV\n"
+               "  -g     Compress with gzip\n"
+               "  -l     Compress with lzma\n"
+               "  -b     Preallocate space in bss for decompressing image\n"
+               "  -h     Help output\n"
+               "\n"
+               "Where: 'inputfile'   is the TGA image to load\n"
+               "       'outputvar'   is the variable name to create\n"
+               "       'outputfile'  is the output header file (default is 'inputfile.h')"
+       );
+       exit (exit_status);
+}
+
 int main (int argc, char *argv[])
 {
+       int c;
+       bool use_rgb888 = false;
+       bool use_rgb565 = false;
        char inputfile[DEF_FILELEN],
                outputfile[DEF_FILELEN], varname[DEF_FILELEN];
 
-       image_t rgb_logo, yuyv_logo;
-
-       switch (argc) {
-       case 2:
-       case 3:
-       case 4:
-               strcpy (inputfile, argv[1]);
+       image_t rgb888_logo, rgb565_logo, yuyv_logo;
 
-               if (argc > 2)
-                       strcpy (varname, argv[2]);
-               else {
-                       char *dot = strchr (inputfile, '.');
-                       int pos = dot - inputfile;
-
-                       if (dot) {
-                               strncpy (varname, inputfile, pos);
-                               varname[pos] = 0;
-                       }
-               }
-
-               if (argc > 3)
-                       strcpy (outputfile, argv[3]);
-               else {
-                       char *dot = strchr (varname, '.');
-                       int pos = dot - varname;
-
-                       if (dot) {
-                               char app[DEF_FILELEN];
-
-                               strncpy (app, varname, pos);
-                               app[pos] = 0;
-                               sprintf (outputfile, "%s.h", app);
-                       }
+       while ((c = getopt(argc, argv, "hrsglb")) > 0) {
+               switch (c) {
+               case 'h':
+                       usage (0);
+                       break;
+               case 'r':
+                       use_rgb888 = true;
+                       puts("Using 24-bit RGB888 Output Fromat");
+                       break;
+               case 's':
+                       use_rgb565 = true;
+                       puts("Using 16-bit RGB565 Output Fromat");
+                       break;
+               case 'g':
+                       compression = COMP_GZIP;
+                       puts("Compressing with gzip");
+                       break;
+               case 'l':
+                       compression = COMP_LZMA;
+                       puts("Compressing with lzma");
+                       break;
+               case 'b':
+                       bss_storage = true;
+                       puts("Preallocating bss space for decompressing image");
+                       break;
+               default:
+                       usage (1);
+                       break;
                }
-               break;
-
-       default:
-               printf ("EasyLogo 1.0 (C) 2000 by Paolo Scaffardi\n\n");
+       }
 
-               printf("Syntax: easylogo inputfile [outputvar {outputfile}] \n");
-               printf("\n");
-               printf("Where:  'inputfile'     is the TGA image to load\n");
-               printf("        'outputvar'     is the variable name to create\n");
-               printf("        'outputfile'    is the output header file (default is 'inputfile.h')\n");
+       c = argc - optind;
+       if (c > 4 || c < 1)
+               usage (1);
+
+       strcpy (inputfile, argv[optind]);
+
+       if (c > 1)
+               strcpy (varname, argv[optind + 1]);
+       else {
+               /* transform "input.tga" to just "input" */
+               char *dot;
+               strcpy (varname, inputfile);
+               dot = strchr (varname, '.');
+               if (dot)
+                       *dot = '\0';
+       }
 
-               return -1;
+       if (c > 2)
+               strcpy (outputfile, argv[optind + 2]);
+       else {
+               /* just append ".h" to input file name */
+               strcpy (outputfile, inputfile);
+               strcat (outputfile, ".h");
        }
 
+       /* Make sure the output is sent as soon as we printf() */
+       setbuf(stdout, NULL);
+
        printf ("Doing '%s' (%s) from '%s'...",
                outputfile, varname, inputfile);
 
        /* Import TGA logo */
 
        printf ("L");
-       if (image_load_tga (&rgb_logo, inputfile) < 0) {
+       if (image_load_tga(&rgb888_logo, inputfile) < 0) {
                printf ("input file not found!\n");
                exit (1);
        }
 
-       /* Convert it to YUYV format */
-
-       printf ("C");
-       image_rgb_to_yuyv (&rgb_logo, &yuyv_logo);
-
-       /* Save it into a header format */
-
-       printf ("S");
-       image_save_header (&yuyv_logo, outputfile, varname);
+       /* Convert, save, and free the image */
+
+       if (!use_rgb888 && !use_rgb565) {
+               printf ("C");
+               image_rgb_to_yuyv(&rgb888_logo, &yuyv_logo);
+
+               printf("S");
+               image_save_header(&yuyv_logo, outputfile, varname);
+               image_free(&yuyv_logo);
+       } else if (use_rgb565) {
+               printf("C");
+               image_rgb888_to_rgb565(&rgb888_logo, &rgb565_logo);
+
+               printf("S");
+               image_save_header(&rgb565_logo, outputfile, varname);
+               image_free(&rgb565_logo);
+       } else {
+               printf("S");
+               image_save_header(&rgb888_logo, outputfile, varname);
+       }
 
        /* Free original image and copy */
 
-       image_free (&rgb_logo);
-       image_free (&yuyv_logo);
+       image_free(&rgb888_logo);
 
        printf ("\n");