easylogo: add optional gzip support
authorMike Frysinger <vapier@gentoo.org>
Tue, 30 Dec 2008 08:15:38 +0000 (03:15 -0500)
committerWolfgang Denk <wd@denx.de>
Sat, 24 Jan 2009 01:05:22 +0000 (02:05 +0100)
Some images can be quite large, so add an option to compress the
image data with gzip in the U-Boot image. Then at runtime, the
board can decompress it with the normal zlib functions.

Signed-off-by: Mike Frysinger <vapier@gentoo.org>
tools/easylogo/easylogo.c

index 00a1e4ed1675ccedbee5a203e1ad68c6610c672a..41e583852f0d2227a1389a84dc2fc8e55e741ce9 100644 (file)
@@ -3,15 +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)
 
@@ -49,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);
@@ -171,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);
@@ -192,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;
@@ -239,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;
 
@@ -261,6 +276,8 @@ int image_rgb_to_yuyv (image_t * rgb_image, image_t * yuyv_image)
        return 0;
 }
 
+int use_gzip = 0;
+
 int image_save_header (image_t * image, char *filename, char *varname)
 {
        FILE *file = fopen (filename, "w");
@@ -283,6 +300,65 @@ 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");
 
+       /*  gzip compress */
+       if (use_gzip & 0x1) {
+               const char *errstr = NULL;
+               unsigned char *compressed;
+               struct stat st;
+               FILE *gz;
+               char *gzfilename = xmalloc(strlen (filename) + 20);
+               char *gzcmd = xmalloc(strlen (filename) + 20);
+
+               sprintf (gzfilename, "%s.gz", filename);
+               sprintf (gzcmd, "gzip > %s", gzfilename);
+               gz = popen (gzcmd, "w");
+               if (!gz) {
+                       errstr = "\nerror: popen() failed";
+                       goto done;
+               }
+               if (fwrite (image->data, image->size, 1, gz) != 1) {
+                       errstr = "\nerror: writing data to gzip failed";
+                       goto done;
+               }
+               if (pclose (gz)) {
+                       errstr = "\nerror: gzip process failed";
+                       goto done;
+               }
+
+               gz = fopen (gzfilename, "r");
+               if (!gz) {
+                       errstr = "\nerror: open() on gzip data failed";
+                       goto done;
+               }
+               if (stat (gzfilename, &st)) {
+                       errstr = "\nerror: stat() on gzip file failed";
+                       goto done;
+               }
+               compressed = xmalloc (st.st_size);
+               if (fread (compressed, st.st_size, 1, gz) != 1) {
+                       errstr = "\nerror: reading gzip data failed";
+                       goto done;
+               }
+               fclose (gz);
+
+               unlink (gzfilename);
+
+               dataptr = compressed;
+               count = st.st_size;
+               fprintf (file, "#define EASYLOGO_ENABLE_GZIP %i\n\n", count);
+               if (use_gzip & 0x2)
+                       fprintf (file, "static unsigned char EASYLOGO_DECOMP_BUFFER[%i];\n\n", image->size);
+
+ done:
+               free (gzfilename);
+               free (gzcmd);
+
+               if (errstr) {
+                       perror (errstr);
+                       return -1;
+               }
+       }
+
        /*      Headers */
        fprintf (file, "#include <video_easylogo.h>\n\n");
        /*      Macros */
@@ -300,8 +376,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)
@@ -359,6 +435,8 @@ static void usage (int exit_status)
                "\n"
                "Options:\n"
                "  -r     Output RGB instead of YUYV\n"
+               "  -g     Compress with gzip\n"
+               "  -b     Preallocate space in bss for decompressing image\n"
                "  -h     Help output\n"
                "\n"
                "Where: 'inputfile'   is the TGA image to load\n"
@@ -377,7 +455,7 @@ int main (int argc, char *argv[])
 
        image_t rgb_logo, yuyv_logo;
 
-       while ((c = getopt(argc, argv, "hr")) > 0) {
+       while ((c = getopt(argc, argv, "hrgb")) > 0) {
                switch (c) {
                case 'h':
                        usage (0);
@@ -386,6 +464,14 @@ int main (int argc, char *argv[])
                        use_rgb = true;
                        puts ("Using 24-bit RGB Output Fromat");
                        break;
+               case 'g':
+                       use_gzip |= 0x1;
+                       puts ("Compressing with gzip");
+                       break;
+               case 'b':
+                       use_gzip |= 0x2;
+                       puts ("Preallocating bss space for decompressing image");
+                       break;
                default:
                        usage (1);
                        break;