We've found that loader_bmp.c in imlib2 1.4.0 does not correctly handle
RGB565 Windows BMPs (compression method BI_BITFIELDS), nor does it
correctly shift the bits for RGB555 images into the MSBs of the 32 bit
output format.

The attached patch corrects loader_bmp.c's handling of 16 bit Windows
BMPs by doing the following:

* Introduce a left shift for each of the three colour components in
16-bit images
* Set this left shift to 3 for each colour component in RGB555 images
* For "bitfields" images (RGB565, for example), determine the value of
left shift by masking and shifting 0xFFFF until the byte value of the
component has the MSB set.
* When reading components, left shift them appropriately, to make the
byte values the MSBs of the output colour components.

We've also noticed that 16 bit BMP handling depends on a little-endian
processor; this is fine for us, so I've not fixed it, but if
endian-independence is a goal, the code underneath "THIS WAS OLD CODE"
needs re-evaluating (casting unsigned char * to unsigned short *, then
deferencing the pix pointer assumes that we're on a little-endian system).

I'm not subscribed to the list, so please CC me on any replies.
--
Thanks,

Simon Farnsworth


diff -urNp imlib2-1.4.0.orig/src/modules/loaders/loader_bmp.c imlib2-1.4.0/src/modules/loaders/loader_bmp.c
--- imlib2-1.4.0.orig/src/modules/loaders/loader_bmp.c	2007-04-09 23:40:40.000000000 +0100
+++ imlib2-1.4.0/src/modules/loaders/loader_bmp.c	2007-05-11 15:26:36.000000000 +0100
@@ -120,6 +120,7 @@ load(ImlibImage * im, ImlibProgressFunct
    RGBQUAD             rgbQuads[256];
    unsigned long       rmask = 0xff, gmask = 0xff, bmask = 0xff;
    unsigned long       rshift = 0, gshift = 0, bshift = 0;
+   unsigned long       rleftshift = 0, gleftshift = 0, bleftshift = 0;
 
    /*
     * 21.3.2006:
@@ -221,16 +222,28 @@ load(ImlibImage * im, ImlibProgressFunct
              {
                 int                 bit;
 
-                ReadleLong(f, &bmask);
-                ReadleLong(f, &gmask);
                 ReadleLong(f, &rmask);
+                ReadleLong(f, &gmask);
+                ReadleLong(f, &bmask);
                 for (bit = bitcount - 1; bit >= 0; bit--)
                   {
                      if (bmask & (1 << bit)) bshift = bit;
                      if (gmask & (1 << bit)) gshift = bit;
                      if (rmask & (1 << bit)) rshift = bit;
                   }
-             }
+                while(((((0xffffL & bmask) >> bshift) << bleftshift) & 0x80) == 0)
+                  {
+                     bleftshift++;
+                  }
+                while(((((0xffffL & gmask) >> gshift) << gleftshift) & 0x80) == 0)
+                  {
+                     gleftshift++;
+                  }
+                while(((((0xffffL & rmask) >> rshift) << rleftshift) & 0x80) == 0)
+                  {
+                     rleftshift++;
+                  }
+              }
            else if (bitcount == 16)
              {
                 rmask = 0x7C00;
@@ -239,6 +252,7 @@ load(ImlibImage * im, ImlibProgressFunct
                 rshift = 10;
                 gshift = 5;
                 bshift = 0;
+                rleftshift = gleftshift = bleftshift = 3;
              }
            else if (bitcount == 32)
              {
@@ -656,13 +670,10 @@ load(ImlibImage * im, ImlibProgressFunct
                         *   bshift;
                         * *ptr++ = 0xff000000 | (r << 16) | (g << 8) | b;
                         */
-                       /* TODO: I don't know if [rgb]shift are calculated correctly, because we
-                        * 16 bit depth losses some values (bits).
-                        */
                        unsigned short pix = *(unsigned short *)buffer_ptr;
-                       *ptr++ = 0xff000000 | (((pix & rmask) >> rshift) << 16) |
-                                             (((pix & gmask) >> gshift) <<  8) |
-                                             (((pix & bmask) >> bshift)      ) ;
+                       *ptr++ = 0xff000000 | ((((pix & rmask) >> rshift) << rleftshift) << 16) |
+                                             ((((pix & gmask) >> gshift) << gleftshift) <<  8) |
+                                             ((((pix & bmask) >> bshift) << bleftshift)      ) ;
                        buffer_ptr += 2;
                     }
                   ptr -= w * 2;
diff -urNp imlib2-1.4.0.orig/src/modules/loaders/loader_bmp.c imlib2-1.4.0/src/modules/loaders/loader_bmp.c
--- imlib2-1.4.0.orig/src/modules/loaders/loader_bmp.c	2007-04-09 23:40:40.000000000 +0100
+++ imlib2-1.4.0/src/modules/loaders/loader_bmp.c	2007-05-11 15:26:36.000000000 +0100
@@ -120,6 +120,7 @@ load(ImlibImage * im, ImlibProgressFunct
    RGBQUAD             rgbQuads[256];
    unsigned long       rmask = 0xff, gmask = 0xff, bmask = 0xff;
    unsigned long       rshift = 0, gshift = 0, bshift = 0;
+   unsigned long       rleftshift = 0, gleftshift = 0, bleftshift = 0;
 
    /*
     * 21.3.2006:
@@ -221,16 +222,28 @@ load(ImlibImage * im, ImlibProgressFunct
              {
                 int                 bit;
 
-                ReadleLong(f, &bmask);
-                ReadleLong(f, &gmask);
                 ReadleLong(f, &rmask);
+                ReadleLong(f, &gmask);
+                ReadleLong(f, &bmask);
                 for (bit = bitcount - 1; bit >= 0; bit--)
                   {
                      if (bmask & (1 << bit)) bshift = bit;
                      if (gmask & (1 << bit)) gshift = bit;
                      if (rmask & (1 << bit)) rshift = bit;
                   }
-             }
+                while(((((0xffffL & bmask) >> bshift) << bleftshift) & 0x80) == 0)
+                  {
+                     bleftshift++;
+                  }
+                while(((((0xffffL & gmask) >> gshift) << gleftshift) & 0x80) == 0)
+                  {
+                     gleftshift++;
+                  }
+                while(((((0xffffL & rmask) >> rshift) << rleftshift) & 0x80) == 0)
+                  {
+                     rleftshift++;
+                  }
+              }
            else if (bitcount == 16)
              {
                 rmask = 0x7C00;
@@ -239,6 +252,7 @@ load(ImlibImage * im, ImlibProgressFunct
                 rshift = 10;
                 gshift = 5;
                 bshift = 0;
+                rleftshift = gleftshift = bleftshift = 3;
              }
            else if (bitcount == 32)
              {
@@ -656,13 +670,10 @@ load(ImlibImage * im, ImlibProgressFunct
                         *   bshift;
                         * *ptr++ = 0xff000000 | (r << 16) | (g << 8) | b;
                         */
-                       /* TODO: I don't know if [rgb]shift are calculated correctly, because we
-                        * 16 bit depth losses some values (bits).
-                        */
                        unsigned short pix = *(unsigned short *)buffer_ptr;
-                       *ptr++ = 0xff000000 | (((pix & rmask) >> rshift) << 16) |
-                                             (((pix & gmask) >> gshift) <<  8) |
-                                             (((pix & bmask) >> bshift)      ) ;
+                       *ptr++ = 0xff000000 | ((((pix & rmask) >> rshift) << rleftshift) << 16) |
+                                             ((((pix & gmask) >> gshift) << gleftshift) <<  8) |
+                                             ((((pix & bmask) >> bshift) << bleftshift)      ) ;
                        buffer_ptr += 2;
                     }
                   ptr -= w * 2;

-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
enlightenment-devel mailing list
enlightenment-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/enlightenment-devel

Reply via email to