Author: spouliot
Date: 2007-01-17 15:03:33 -0500 (Wed, 17 Jan 2007)
New Revision: 71226

Modified:
   trunk/libgdiplus/src/ChangeLog
   trunk/libgdiplus/src/bmpcodec.c
   trunk/libgdiplus/src/bmpcodec.h
Log:
2007-01-17  Sebastien Pouliot  <[EMAIL PROTECTED]> 

        * bmpcodec.c: Add support for loading 16bpp bitmaps (555 or 565).
        Cairo deprecated CAIRO_FORMAT_RGB16_565 so we promote the bitmaps
        into 24bpp RGB bitmaps.
        * bmpcodec.h: Add new structures for V4 bitmap headers.



Modified: trunk/libgdiplus/src/ChangeLog
===================================================================
--- trunk/libgdiplus/src/ChangeLog      2007-01-17 19:15:13 UTC (rev 71225)
+++ trunk/libgdiplus/src/ChangeLog      2007-01-17 20:03:33 UTC (rev 71226)
@@ -1,3 +1,10 @@
+2007-01-17  Sebastien Pouliot  <[EMAIL PROTECTED]> 
+
+       * bmpcodec.c: Add support for loading 16bpp bitmaps (555 or 565).
+       Cairo deprecated CAIRO_FORMAT_RGB16_565 so we promote the bitmaps
+       into 24bpp RGB bitmaps.
+       * bmpcodec.h: Add new structures for V4 bitmap headers.
+
 2007-01-17  Sebastien Pouliot  <[EMAIL PROTECTED]>
 
        * bmpcodec.c: Avoid potential double-free if the image is invalid.

Modified: trunk/libgdiplus/src/bmpcodec.c
===================================================================
--- trunk/libgdiplus/src/bmpcodec.c     2007-01-17 19:15:13 UTC (rev 71225)
+++ trunk/libgdiplus/src/bmpcodec.c     2007-01-17 20:03:33 UTC (rev 71226)
@@ -75,51 +75,50 @@
         return &bmp_codec; 
 }
 
-int
-gdip_get_pixelformat (WORD bitcount)
+GpStatus
+gdip_get_bmp_pixelformat (BITMAPINFOHEADER *bih, PixelFormat *dest)
 {
-        switch (bitcount) {
-        case 32:
-                return Format32bppRgb;
-        case 24:
-                return Format24bppRgb;
-        case 8:
-                return Format8bppIndexed;
-        case 4:
-                return Format4bppIndexed;
-       case 1:
-               return Format1bppIndexed;
-        default:
-                return 0;
-        }  
-}
+       int bitCount = bih->biBitCount;
+       int compression = bih->biCompression;
 
-GpStatus
-gdip_get_bmp_pixelformat (int bitCount, int compression, PixelFormat *dest)
-{
-       switch (compression)
-       {
-               case BI_RLE4:
-               {
-                       if (bitCount != 4)
-                               return InvalidParameter;
-                       *dest = Format4bppIndexed;
+       switch (compression) {
+       case BI_RLE4:
+               if (bitCount != 4)
+                       return InvalidParameter;
+               *dest = Format4bppIndexed;
+               break;
+       case BI_RLE8:
+               if (bitCount != 8)
+                       return InvalidParameter;
+               *dest = Format8bppIndexed;
+               break;
+       case BI_BITFIELDS:
+               if (bitCount != 16)
+                       return InvalidParameter;
+               /* note: incomplete at this stage */
+               *dest = Format16bppRgb565;
+               break;
+       default:
+               switch (bitCount) {
+               case 32:
+                       *dest = Format32bppRgb;
                        break;
-               }
-               case BI_RLE8:
-               {
-                       if (bitCount != 8)
-                               return InvalidParameter;
-                       *dest = Format8bppIndexed;
+               case 24:
+                       *dest = Format24bppRgb;
                        break;
-               }
-               default:
-               {
-                       *dest = gdip_get_pixelformat (bitCount);
-                       if (0 == *dest) /* invalid pixel format */
-                               return InvalidParameter;
+               case 8:
+                       *dest = Format8bppIndexed;
                        break;
-               }
+               case 4:
+                       *dest = Format4bppIndexed;
+                       break;
+               case 1:
+                       *dest = Format1bppIndexed;
+                       break;
+               default:
+                       g_warning ("Unsupported bitcount (%d) and/or 
compression (%d).", bitCount, compression);
+                       return InvalidParameter;
+               }  
        }
 
        return Ok;
@@ -798,6 +797,11 @@
        int             loop;
        long            index;
        GpStatus        status;
+       ARGB alpha_mask = 0;
+       ARGB red_mask = 0;
+       ARGB green_mask = 0;
+       ARGB blue_mask = 0;
+       int red_shift = 0;
                
        size = sizeof(bmfh);
        data_read = (byte*) GdipAlloc(size);
@@ -831,13 +835,57 @@
 
        colours = (bmi.biClrUsed == 0 && bmi.biBitCount <= 8) ? (1 << 
bmi.biBitCount) : bmi.biClrUsed;
 
-       status = gdip_get_bmp_pixelformat (bmi.biBitCount, bmi.biCompression, 
&format);
+       status = gdip_get_bmp_pixelformat (&bmi, &format);
 
        if (status != Ok) {
                 /* bit count mismatch */
                goto error;
        }
-        
+
+       /* for 16bbp images we need to be more precise */
+       if (format == Format16bppRgb565) {
+               /* check if we're dealing with a BITMAPV4HEADER (or later) 
structure */
+               if (bmi.biSize >= sizeof (BITMAPV4HEADER)) {
+                       /* the new structure contains the ARGB masks */
+                       void *p = &bmi;
+                       BITMAPV4HEADER *v4 = p;
+                       alpha_mask = v4->bV4AlphaMask;
+                       red_mask = v4->bV4RedMask;
+                       green_mask = v4->bV4GreenMask;
+                       blue_mask = v4->bV4BlueMask;
+               } else if (bmi.biSize == sizeof (BITMAPINFOHEADER)) {
+                       // next three DWORD are the R,G,B masks, like bmiColors 
in BITMAPINFO
+                       int size = sizeof (RGBQUAD);
+                       size_read = gdip_read_bmp_data (pointer, 
(void*)&red_mask, size, useFile);
+                       if (size_read != size)
+                               goto error;
+                       size_read = gdip_read_bmp_data (pointer, 
(void*)&green_mask, size, useFile);
+                       if (size_read != size)
+                               goto error;
+                       size_read = gdip_read_bmp_data (pointer, 
(void*)&blue_mask, size, useFile);
+                       if (size_read != size)
+                               goto error;
+               }
+
+               if ((red_mask == 0x7C00) && (green_mask == 0x3E0) && (blue_mask 
== 0x1F)) {
+                       /* five red bits, five green bits and five blue bits 
(0x7FFF) */
+                       red_shift = 10;
+               } else if ((red_mask == 63488) && (green_mask == 2016) && 
(blue_mask == 31)) {
+                       /* five red bits, six green bits and five blue bits 
(0xFFFF) */
+                       red_shift = 11;
+               } else {
+                       g_warning ("Unsupported 16bbp format with masks A %d, 
R: %d, G %d, B %d", 
+                               alpha_mask, red_mask, green_mask, blue_mask);
+                       status = InvalidParameter;
+                       goto error;
+               }
+
+               /* note: CAIRO_FORMAT_RGB16_565 is deprecated so we're 
promoting the bitmap to 24RGB */
+               format = Format24bppRgb;
+               /* 16bbp bitmap don't seems reversed like their height 
indicates */
+               upsidedown = FALSE;
+       }
+
        result = gdip_bitmap_new_with_frame (NULL, TRUE);
        result->type = imageBitmap;
        result->image_format = BMP;
@@ -846,15 +894,23 @@
        result->active_bitmap->height = bmi.biHeight;
 
        switch (result->active_bitmap->pixel_format) {
-               case Format1bppIndexed: result->active_bitmap->stride = 
(result->active_bitmap->width + 7) / 8; break;
-               case Format4bppIndexed: result->active_bitmap->stride = 
(result->active_bitmap->width + 1) / 2; break;
-               case Format8bppIndexed: result->active_bitmap->stride =  
result->active_bitmap->width;          break;
-               case Format24bppRgb: result->active_bitmap->stride = 
result->active_bitmap->width * 4;          break;
-               default:
-                       /* For other types, we assume 32 bit and translate into 
32 bit from source format */
-                       result->active_bitmap->pixel_format = Format32bppRgb;
-                       result->active_bitmap->stride = 
result->active_bitmap->width * 4;
-                       break;
+       case Format1bppIndexed:
+               result->active_bitmap->stride = (result->active_bitmap->width + 
7) / 8;
+               break;
+       case Format4bppIndexed:
+               result->active_bitmap->stride = (result->active_bitmap->width + 
1) / 2;
+               break;
+       case Format8bppIndexed:
+               result->active_bitmap->stride =  result->active_bitmap->width;
+               break;
+       case Format24bppRgb:
+               result->active_bitmap->stride = result->active_bitmap->width * 
4;
+               break;
+       default:
+               /* For other types, we assume 32 bit and translate into 32 bit 
from source format */
+               result->active_bitmap->pixel_format = Format32bppRgb;
+               result->active_bitmap->stride = result->active_bitmap->width * 
4;
+               break;
        }
 
        /* Ensure pixman_bits_t alignment */
@@ -975,6 +1031,24 @@
                                case 8: memcpy(pixels + line * 
result->active_bitmap->stride, data_read, size);
                                        continue;
 
+                               case 16: {
+                                       int src = 0;
+                                       int dest = 0;
+                                       SHORT *pix = (SHORT*) data_read;
+
+                                       index = (line * 
result->active_bitmap->stride);
+                                       while (src < loop) {
+                                               BYTE r = ((*pix & red_mask) >> 
(red_shift - 3));
+                                               BYTE g = ((*pix & green_mask) 
>> (red_shift - 8));
+                                               BYTE b = (*pix & blue_mask) << 
3;
+                                               set_pixel_bgra (pixels, index + 
dest, b, g, r, 0xff);
+                                               dest += 4;
+                                               src += 2;
+                                               pix++;
+                                       }
+                                       continue;
+                               }
+
                                case 24: {
                                        int src = 0;
                                        int dest = 0;

Modified: trunk/libgdiplus/src/bmpcodec.h
===================================================================
--- trunk/libgdiplus/src/bmpcodec.h     2007-01-17 19:15:13 UTC (rev 71225)
+++ trunk/libgdiplus/src/bmpcodec.h     2007-01-17 20:03:33 UTC (rev 71226)
@@ -16,6 +16,7 @@
 #define BI_RGB           0
 #define BI_RLE8          1
 #define BI_RLE4          2
+#define BI_BITFIELDS     3
 
 #define BITMAPINFOHEADER_SIZE   40
 #define BITMAPCOREHEADER_SIZE   12
@@ -45,8 +46,7 @@
   BYTE rgbReserved;
 } RGBQUAD, *LPRGBQUAD;
 
-typedef struct
-{
+typedef struct {
     DWORD      biSize;
     LONG       biWidth;
     LONG       biHeight;
@@ -60,7 +60,44 @@
     DWORD      biClrImportant;
 } BITMAPINFOHEADER, *PBITMAPINFOHEADER, *LPBITMAPINFOHEADER;
 
+typedef long FXPT2DOT30;
+
 typedef struct {
+       FXPT2DOT30      ciexyzX;
+       FXPT2DOT30      ciexyzY;
+       FXPT2DOT30      ciexyzZ;
+} CIEXYZ;
+
+typedef struct {
+       CIEXYZ  ciexyzRed;
+       CIEXYZ  ciexyzGreen;
+       CIEXYZ  ciexyzBlue;
+} CIEXYZTRIPLE;
+
+typedef struct {
+       DWORD   bV4Size;
+       LONG    bV4Width;
+       LONG    bV4Height;
+       WORD    bV4Planes;
+       WORD    bV4BitCount;
+       DWORD   bV4Compression;
+       DWORD   bV4SizeImage;
+       LONG    bV4XPelsPerMeter;
+       LONG    bV4YPelsPerMeter;
+       DWORD   bV4ClrUsed;
+       DWORD   bV4ClrImportant;
+       DWORD   bV4RedMask;
+       DWORD   bV4GreenMask;
+       DWORD   bV4BlueMask;
+       DWORD   bV4AlphaMask;
+       DWORD   bV4CSType;
+       CIEXYZTRIPLE    bV4Endpoints;
+       DWORD   bV4GammaRed;
+       DWORD   bV4GammaGreen;
+       DWORD   bV4GammaBlue;
+} BITMAPV4HEADER, *PBITMAPV4HEADER;
+
+typedef struct {
        BITMAPINFOHEADER bmiHeader;
        RGBQUAD bmiColors[1];
 } BITMAPINFO, *PBITMAPINFO, *LPBITMAPINFO;

_______________________________________________
Mono-patches maillist  -  [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches

Reply via email to