General tidy up of the MetaFile driver - make sure that everything
[wine] / objects / dib.c
1 /*
2  * GDI device-independent bitmaps
3  *
4  * Copyright 1993,1994  Alexandre Julliard
5  *
6  */
7
8 #include "bitmap.h"
9 #include "callback.h"
10 #include "dc.h"
11 #include "debug.h"
12 #include "monitor.h"
13 #include "palette.h"
14
15 DEFAULT_DEBUG_CHANNEL(bitmap)
16
17 /***********************************************************************
18  *           DIB_GetDIBWidthBytes
19  *
20  * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
21  * http://www.microsoft.com/msdn/sdk/platforms/doc/sdk/win32/struc/src/str01.htm
22  */
23 int DIB_GetDIBWidthBytes( int width, int depth )
24 {
25     int words;
26
27     switch(depth)
28     {
29         case 1:  words = (width + 31) / 32; break;
30         case 4:  words = (width + 7) / 8; break;
31         case 8:  words = (width + 3) / 4; break;
32         case 15:
33         case 16: words = (width + 1) / 2; break;
34         case 24: words = (width * 3 + 3)/4; break;
35
36         default:
37             WARN(bitmap, "(%d): Unsupported depth\n", depth );
38         /* fall through */
39         case 32:
40                 words = width;
41     }
42     return 4 * words;
43 }
44
45 /***********************************************************************
46  *           DIB_GetDIBImageBytes
47  *
48  * Return the number of bytes used to hold the image in a DIB bitmap.
49  */
50 int DIB_GetDIBImageBytes( int width, int height, int depth )
51 {
52     return DIB_GetDIBWidthBytes( width, depth ) * abs( height );
53 }
54
55
56 /***********************************************************************
57  *           DIB_BitmapInfoSize
58  *
59  * Return the size of the bitmap info structure including color table.
60  */
61 int DIB_BitmapInfoSize( const BITMAPINFO * info, WORD coloruse )
62 {
63     int colors;
64
65     if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
66     {
67         BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)info;
68         colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
69         return sizeof(BITMAPCOREHEADER) + colors *
70              ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
71     }
72     else  /* assume BITMAPINFOHEADER */
73     {
74         colors = info->bmiHeader.biClrUsed;
75         if (!colors && (info->bmiHeader.biBitCount <= 8))
76             colors = 1 << info->bmiHeader.biBitCount;
77         return sizeof(BITMAPINFOHEADER) + colors *
78                ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
79     }
80 }
81
82
83 /***********************************************************************
84  *           DIB_GetBitmapInfo
85  *
86  * Get the info from a bitmap header.
87  * Return 1 for INFOHEADER, 0 for COREHEADER, -1 for error.
88  */
89 int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, DWORD *width,
90                               int *height, WORD *bpp, WORD *compr )
91 {
92     if (header->biSize == sizeof(BITMAPINFOHEADER))
93     {
94         *width  = header->biWidth;
95         *height = header->biHeight;
96         *bpp    = header->biBitCount;
97         *compr  = header->biCompression;
98         return 1;
99     }
100     if (header->biSize == sizeof(BITMAPCOREHEADER))
101     {
102         BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)header;
103         *width  = core->bcWidth;
104         *height = core->bcHeight;
105         *bpp    = core->bcBitCount;
106         *compr  = 0;
107         return 0;
108     }
109     WARN(bitmap, "(%ld): wrong size for header\n", header->biSize );
110     return -1;
111 }
112
113
114 /***********************************************************************
115  *           StretchDIBits16   (GDI.439)
116  */
117 INT16 WINAPI StretchDIBits16(HDC16 hdc, INT16 xDst, INT16 yDst, INT16 widthDst,
118                        INT16 heightDst, INT16 xSrc, INT16 ySrc, INT16 widthSrc,
119                        INT16 heightSrc, const VOID *bits,
120                        const BITMAPINFO *info, UINT16 wUsage, DWORD dwRop )
121 {
122     return (INT16)StretchDIBits( hdc, xDst, yDst, widthDst, heightDst,
123                                    xSrc, ySrc, widthSrc, heightSrc, bits,
124                                    info, wUsage, dwRop );
125 }
126
127
128 /***********************************************************************
129  *           StretchDIBits32   (GDI32.351)
130  */
131 INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst,
132                        INT heightDst, INT xSrc, INT ySrc, INT widthSrc,
133                        INT heightSrc, const void *bits,
134                        const BITMAPINFO *info, UINT wUsage, DWORD dwRop )
135 {
136     DC *dc = DC_GetDCPtr( hdc );
137     if(!dc) return FALSE;
138
139     if(dc->funcs->pStretchDIBits)
140            return dc->funcs->pStretchDIBits(dc, xDst, yDst, widthDst, 
141                                             heightDst, xSrc, ySrc, widthSrc,
142                                             heightSrc, bits, info, wUsage,
143                                             dwRop);
144     else { /* use StretchBlt32 */
145         HBITMAP hBitmap, hOldBitmap;
146         HDC hdcMem;
147     
148         hBitmap = CreateDIBitmap( hdc, &info->bmiHeader, CBM_INIT,
149                                     bits, info, wUsage );
150         hdcMem = CreateCompatibleDC( hdc );
151         hOldBitmap = SelectObject( hdcMem, hBitmap );
152         /* Origin for DIBitmap is bottom left ! */
153         StretchBlt( hdc, xDst, yDst, widthDst, heightDst,
154                       hdcMem, xSrc, info->bmiHeader.biHeight - heightSrc - ySrc, 
155                       widthSrc, heightSrc, dwRop );
156         SelectObject( hdcMem, hOldBitmap );
157         DeleteDC( hdcMem );
158         DeleteObject( hBitmap );
159         return heightSrc;
160     }
161 }
162
163
164 /***********************************************************************
165  *           SetDIBits16    (GDI.440)
166  */
167 INT16 WINAPI SetDIBits16( HDC16 hdc, HBITMAP16 hbitmap, UINT16 startscan,
168                           UINT16 lines, LPCVOID bits, const BITMAPINFO *info,
169                           UINT16 coloruse )
170 {
171     return SetDIBits( hdc, hbitmap, startscan, lines, bits, info, coloruse );
172 }
173
174
175 /******************************************************************************
176  * SetDIBits32 [GDI32.312]  Sets pixels in a bitmap using colors from DIB
177  *
178  * PARAMS
179  *    hdc       [I] Handle to device context
180  *    hbitmap   [I] Handle to bitmap
181  *    startscan [I] Starting scan line
182  *    lines     [I] Number of scan lines
183  *    bits      [I] Array of bitmap bits
184  *    info      [I] Address of structure with data
185  *    coloruse  [I] Type of color indexes to use
186  *
187  * RETURNS
188  *    Success: Number of scan lines copied
189  *    Failure: 0
190  */
191 INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
192                       UINT lines, LPCVOID bits, const BITMAPINFO *info,
193                       UINT coloruse )
194 {
195     DC *dc;
196     BITMAPOBJ *bitmap;
197     INT result;
198
199     /* Check parameters */
200     dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
201     if (!dc) 
202     {
203         dc = (DC *) GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
204         if (!dc) return 0;
205     }
206
207     if (!(bitmap = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
208     {
209         GDI_HEAP_UNLOCK( hdc );
210         return 0;
211     }
212
213     result = BITMAP_Driver->pSetDIBits(bitmap, dc, startscan, 
214                                        lines, bits, info, 
215                                        coloruse, hbitmap);
216
217     GDI_HEAP_UNLOCK( hdc );
218     GDI_HEAP_UNLOCK( hbitmap );
219
220     return result;
221 }
222
223
224 /***********************************************************************
225  *           SetDIBitsToDevice16    (GDI.443)
226  */
227 INT16 WINAPI SetDIBitsToDevice16(HDC16 hdc, INT16 xDest, INT16 yDest, INT16 cx,
228                            INT16 cy, INT16 xSrc, INT16 ySrc, UINT16 startscan,
229                            UINT16 lines, LPCVOID bits, const BITMAPINFO *info,
230                            UINT16 coloruse )
231 {
232     return SetDIBitsToDevice( hdc, xDest, yDest, cx, cy, xSrc, ySrc,
233                                 startscan, lines, bits, info, coloruse );
234 }
235
236
237 /***********************************************************************
238  *           SetDIBitsToDevice32   (GDI32.313)
239  */
240 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
241                            DWORD cy, INT xSrc, INT ySrc, UINT startscan,
242                            UINT lines, LPCVOID bits, const BITMAPINFO *info,
243                            UINT coloruse )
244 {
245     INT ret;
246     DC *dc;
247
248     if (!(dc = DC_GetDCPtr( hdc ))) return 0;
249
250     if(dc->funcs->pSetDIBitsToDevice)
251         ret = dc->funcs->pSetDIBitsToDevice( dc, xDest, yDest, cx, cy, xSrc,
252                                              ySrc, startscan, lines, bits,
253                                              info, coloruse );
254     else {
255         FIXME(bitmap, "unimplemented on hdc %08x\n", hdc);
256         ret = 0;
257     }
258
259     GDI_HEAP_UNLOCK( hdc );
260     return ret;
261 }
262
263 /***********************************************************************
264  *           SetDIBColorTable16    (GDI.602)
265  */
266 UINT16 WINAPI SetDIBColorTable16( HDC16 hdc, UINT16 startpos, UINT16 entries,
267                                   RGBQUAD *colors )
268 {
269     return SetDIBColorTable( hdc, startpos, entries, colors );
270 }
271
272 /***********************************************************************
273  *           SetDIBColorTable32    (GDI32.311)
274  */
275 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries,
276                                   RGBQUAD *colors )
277 {
278     DC * dc;
279     PALETTEENTRY * palEntry;
280     PALETTEOBJ * palette;
281     RGBQUAD *end;
282
283     dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
284     if (!dc) 
285     {
286         dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
287         if (!dc) return 0;
288     }
289
290     if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->w.hPalette, PALETTE_MAGIC )))
291     {
292         return 0;
293     }
294
295     /* Transfer color info */
296     
297     if (dc->w.bitsPerPixel <= 8) {
298         palEntry = palette->logpalette.palPalEntry + startpos;
299         if (startpos + entries > (1 << dc->w.bitsPerPixel)) {
300             entries = (1 << dc->w.bitsPerPixel) - startpos;
301         }
302         for (end = colors + entries; colors < end; palEntry++, colors++)
303         {
304             palEntry->peRed   = colors->rgbRed;
305             palEntry->peGreen = colors->rgbGreen;
306             palEntry->peBlue  = colors->rgbBlue;
307         }
308     } else {
309         entries = 0;
310     }
311     GDI_HEAP_UNLOCK( dc->w.hPalette );
312     return entries;
313 }
314
315 /***********************************************************************
316  *           GetDIBColorTable16    (GDI.603)
317  */
318 UINT16 WINAPI GetDIBColorTable16( HDC16 hdc, UINT16 startpos, UINT16 entries,
319                                   RGBQUAD *colors )
320 {
321     return GetDIBColorTable( hdc, startpos, entries, colors );
322 }
323
324 /***********************************************************************
325  *           GetDIBColorTable32    (GDI32.169)
326  */
327 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries,
328                                   RGBQUAD *colors )
329 {
330     DC * dc;
331     PALETTEENTRY * palEntry;
332     PALETTEOBJ * palette;
333     RGBQUAD *end;
334
335     dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
336     if (!dc) 
337     {
338         dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
339         if (!dc) return 0;
340     }
341
342     if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->w.hPalette, PALETTE_MAGIC )))
343     {
344         return 0;
345     }
346
347     /* Transfer color info */
348     
349     if (dc->w.bitsPerPixel <= 8) {
350         palEntry = palette->logpalette.palPalEntry + startpos;
351         if (startpos + entries > (1 << dc->w.bitsPerPixel)) {
352             entries = (1 << dc->w.bitsPerPixel) - startpos;
353         }
354         for (end = colors + entries; colors < end; palEntry++, colors++)
355         {
356             colors->rgbRed      = palEntry->peRed;
357             colors->rgbGreen    = palEntry->peGreen;
358             colors->rgbBlue     = palEntry->peBlue;
359             colors->rgbReserved = 0;
360         }
361     } else {
362         entries = 0;
363     }
364     GDI_HEAP_UNLOCK( dc->w.hPalette );
365     return entries;
366 }
367
368 /* FIXME the following two structs should be combined with __sysPalTemplate in
369    objects/color.c - this should happen after de-X11-ing both of these
370    files.
371    NB. RGBQUAD and PALETTENTRY have different orderings of red, green
372    and blue - sigh */
373
374 static RGBQUAD EGAColors[16] = { 
375 /* rgbBlue, rgbGreen, rgbRed, rgbReserverd */
376     { 0x00, 0x00, 0x00, 0x00 },
377     { 0x00, 0x00, 0x80, 0x00 },
378     { 0x00, 0x80, 0x00, 0x00 },
379     { 0x00, 0x80, 0x80, 0x00 },
380     { 0x80, 0x00, 0x00, 0x00 },
381     { 0x80, 0x00, 0x80, 0x00 },
382     { 0x80, 0x80, 0x00, 0x00 },
383     { 0x80, 0x80, 0x80, 0x00 },
384     { 0xc0, 0xc0, 0xc0, 0x00 },
385     { 0x00, 0x00, 0xff, 0x00 },
386     { 0x00, 0xff, 0x00, 0x00 },
387     { 0x00, 0xff, 0xff, 0x00 },
388     { 0xff, 0x00, 0x00, 0x00 },
389     { 0xff, 0x00, 0xff, 0x00 },
390     { 0xff, 0xff, 0x00, 0x00 },
391     { 0xff, 0xff, 0xff, 0x00 }
392 };
393
394
395 static RGBQUAD DefLogPalette[20] = { /* Copy of Default Logical Palette */
396 /* rgbBlue, rgbGreen, rgbRed, rgbReserverd */
397     { 0x00, 0x00, 0x00, 0x00 },
398     { 0x00, 0x00, 0x80, 0x00 },
399     { 0x00, 0x80, 0x00, 0x00 },
400     { 0x00, 0x80, 0x80, 0x00 },
401     { 0x80, 0x00, 0x00, 0x00 },
402     { 0x80, 0x00, 0x80, 0x00 },
403     { 0x80, 0x80, 0x00, 0x00 },
404     { 0xc0, 0xc0, 0xc0, 0x00 },
405     { 0xc0, 0xdc, 0xc0, 0x00 },
406     { 0xf0, 0xca, 0xa6, 0x00 },
407     { 0xf0, 0xfb, 0xff, 0x00 },
408     { 0xa4, 0xa0, 0xa0, 0x00 },
409     { 0x80, 0x80, 0x80, 0x00 },
410     { 0x00, 0x00, 0xf0, 0x00 },
411     { 0x00, 0xff, 0x00, 0x00 },
412     { 0x00, 0xff, 0xff, 0x00 },
413     { 0xff, 0x00, 0x00, 0x00 },
414     { 0xff, 0x00, 0xff, 0x00 },
415     { 0xff, 0xff, 0x00, 0x00 },
416     { 0xff, 0xff, 0xff, 0x00 }
417 };
418
419 /***********************************************************************
420  *           GetDIBits16    (GDI.441)
421  */
422 INT16 WINAPI GetDIBits16( HDC16 hdc, HBITMAP16 hbitmap, UINT16 startscan,
423                           UINT16 lines, LPVOID bits, BITMAPINFO * info,
424                           UINT16 coloruse )
425 {
426     return GetDIBits( hdc, hbitmap, startscan, lines, bits, info, coloruse );
427 }
428
429
430 /******************************************************************************
431  * GetDIBits32 [GDI32.170]  Retrieves bits of bitmap and copies to buffer
432  *
433  * RETURNS
434  *    Success: Number of scan lines copied from bitmap
435  *    Failure: 0
436  *
437  * http://www.microsoft.com/msdn/sdk/platforms/doc/sdk/win32/func/src/f30_14.htm
438  */
439 INT WINAPI GetDIBits(
440     HDC hdc,         /* [in]  Handle to device context */
441     HBITMAP hbitmap, /* [in]  Handle to bitmap */
442     UINT startscan,  /* [in]  First scan line to set in dest bitmap */
443     UINT lines,      /* [in]  Number of scan lines to copy */
444     LPVOID bits,       /* [out] Address of array for bitmap bits */
445     BITMAPINFO * info, /* [out] Address of structure with bitmap data */
446     UINT coloruse)   /* [in]  RGB or palette index */
447 {
448     DC * dc;
449     BITMAPOBJ * bmp;
450     PALETTEENTRY * palEntry;
451     PALETTEOBJ * palette;
452     int i;
453
454     if (!lines) return 0;
455     if (!info) return 0;
456     dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
457     if (!dc) 
458     {
459         dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
460         if (!dc) return 0;
461     }
462     if (!(bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
463     {
464         GDI_HEAP_UNLOCK( hdc );
465         return 0;
466     }
467     if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->w.hPalette, PALETTE_MAGIC )))
468     {
469         GDI_HEAP_UNLOCK( hdc );
470         GDI_HEAP_UNLOCK( hbitmap );
471         return 0;
472     }
473
474     /* Transfer color info */
475
476     if (info->bmiHeader.biBitCount <= 8 && info->bmiHeader.biBitCount > 0 ) {
477
478         info->bmiHeader.biClrUsed = 0;
479
480         if(info->bmiHeader.biBitCount >= bmp->bitmap.bmBitsPixel) {
481             palEntry = palette->logpalette.palPalEntry;
482             for (i = 0; i < (1 << bmp->bitmap.bmBitsPixel); i++, palEntry++) {
483                 if (coloruse == DIB_RGB_COLORS) {
484                     info->bmiColors[i].rgbRed      = palEntry->peRed;
485                     info->bmiColors[i].rgbGreen    = palEntry->peGreen;
486                     info->bmiColors[i].rgbBlue     = palEntry->peBlue;
487                     info->bmiColors[i].rgbReserved = 0;
488                 }
489                 else ((WORD *)info->bmiColors)[i] = (WORD)i;
490             }
491         } else {
492             switch (info->bmiHeader.biBitCount) {
493             case 1:
494                 info->bmiColors[0].rgbRed = info->bmiColors[0].rgbGreen =
495                   info->bmiColors[0].rgbBlue = 0;
496                 info->bmiColors[0].rgbReserved = 0;
497                 info->bmiColors[1].rgbRed = info->bmiColors[1].rgbGreen =
498                   info->bmiColors[1].rgbBlue = 0xff;
499                 info->bmiColors[1].rgbReserved = 0;
500                 break;
501
502             case 4:
503                 memcpy(info->bmiColors, EGAColors, sizeof(EGAColors));
504                 break;
505
506             case 8:
507                 {
508                 INT r, g, b;
509                 RGBQUAD *color;
510
511                 memcpy(info->bmiColors, DefLogPalette,
512                        10 * sizeof(RGBQUAD));
513                 memcpy(info->bmiColors + 246, DefLogPalette + 10,
514                        10 * sizeof(RGBQUAD));
515                 color = info->bmiColors + 10;
516                 for(r = 0; r <= 5; r++) /* FIXME */
517                     for(g = 0; g <= 5; g++)
518                         for(b = 0; b <= 5; b++) {
519                             color->rgbRed =   (r * 0xff) / 5;
520                             color->rgbGreen = (g * 0xff) / 5;
521                             color->rgbBlue =  (b * 0xff) / 5;
522                             color->rgbReserved = 0;
523                             color++;
524                         }
525                 }
526             }
527         }
528     }
529
530     GDI_HEAP_UNLOCK( dc->w.hPalette );
531
532     if (bits)
533     {
534         if(!BITMAP_Driver->pGetDIBits(bmp, dc, startscan, lines, bits, info, coloruse, hbitmap))        
535         {
536             GDI_HEAP_UNLOCK( hdc );
537             GDI_HEAP_UNLOCK( hbitmap );
538
539             return FALSE;
540         }
541     }
542     else if( info->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) ) 
543     {
544         /* fill in struct members */
545
546         if( info->bmiHeader.biBitCount == 0)
547         {
548             info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
549             info->bmiHeader.biHeight = bmp->bitmap.bmHeight;
550             info->bmiHeader.biPlanes = 1;
551             info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
552             info->bmiHeader.biSizeImage = 
553                              DIB_GetDIBImageBytes( bmp->bitmap.bmWidth,
554                                                    bmp->bitmap.bmHeight,
555                                                    bmp->bitmap.bmBitsPixel );
556             info->bmiHeader.biCompression = 0;
557         }
558         else
559         {
560             info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(
561                                                info->bmiHeader.biWidth,
562                                                info->bmiHeader.biHeight,
563                                                info->bmiHeader.biBitCount );
564         }
565     }
566
567     TRACE(bitmap, "biSizeImage = %ld, biWidth = %ld, biHeight = %ld\n",
568           info->bmiHeader.biSizeImage, info->bmiHeader.biWidth,
569           info->bmiHeader.biHeight);
570
571     GDI_HEAP_UNLOCK( hdc );
572     GDI_HEAP_UNLOCK( hbitmap );
573
574     return lines;
575 }
576
577
578 /***********************************************************************
579  *           CreateDIBitmap16    (GDI.442)
580  */
581 HBITMAP16 WINAPI CreateDIBitmap16( HDC16 hdc, const BITMAPINFOHEADER * header,
582                             DWORD init, LPCVOID bits, const BITMAPINFO * data,
583                             UINT16 coloruse )
584 {
585     return CreateDIBitmap( hdc, header, init, bits, data, coloruse );
586 }
587
588
589 /***********************************************************************
590  *           CreateDIBitmap32    (GDI32.37)
591  */
592 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
593                             DWORD init, LPCVOID bits, const BITMAPINFO *data,
594                             UINT coloruse )
595 {
596     HBITMAP handle;
597     BOOL fColor;
598     DWORD width;
599     int height;
600     WORD bpp;
601     WORD compr;
602
603     if (DIB_GetBitmapInfo( header, &width, &height, &bpp, &compr ) == -1) return 0;
604     if (height < 0) height = -height;
605
606     /* Check if we should create a monochrome or color bitmap. */
607     /* We create a monochrome bitmap only if it has exactly 2  */
608     /* colors, which are either black or white, nothing else.  */
609     /* In all other cases, we create a color bitmap.           */
610
611     if (bpp != 1) fColor = TRUE;
612     else if ((coloruse != DIB_RGB_COLORS) ||
613              (init != CBM_INIT) || !data) fColor = FALSE;
614     else
615     {
616         if (data->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
617         {
618             RGBQUAD *rgb = data->bmiColors;
619             DWORD col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
620             if ((col == RGB(0,0,0)) || (col == RGB(0xff,0xff,0xff)))
621             {
622                 rgb++;
623                 col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
624                 fColor = ((col != RGB(0,0,0)) && (col != RGB(0xff,0xff,0xff)));
625             }
626             else fColor = TRUE;
627         }
628         else if (data->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
629         {
630             RGBTRIPLE *rgb = ((BITMAPCOREINFO *)data)->bmciColors;
631             DWORD col = RGB( rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue );
632             if ((col == RGB(0,0,0)) || (col == RGB(0xff,0xff,0xff)))
633             {
634                 rgb++;
635                 col = RGB( rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue );
636                 fColor = ((col != RGB(0,0,0)) && (col != RGB(0xff,0xff,0xff)));
637             }
638             else fColor = TRUE;
639         }
640         else
641         {
642             WARN(bitmap, "(%ld): wrong size for data\n",
643                      data->bmiHeader.biSize );
644             return 0;
645         }
646     }
647
648     /* Now create the bitmap */
649
650     handle = fColor ? CreateBitmap( width, height, 1, MONITOR_GetDepth(&MONITOR_PrimaryMonitor), NULL ) :
651                       CreateBitmap( width, height, 1, 1, NULL );
652     if (!handle) return 0;
653
654     if (init == CBM_INIT)
655         SetDIBits( hdc, handle, 0, height, bits, data, coloruse );
656     return handle;
657 }
658
659 /***********************************************************************
660  *           CreateDIBSection16    (GDI.489)
661  */
662 HBITMAP16 WINAPI CreateDIBSection16 (HDC16 hdc, BITMAPINFO *bmi, UINT16 usage,
663                                      SEGPTR *bits, HANDLE section,
664                                      DWORD offset)
665 {
666     HBITMAP16 hbitmap;
667     DC *dc = (DC *) GDI_GetObjPtr(hdc, DC_MAGIC);
668     if(!dc) dc = (DC *) GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
669     if(!dc) return (HBITMAP16) NULL;
670
671     hbitmap = dc->funcs->pCreateDIBSection16(dc, bmi, usage, bits, section, offset);
672
673     GDI_HEAP_UNLOCK(hdc);
674
675     return hbitmap;
676 }
677
678 /***********************************************************************
679  *           CreateDIBSection32    (GDI32.36)
680  */
681 HBITMAP WINAPI CreateDIBSection(HDC hdc, BITMAPINFO *bmi, UINT usage,
682                                 LPVOID *bits, HANDLE section,
683                                 DWORD offset)
684 {
685     HBITMAP hbitmap;
686     DC *dc = (DC *) GDI_GetObjPtr(hdc, DC_MAGIC);
687     if(!dc) dc = (DC *) GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
688     if(!dc) return (HBITMAP) NULL;
689
690     hbitmap = dc->funcs->pCreateDIBSection(dc, bmi, usage, bits, section, offset);
691
692     GDI_HEAP_UNLOCK(hdc);
693
694     return hbitmap;
695 }
696
697 /***********************************************************************
698  *           DIB_DeleteDIBSection
699  */
700 void DIB_DeleteDIBSection( BITMAPOBJ *bmp )
701 {
702     if (bmp && bmp->dib)
703     {
704         DIBSECTION *dib = bmp->dib;
705
706         if (dib->dsBm.bmBits)
707         {
708             if (dib->dshSection)
709                 UnmapViewOfFile(dib->dsBm.bmBits);
710             else
711                 VirtualFree(dib->dsBm.bmBits, MEM_RELEASE, 0L);
712         }
713
714         BITMAP_Driver->pDeleteDIBSection(bmp);
715
716         HeapFree(GetProcessHeap(), 0, dib);
717         bmp->dib = NULL;
718     }
719 }
720
721 /***********************************************************************
722  *           DIB_FixColorsToLoadflags
723  *
724  * Change color table entries when LR_LOADTRANSPARENT or LR_LOADMAP3DCOLORS
725  * are in loadflags
726  */
727 void DIB_FixColorsToLoadflags(BITMAPINFO * bmi, UINT loadflags, BYTE pix)
728 {
729   int colors;
730   COLORREF c_W, c_S, c_F, c_L, c_C;
731   int incr,i;
732   RGBQUAD *ptr;
733
734   if (bmi->bmiHeader.biBitCount > 8) return;
735   if (bmi->bmiHeader.biSize == sizeof(BITMAPINFOHEADER)) incr = 4;
736   else if (bmi->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) incr = 3;
737   else {
738     WARN(bitmap, "Wrong bitmap header size!\n");
739     return;
740   }
741   colors = bmi->bmiHeader.biClrUsed;
742   if (!colors && (bmi->bmiHeader.biBitCount <= 8))
743     colors = 1 << bmi->bmiHeader.biBitCount;
744   c_W = GetSysColor(COLOR_WINDOW);
745   c_S = GetSysColor(COLOR_3DSHADOW);
746   c_F = GetSysColor(COLOR_3DFACE);
747   c_L = GetSysColor(COLOR_3DLIGHT);
748   if (loadflags & LR_LOADTRANSPARENT) {
749     switch (bmi->bmiHeader.biBitCount) {
750       case 1: pix = pix >> 7; break;
751       case 4: pix = pix >> 4; break;
752       case 8: break;
753       default: 
754         WARN(bitmap, "(%d): Unsupported depth\n", bmi->bmiHeader.biBitCount); 
755         return;
756     }
757     if (pix >= colors) {
758       WARN(bitmap, "pixel has color index greater than biClrUsed!\n");
759       return;
760     }
761     if (loadflags & LR_LOADMAP3DCOLORS) c_W = c_F;
762     ptr = (RGBQUAD*)((char*)bmi->bmiColors+pix*incr);
763     ptr->rgbBlue = GetBValue(c_W);
764     ptr->rgbGreen = GetGValue(c_W);
765     ptr->rgbRed = GetRValue(c_W);
766   }
767   if (loadflags & LR_LOADMAP3DCOLORS)
768     for (i=0; i<colors; i++) {
769       ptr = (RGBQUAD*)((char*)bmi->bmiColors+i*incr);
770       c_C = RGB(ptr->rgbRed, ptr->rgbGreen, ptr->rgbBlue);
771       if (c_C == RGB(128, 128, 128)) { 
772         ptr->rgbRed = GetRValue(c_S);
773         ptr->rgbGreen = GetGValue(c_S);
774         ptr->rgbBlue = GetBValue(c_S);
775       } else if (c_C == RGB(192, 192, 192)) { 
776         ptr->rgbRed = GetRValue(c_F);
777         ptr->rgbGreen = GetGValue(c_F);
778         ptr->rgbBlue = GetBValue(c_F);
779       } else if (c_C == RGB(223, 223, 223)) { 
780         ptr->rgbRed = GetRValue(c_L);
781         ptr->rgbGreen = GetGValue(c_L);
782         ptr->rgbBlue = GetBValue(c_L);
783       } 
784     }
785 }