I recently upgraded from libpng-1.2.18 to the newly released libpng-1.2.19 on my Intel Debian 4.0 box. Things seemed to work okay, except that grayscale images were rendered in shades of BLUE instead of shades of gray. [The same effect did *not* happen on a Sparc Solaris 8 box. It worked properly.] I ended up reworking the PNG transformation calls in the loader_png.c routine. It was primarily a re-ordering of the routines, to call them in the same order that they're described in the libpng documentation.

These changes appear to have resolved the problem. I've tested them on both the Intel Debian 4.0 box and the Sparc Solaris 8 box. Patched is attached. [The patch also contains spelling corrections and a couple of innocuous whitespace tweaks. I probably should have separated them into a separate patch, but I ran out of steam last night. Sorry.]

Brian Lindholm

diff -dru imlib2-1.4.0-orig/src/modules/loaders/loader_png.c imlib2-1.4.0/src/modules/loaders/loader_png.c
--- imlib2-1.4.0-orig/src/modules/loaders/loader_png.c	2007-04-09 18:40:40.000000000 -0400
+++ imlib2-1.4.0/src/modules/loaders/loader_png.c	2007-08-21 11:27:28.500001000 -0400
@@ -1,7 +1,7 @@
 #include "loader_common.h"
 #include <png.h>
 
-/* this is a quick sample png loader module... nice and small isnt it? */
+/* this is a quick sample png loader module... nice and small isn't it? */
 
 /* PNG stuff */
 #define PNG_BYTES_TO_CHECK 4
@@ -18,14 +18,14 @@
 {
    png_uint_32         w32, h32;
    int                 w, h;
-   char                hasa = 0, hasg = 0;
+   char                hasa = 0;
    FILE               *f;
    png_structp         png_ptr = NULL;
    png_infop           info_ptr = NULL;
    int                 bit_depth, color_type, interlace_type;
 
-   /* if immediate_load is 1, then dont delay image laoding as below, or */
-   /* already data in this image - dont load it again */
+   /* if immediate_load is 1, then don't delay image loading as below, or */
+   /* already data in this image - don't load it again */
    if (im->data)
       return 0;
    f = fopen(im->real_file, "rb");
@@ -36,7 +36,7 @@
      {
         unsigned char       buf[PNG_BYTES_TO_CHECK];
 
-        /* if we havent read the header before, set the header data */
+        /* if we haven't read the header before, set the header data */
         fread(buf, 1, PNG_BYTES_TO_CHECK, f);
         if (!png_check_sig(buf, PNG_BYTES_TO_CHECK))
           {
@@ -71,28 +71,19 @@
                      &interlace_type, NULL, NULL);
         im->w = (int)w32;
         im->h = (int)h32;
-	if ((w32 < 1) || (h32 < 1) || (w32 > 8192) || (h32 > 8192))
-	  {
+        if ((w32 < 1) || (h32 < 1) || (w32 > 8192) || (h32 > 8192))
+          {
              png_read_end(png_ptr, info_ptr);
              png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
              fclose(f);
              return 0;
-	  }
-        if (color_type == PNG_COLOR_TYPE_PALETTE)
-	  {
-	     png_set_expand(png_ptr);
-	     if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
-	       hasa = 1;
-	  }
-        if (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
-           hasa = 1;
-        if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
-          {
-             hasa = 1;
-             hasg = 1;
           }
-        if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY)
-           hasg = 1;
+        if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
+           hasa = 1;
+        if (color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+           hasa = 1;
+        if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+           hasa = 1;
         if (hasa)
            SET_FLAG(im->flags, F_HAS_ALPHA);
         else
@@ -112,27 +103,43 @@
 
         w = im->w;
         h = im->h;
-        if (hasa)
-           png_set_expand(png_ptr);
-        /* we want ARGB */
-/* note form raster:                                                         */
+
+        /* Prep for transformations...  ultimately we want ARGB */
+        /* expand palette -> RGB if necessary */
+        if (color_type == PNG_COLOR_TYPE_PALETTE)
+           png_set_palette_to_rgb(png_ptr);
+        /* expand gray (w/reduced bits) -> 8-bit RGB if necessary */
+        if ((color_type == PNG_COLOR_TYPE_GRAY) ||
+           (color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
+          {
+             png_set_gray_to_rgb(png_ptr);
+             if (bit_depth < 8)
+                png_set_expand_gray_1_2_4_to_8(png_ptr);
+          }
+        /* expand transparency entry -> alpha channel if present */
+        if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
+           png_set_tRNS_to_alpha(png_ptr);
+        /* reduce 16bit color -> 8bit color if necessary */
+        if (bit_depth > 8)
+           png_set_strip_16(png_ptr);
+        /* pack all pixels to byte boundaries */
+        png_set_packing(png_ptr);
+
+/* note from raster:                                                         */
 /* thanks to mustapha for helping debug this on PPC Linux remotely by        */
-/* sending across screenshots all the tiem and me figuring out form them     */
+/* sending across screenshots all the time and me figuring out from them     */
 /* what the hell was up with the colors                                      */
-/* now png loading shoudl work on big endian machines nicely                 */
+/* now png loading should work on big-endian machines nicely                 */
 #ifdef WORDS_BIGENDIAN
         png_set_swap_alpha(png_ptr);
-        png_set_filler(png_ptr, 0xff, PNG_FILLER_BEFORE);
+        if (!hasa)
+           png_set_filler(png_ptr, 0xff, PNG_FILLER_BEFORE);
 #else
         png_set_bgr(png_ptr);
-        png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
+        if (!hasa)
+           png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
 #endif
-        /* 16bit color -> 8bit color */
-        png_set_strip_16(png_ptr);
-        /* pack all pixels to byte boundaires */
-        png_set_packing(png_ptr);
-        if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
-           png_set_expand(png_ptr);
+
         if (im->data)
            free(im->data);
         im->data = malloc(w * h * sizeof(DATA32));
@@ -154,12 +161,6 @@
              fclose(f);
              return 0;
           }
-        if (hasg)
-          {
-             png_set_gray_to_rgb(png_ptr);
-             if (png_get_bit_depth(png_ptr, info_ptr) < 8)
-                png_set_gray_1_2_4_to_8(png_ptr);
-          }
         for (i = 0; i < h; i++)
            lines[i] = ((unsigned char *)(im->data)) + (i * w * sizeof(DATA32));
         if (progress)
@@ -276,11 +277,11 @@
    if ((tag = __imlib_GetTag(im, "interlacing")) && tag->val)
      {
 #ifdef PNG_WRITE_INTERLACING_SUPPORTED
-	  png_ptr->interlaced = PNG_INTERLACE_ADAM7;
-	  num_passes = png_set_interlace_handling(png_ptr);
+          png_ptr->interlaced = PNG_INTERLACE_ADAM7;
+          num_passes = png_set_interlace_handling(png_ptr);
 #endif
      }
-   
+
    png_init_io(png_ptr, f);
    if (im->flags & F_HAS_ALPHA)
      {
@@ -400,7 +401,7 @@
    return 1;
 }
 
-/* fills the ImlibLoader struct with a strign array of format file */
+/* fills the ImlibLoader struct with a string array of format file */
 /* extensions this loader can load. eg: */
 /* loader->formats = { "jpeg", "jpg"}; */
 /* giving permutations is a good idea. case sensitivity is irrelevant */
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >>  http://get.splunk.com/
_______________________________________________
enlightenment-devel mailing list
enlightenment-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/enlightenment-devel

Reply via email to