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