gdi32: Fixed initialization of bit masks in GetDIBits for 16-bit bitmaps.
[wine] / dlls / gdi32 / dib.c
1 /*
2  * GDI device-independent bitmaps
3  *
4  * Copyright 1993,1994  Alexandre Julliard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 /*
22   Important information:
23   
24   * Current Windows versions support two different DIB structures:
25
26     - BITMAPCOREINFO / BITMAPCOREHEADER (legacy structures; used in OS/2)
27     - BITMAPINFO / BITMAPINFOHEADER
28   
29     Most Windows API functions taking a BITMAPINFO* / BITMAPINFOHEADER* also
30     accept the old "core" structures, and so must WINE.
31     You can distinguish them by looking at the first member (bcSize/biSize),
32     or use the internal function DIB_GetBitmapInfo.
33
34     
35   * The palettes are stored in different formats:
36
37     - BITMAPCOREINFO: Array of RGBTRIPLE
38     - BITMAPINFO:     Array of RGBQUAD
39
40     
41   * There are even more DIB headers, but they all extend BITMAPINFOHEADER:
42     
43     - BITMAPV4HEADER: Introduced in Windows 95 / NT 4.0
44     - BITMAPV5HEADER: Introduced in Windows 98 / 2000
45     
46     If biCompression is BI_BITFIELDS, the color masks are at the same position
47     in all the headers (they start at bmiColors of BITMAPINFOHEADER), because
48     the new headers have structure members for the masks.
49
50
51   * You should never access the color table using the bmiColors member,
52     because the passed structure may have one of the extended headers
53     mentioned above. Use this to calculate the location:
54     
55     BITMAPINFO* info;
56     void* colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
57
58     
59   * More information:
60     Search for "Bitmap Structures" in MSDN
61 */
62
63 #include <stdarg.h>
64 #include <stdlib.h>
65 #include <string.h>
66
67 #include "windef.h"
68 #include "winbase.h"
69 #include "wownt32.h"
70 #include "gdi_private.h"
71 #include "wine/debug.h"
72
73 WINE_DEFAULT_DEBUG_CHANNEL(bitmap);
74
75
76 /*
77   Some of the following helper functions are duplicated in
78   dlls/x11drv/dib.c
79 */
80
81 /***********************************************************************
82  *           DIB_GetDIBWidthBytes
83  *
84  * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
85  */
86 int DIB_GetDIBWidthBytes( int width, int depth )
87 {
88     int words;
89
90     switch(depth)
91     {
92         case 1:  words = (width + 31) / 32; break;
93         case 4:  words = (width + 7) / 8; break;
94         case 8:  words = (width + 3) / 4; break;
95         case 15:
96         case 16: words = (width + 1) / 2; break;
97         case 24: words = (width * 3 + 3)/4; break;
98
99         default:
100             WARN("(%d): Unsupported depth\n", depth );
101         /* fall through */
102         case 32:
103                 words = width;
104     }
105     return 4 * words;
106 }
107
108 /***********************************************************************
109  *           DIB_GetDIBImageBytes
110  *
111  * Return the number of bytes used to hold the image in a DIB bitmap.
112  */
113 int DIB_GetDIBImageBytes( int width, int height, int depth )
114 {
115     return DIB_GetDIBWidthBytes( width, depth ) * abs( height );
116 }
117
118
119 /***********************************************************************
120  *           DIB_BitmapInfoSize
121  *
122  * Return the size of the bitmap info structure including color table.
123  */
124 int DIB_BitmapInfoSize( const BITMAPINFO * info, WORD coloruse )
125 {
126     int colors;
127
128     if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
129     {
130         const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
131         colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
132         return sizeof(BITMAPCOREHEADER) + colors *
133              ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
134     }
135     else  /* assume BITMAPINFOHEADER */
136     {
137         colors = info->bmiHeader.biClrUsed;
138         if (colors > 256) colors = 256;
139         if (!colors && (info->bmiHeader.biBitCount <= 8))
140             colors = 1 << info->bmiHeader.biBitCount;
141         return sizeof(BITMAPINFOHEADER) + colors *
142                ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
143     }
144 }
145
146
147 /***********************************************************************
148  *           DIB_GetBitmapInfo
149  *
150  * Get the info from a bitmap header.
151  * Return 0 for COREHEADER, 1 for INFOHEADER, -1 for error.
152  */
153 static int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
154                               LONG *height, WORD *planes, WORD *bpp, DWORD *compr, DWORD *size )
155 {
156     if (header->biSize == sizeof(BITMAPCOREHEADER))
157     {
158         const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)header;
159         *width  = core->bcWidth;
160         *height = core->bcHeight;
161         *planes = core->bcPlanes;
162         *bpp    = core->bcBitCount;
163         *compr  = 0;
164         *size   = 0;
165         return 0;
166     }
167     if (header->biSize >= sizeof(BITMAPINFOHEADER)) /* assume BITMAPINFOHEADER */
168     {
169         *width  = header->biWidth;
170         *height = header->biHeight;
171         *planes = header->biPlanes;
172         *bpp    = header->biBitCount;
173         *compr  = header->biCompression;
174         *size   = header->biSizeImage;
175         return 1;
176     }
177     ERR("(%d): unknown/wrong size for header\n", header->biSize );
178     return -1;
179 }
180
181
182 /***********************************************************************
183  *           StretchDIBits   (GDI32.@)
184  */
185 INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst,
186                        INT heightDst, INT xSrc, INT ySrc, INT widthSrc,
187                        INT heightSrc, const void *bits,
188                        const BITMAPINFO *info, UINT wUsage, DWORD dwRop )
189 {
190     DC *dc;
191     INT ret;
192
193     if (!bits || !info)
194         return 0;
195
196     if (!(dc = get_dc_ptr( hdc ))) return 0;
197
198     if(dc->funcs->pStretchDIBits)
199     {
200         update_dc( dc );
201         ret = dc->funcs->pStretchDIBits(dc->physDev, xDst, yDst, widthDst,
202                                         heightDst, xSrc, ySrc, widthSrc,
203                                         heightSrc, bits, info, wUsage, dwRop);
204         release_dc_ptr( dc );
205     }
206     else /* use StretchBlt */
207     {
208         LONG height;
209         LONG width;
210         WORD planes, bpp;
211         DWORD compr, size;
212         HBITMAP hBitmap;
213         BOOL fastpath = FALSE;
214
215         release_dc_ptr( dc );
216
217         if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size ) == -1)
218         {
219             ERR("Invalid bitmap\n");
220             return 0;
221         }
222
223         if (width < 0)
224         {
225             ERR("Bitmap has a negative width\n");
226             return 0;
227         }
228
229         hBitmap = GetCurrentObject(hdc, OBJ_BITMAP);
230
231         if (xDst == 0 && yDst == 0 && xSrc == 0 && ySrc == 0 &&
232             widthDst == widthSrc && heightDst == heightSrc &&
233             info->bmiHeader.biCompression == BI_RGB &&
234             dwRop == SRCCOPY)
235         {
236             BITMAPOBJ *bmp;
237             if ((bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBitmap, BITMAP_MAGIC )))
238             {
239                 if (bmp->bitmap.bmBitsPixel == bpp &&
240                     bmp->bitmap.bmWidth == widthSrc &&
241                     bmp->bitmap.bmHeight == heightSrc &&
242                     bmp->bitmap.bmPlanes == planes)
243                     fastpath = TRUE;
244                 GDI_ReleaseObj( hBitmap );
245             }
246         }
247
248         if (fastpath)
249         {
250             /* fast path */
251             TRACE("using fast path\n");
252             ret = SetDIBits( hdc, hBitmap, 0, height, bits, info, wUsage);
253         }
254         else
255         {
256             /* slow path - need to use StretchBlt */
257             HBITMAP hOldBitmap;
258             HPALETTE hpal = NULL;
259             HDC hdcMem;
260
261             hdcMem = CreateCompatibleDC( hdc );
262             hBitmap = CreateCompatibleBitmap(hdc, width, height);
263             hOldBitmap = SelectObject( hdcMem, hBitmap );
264             if(wUsage == DIB_PAL_COLORS)
265             {
266                 hpal = GetCurrentObject(hdc, OBJ_PAL);
267                 hpal = SelectPalette(hdcMem, hpal, FALSE);
268             }
269
270             if (info->bmiHeader.biCompression == BI_RLE4 ||
271                     info->bmiHeader.biCompression == BI_RLE8) {
272
273                 /* when RLE compression is used, there may be some gaps (ie the DIB doesn't
274                  * contain all the rectangle described in bmiHeader, but only part of it.
275                  * This mean that those undescribed pixels must be left untouched.
276                  * So, we first copy on a memory bitmap the current content of the
277                  * destination rectangle, blit the DIB bits on top of it - hence leaving
278                  * the gaps untouched -, and blitting the rectangle back.
279                  * This insure that gaps are untouched on the destination rectangle
280                  * Not doing so leads to trashed images (the gaps contain what was on the
281                  * memory bitmap => generally black or garbage)
282                  * Unfortunately, RLE DIBs without gaps will be slowed down. But this is
283                  * another speed vs correctness issue. Anyway, if speed is needed, then the
284                  * pStretchDIBits function shall be implemented.
285                  * ericP (2000/09/09)
286                  */
287
288                 /* copy existing bitmap from destination dc */
289                 StretchBlt( hdcMem, xSrc, abs(height) - heightSrc - ySrc,
290                             widthSrc, heightSrc, hdc, xDst, yDst, widthDst, heightDst,
291                             dwRop );
292             }
293
294             ret = SetDIBits(hdcMem, hBitmap, 0, height, bits, info, wUsage);
295
296             /* Origin for DIBitmap may be bottom left (positive biHeight) or top
297                left (negative biHeight) */
298             if (ret) StretchBlt( hdc, xDst, yDst, widthDst, heightDst,
299                                  hdcMem, xSrc, abs(height) - heightSrc - ySrc,
300                                  widthSrc, heightSrc, dwRop );
301             if(hpal)
302                 SelectPalette(hdcMem, hpal, FALSE);
303             SelectObject( hdcMem, hOldBitmap );
304             DeleteDC( hdcMem );
305             DeleteObject( hBitmap );
306         }
307     }
308     return ret;
309 }
310
311
312 /******************************************************************************
313  * SetDIBits [GDI32.@]
314  *
315  * Sets pixels in a bitmap using colors from DIB.
316  *
317  * PARAMS
318  *    hdc       [I] Handle to device context
319  *    hbitmap   [I] Handle to bitmap
320  *    startscan [I] Starting scan line
321  *    lines     [I] Number of scan lines
322  *    bits      [I] Array of bitmap bits
323  *    info      [I] Address of structure with data
324  *    coloruse  [I] Type of color indexes to use
325  *
326  * RETURNS
327  *    Success: Number of scan lines copied
328  *    Failure: 0
329  */
330 INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
331                       UINT lines, LPCVOID bits, const BITMAPINFO *info,
332                       UINT coloruse )
333 {
334     DC *dc;
335     BITMAPOBJ *bitmap;
336     INT result = 0;
337
338     if (!(dc = get_dc_ptr( hdc )))
339     {
340         if (coloruse == DIB_RGB_COLORS) FIXME( "shouldn't require a DC for DIB_RGB_COLORS\n" );
341         return 0;
342     }
343
344     update_dc( dc );
345
346     if (!(bitmap = GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
347     {
348         release_dc_ptr( dc );
349         return 0;
350     }
351
352     if (!bitmap->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) goto done;
353
354     result = lines;
355     if (bitmap->funcs)
356     {
357         if (bitmap->funcs != dc->funcs)
358             ERR( "not supported: DDB bitmap %p not belonging to device %p\n", hbitmap, hdc );
359         else if (dc->funcs->pSetDIBits)
360             result = dc->funcs->pSetDIBits( dc->physDev, hbitmap, startscan, lines,
361                                             bits, info, coloruse );
362     }
363
364  done:
365     GDI_ReleaseObj( hbitmap );
366     release_dc_ptr( dc );
367     return result;
368 }
369
370
371 /***********************************************************************
372  *           SetDIBitsToDevice   (GDI32.@)
373  */
374 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
375                            DWORD cy, INT xSrc, INT ySrc, UINT startscan,
376                            UINT lines, LPCVOID bits, const BITMAPINFO *info,
377                            UINT coloruse )
378 {
379     INT ret;
380     DC *dc;
381
382     if (!bits) return 0;
383
384     if (!(dc = get_dc_ptr( hdc ))) return 0;
385
386     if(dc->funcs->pSetDIBitsToDevice)
387     {
388         update_dc( dc );
389         ret = dc->funcs->pSetDIBitsToDevice( dc->physDev, xDest, yDest, cx, cy, xSrc,
390                                              ySrc, startscan, lines, bits,
391                                              info, coloruse );
392     }
393     else {
394         FIXME("unimplemented on hdc %p\n", hdc);
395         ret = 0;
396     }
397
398     release_dc_ptr( dc );
399     return ret;
400 }
401
402 /***********************************************************************
403  *           SetDIBColorTable    (GDI32.@)
404  */
405 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, CONST RGBQUAD *colors )
406 {
407     DC * dc;
408     UINT result = 0;
409     BITMAPOBJ * bitmap;
410
411     if (!(dc = get_dc_ptr( hdc ))) return 0;
412
413     if ((bitmap = GDI_GetObjPtr( dc->hBitmap, BITMAP_MAGIC )))
414     {
415         /* Check if currently selected bitmap is a DIB */
416         if (bitmap->color_table)
417         {
418             if (startpos < bitmap->nb_colors)
419             {
420                 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
421                 memcpy(bitmap->color_table + startpos, colors, entries * sizeof(RGBQUAD));
422                 result = entries;
423             }
424         }
425         GDI_ReleaseObj( dc->hBitmap );
426     }
427
428     if (dc->funcs->pSetDIBColorTable)
429         dc->funcs->pSetDIBColorTable(dc->physDev, startpos, entries, colors);
430
431     release_dc_ptr( dc );
432     return result;
433 }
434
435
436 /***********************************************************************
437  *           GetDIBColorTable    (GDI32.@)
438  */
439 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
440 {
441     DC * dc;
442     UINT result = 0;
443
444     if (!(dc = get_dc_ptr( hdc ))) return 0;
445
446     if (dc->funcs->pGetDIBColorTable)
447         result = dc->funcs->pGetDIBColorTable(dc->physDev, startpos, entries, colors);
448     else
449     {
450         BITMAPOBJ *bitmap = GDI_GetObjPtr( dc->hBitmap, BITMAP_MAGIC );
451         if (bitmap)
452         {
453             /* Check if currently selected bitmap is a DIB */
454             if (bitmap->color_table)
455             {
456                 if (startpos < bitmap->nb_colors)
457                 {
458                     if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
459                     memcpy(colors, bitmap->color_table + startpos, entries * sizeof(RGBQUAD));
460                     result = entries;
461                 }
462             }
463             GDI_ReleaseObj( dc->hBitmap );
464         }
465     }
466     release_dc_ptr( dc );
467     return result;
468 }
469
470 /* FIXME the following two structs should be combined with __sysPalTemplate in
471    objects/color.c - this should happen after de-X11-ing both of these
472    files.
473    NB. RGBQUAD and PALETTEENTRY have different orderings of red, green
474    and blue - sigh */
475
476 static const RGBQUAD EGAColorsQuads[16] = {
477 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
478     { 0x00, 0x00, 0x00, 0x00 },
479     { 0x00, 0x00, 0x80, 0x00 },
480     { 0x00, 0x80, 0x00, 0x00 },
481     { 0x00, 0x80, 0x80, 0x00 },
482     { 0x80, 0x00, 0x00, 0x00 },
483     { 0x80, 0x00, 0x80, 0x00 },
484     { 0x80, 0x80, 0x00, 0x00 },
485     { 0x80, 0x80, 0x80, 0x00 },
486     { 0xc0, 0xc0, 0xc0, 0x00 },
487     { 0x00, 0x00, 0xff, 0x00 },
488     { 0x00, 0xff, 0x00, 0x00 },
489     { 0x00, 0xff, 0xff, 0x00 },
490     { 0xff, 0x00, 0x00, 0x00 },
491     { 0xff, 0x00, 0xff, 0x00 },
492     { 0xff, 0xff, 0x00, 0x00 },
493     { 0xff, 0xff, 0xff, 0x00 }
494 };
495
496 static const RGBTRIPLE EGAColorsTriples[16] = {
497 /* rgbBlue, rgbGreen, rgbRed */
498     { 0x00, 0x00, 0x00 },
499     { 0x00, 0x00, 0x80 },
500     { 0x00, 0x80, 0x00 },
501     { 0x00, 0x80, 0x80 },
502     { 0x80, 0x00, 0x00 },
503     { 0x80, 0x00, 0x80 },
504     { 0x80, 0x80, 0x00 },
505     { 0x80, 0x80, 0x80 },
506     { 0xc0, 0xc0, 0xc0 },
507     { 0x00, 0x00, 0xff },
508     { 0x00, 0xff, 0x00 },
509     { 0x00, 0xff, 0xff },
510     { 0xff, 0x00, 0x00 } ,
511     { 0xff, 0x00, 0xff },
512     { 0xff, 0xff, 0x00 },
513     { 0xff, 0xff, 0xff }
514 };
515
516 static const RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
517 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
518     { 0x00, 0x00, 0x00, 0x00 },
519     { 0x00, 0x00, 0x80, 0x00 },
520     { 0x00, 0x80, 0x00, 0x00 },
521     { 0x00, 0x80, 0x80, 0x00 },
522     { 0x80, 0x00, 0x00, 0x00 },
523     { 0x80, 0x00, 0x80, 0x00 },
524     { 0x80, 0x80, 0x00, 0x00 },
525     { 0xc0, 0xc0, 0xc0, 0x00 },
526     { 0xc0, 0xdc, 0xc0, 0x00 },
527     { 0xf0, 0xca, 0xa6, 0x00 },
528     { 0xf0, 0xfb, 0xff, 0x00 },
529     { 0xa4, 0xa0, 0xa0, 0x00 },
530     { 0x80, 0x80, 0x80, 0x00 },
531     { 0x00, 0x00, 0xf0, 0x00 },
532     { 0x00, 0xff, 0x00, 0x00 },
533     { 0x00, 0xff, 0xff, 0x00 },
534     { 0xff, 0x00, 0x00, 0x00 },
535     { 0xff, 0x00, 0xff, 0x00 },
536     { 0xff, 0xff, 0x00, 0x00 },
537     { 0xff, 0xff, 0xff, 0x00 }
538 };
539
540 static const RGBTRIPLE DefLogPaletteTriples[20] = { /* Copy of Default Logical Palette */
541 /* rgbBlue, rgbGreen, rgbRed */
542     { 0x00, 0x00, 0x00 },
543     { 0x00, 0x00, 0x80 },
544     { 0x00, 0x80, 0x00 },
545     { 0x00, 0x80, 0x80 },
546     { 0x80, 0x00, 0x00 },
547     { 0x80, 0x00, 0x80 },
548     { 0x80, 0x80, 0x00 },
549     { 0xc0, 0xc0, 0xc0 },
550     { 0xc0, 0xdc, 0xc0 },
551     { 0xf0, 0xca, 0xa6 },
552     { 0xf0, 0xfb, 0xff },
553     { 0xa4, 0xa0, 0xa0 },
554     { 0x80, 0x80, 0x80 },
555     { 0x00, 0x00, 0xf0 },
556     { 0x00, 0xff, 0x00 },
557     { 0x00, 0xff, 0xff },
558     { 0xff, 0x00, 0x00 },
559     { 0xff, 0x00, 0xff },
560     { 0xff, 0xff, 0x00 },
561     { 0xff, 0xff, 0xff}
562 };
563
564
565 /******************************************************************************
566  * GetDIBits [GDI32.@]
567  *
568  * Retrieves bits of bitmap and copies to buffer.
569  *
570  * RETURNS
571  *    Success: Number of scan lines copied from bitmap
572  *    Failure: 0
573  */
574 INT WINAPI GetDIBits(
575     HDC hdc,         /* [in]  Handle to device context */
576     HBITMAP hbitmap, /* [in]  Handle to bitmap */
577     UINT startscan,  /* [in]  First scan line to set in dest bitmap */
578     UINT lines,      /* [in]  Number of scan lines to copy */
579     LPVOID bits,       /* [out] Address of array for bitmap bits */
580     BITMAPINFO * info, /* [out] Address of structure with bitmap data */
581     UINT coloruse)   /* [in]  RGB or palette index */
582 {
583     DC * dc;
584     BITMAPOBJ * bmp;
585     int i;
586     int bitmap_type;
587     BOOL core_header;
588     LONG width;
589     LONG height;
590     WORD planes, bpp;
591     DWORD compr, size;
592     void* colorPtr;
593     RGBTRIPLE* rgbTriples;
594     RGBQUAD* rgbQuads;
595
596     if (!info) return 0;
597
598     bitmap_type = DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size);
599     if (bitmap_type == -1)
600     {
601         ERR("Invalid bitmap format\n");
602         return 0;
603     }
604     core_header = (bitmap_type == 0);
605     if (!(dc = get_dc_ptr( hdc )))
606     {
607         SetLastError( ERROR_INVALID_PARAMETER );
608         return 0;
609     }
610     update_dc( dc );
611     if (!(bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
612     {
613         release_dc_ptr( dc );
614         return 0;
615     }
616
617     colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
618     rgbTriples = (RGBTRIPLE *) colorPtr;
619     rgbQuads = (RGBQUAD *) colorPtr;
620
621     /* Transfer color info */
622
623     switch (bpp)
624     {
625     case 0:  /* query bitmap info only */
626         if (core_header)
627         {
628             BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) info;
629             coreheader->bcWidth = bmp->bitmap.bmWidth;
630             coreheader->bcHeight = bmp->bitmap.bmHeight;
631             coreheader->bcPlanes = 1;
632             coreheader->bcBitCount = bmp->bitmap.bmBitsPixel;
633         }
634         else
635         {
636             info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
637             info->bmiHeader.biHeight = bmp->bitmap.bmHeight;
638             info->bmiHeader.biPlanes = 1;
639             info->bmiHeader.biSizeImage =
640                 DIB_GetDIBImageBytes( bmp->bitmap.bmWidth,
641                                       bmp->bitmap.bmHeight,
642                                       bmp->bitmap.bmBitsPixel );
643             switch(bmp->bitmap.bmBitsPixel)
644             {
645             case 15:
646                 info->bmiHeader.biBitCount = 16;
647                 info->bmiHeader.biCompression = BI_RGB;
648                 break;
649             case 16:
650                 info->bmiHeader.biBitCount = 16;
651                 info->bmiHeader.biCompression = BI_BITFIELDS;
652                 break;
653             default:
654                 info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
655                 info->bmiHeader.biCompression = BI_RGB;
656                 break;
657             }
658             info->bmiHeader.biXPelsPerMeter = 0;
659             info->bmiHeader.biYPelsPerMeter = 0;
660             info->bmiHeader.biClrUsed = 0;
661             info->bmiHeader.biClrImportant = 0;
662
663             /* Windows 2000 doesn't touch the additional struct members if
664                it's a BITMAPV4HEADER or a BITMAPV5HEADER */
665         }
666         lines = abs(bmp->bitmap.bmHeight);
667         goto done;
668
669     case 1:
670     case 4:
671     case 8:
672         if (!core_header) info->bmiHeader.biClrUsed = 0;
673
674         /* If the bitmap object already has a dib section at the
675            same color depth then get the color map from it */
676         if (bmp->dib && bmp->dib->dsBm.bmBitsPixel == bpp) {
677             if(coloruse == DIB_RGB_COLORS) {
678                 unsigned int colors = min( bmp->nb_colors, 1 << bpp );
679
680                 if (core_header)
681                 {
682                     /* Convert the color table (RGBQUAD to RGBTRIPLE) */
683                     RGBTRIPLE* index = rgbTriples;
684
685                     for (i=0; i < colors; i++, index++)
686                     {
687                         index->rgbtRed   = bmp->color_table[i].rgbRed;
688                         index->rgbtGreen = bmp->color_table[i].rgbGreen;
689                         index->rgbtBlue  = bmp->color_table[i].rgbBlue;
690                     }
691                 }
692                 else
693                 {
694                     if (colors != 1 << bpp) info->bmiHeader.biClrUsed = colors;
695                     memcpy(colorPtr, bmp->color_table, colors * sizeof(RGBQUAD));
696                 }
697             }
698             else {
699                 WORD *index = colorPtr;
700                 for(i = 0; i < 1 << info->bmiHeader.biBitCount; i++, index++)
701                     *index = i;
702             }
703         }
704         else {
705             if(bpp >= bmp->bitmap.bmBitsPixel) {
706                 /* Generate the color map from the selected palette */
707                 PALETTEENTRY palEntry[256];
708
709                 memset( palEntry, 0, sizeof(palEntry) );
710                 if (!GetPaletteEntries( dc->hPalette, 0, 1 << bmp->bitmap.bmBitsPixel, palEntry ))
711                 {
712                     release_dc_ptr( dc );
713                     GDI_ReleaseObj( hbitmap );
714                     return 0;
715                 }
716                 for (i = 0; i < (1 << bmp->bitmap.bmBitsPixel); i++) {
717                     if (coloruse == DIB_RGB_COLORS) {
718                         if (core_header)
719                         {
720                             rgbTriples[i].rgbtRed   = palEntry[i].peRed;
721                             rgbTriples[i].rgbtGreen = palEntry[i].peGreen;
722                             rgbTriples[i].rgbtBlue  = palEntry[i].peBlue;
723                         }
724                         else
725                         {
726                             rgbQuads[i].rgbRed      = palEntry[i].peRed;
727                             rgbQuads[i].rgbGreen    = palEntry[i].peGreen;
728                             rgbQuads[i].rgbBlue     = palEntry[i].peBlue;
729                             rgbQuads[i].rgbReserved = 0;
730                         }
731                     }
732                     else ((WORD *)colorPtr)[i] = (WORD)i;
733                 }
734             } else {
735                 switch (bpp) {
736                 case 1:
737                     if (core_header)
738                     {
739                         rgbTriples[0].rgbtRed = rgbTriples[0].rgbtGreen =
740                             rgbTriples[0].rgbtBlue = 0;
741                         rgbTriples[1].rgbtRed = rgbTriples[1].rgbtGreen =
742                             rgbTriples[1].rgbtBlue = 0xff;
743                     }
744                     else
745                     {    
746                         rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen =
747                             rgbQuads[0].rgbBlue = 0;
748                         rgbQuads[0].rgbReserved = 0;
749                         rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen =
750                             rgbQuads[1].rgbBlue = 0xff;
751                         rgbQuads[1].rgbReserved = 0;
752                     }
753                     break;
754
755                 case 4:
756                     if (core_header)
757                         memcpy(colorPtr, EGAColorsTriples, sizeof(EGAColorsTriples));
758                     else
759                         memcpy(colorPtr, EGAColorsQuads, sizeof(EGAColorsQuads));
760
761                     break;
762
763                 case 8:
764                     {
765                         if (core_header)
766                         {
767                             INT r, g, b;
768                             RGBTRIPLE *color;
769
770                             memcpy(rgbTriples, DefLogPaletteTriples,
771                                        10 * sizeof(RGBTRIPLE));
772                             memcpy(rgbTriples + 246, DefLogPaletteTriples + 10,
773                                        10 * sizeof(RGBTRIPLE));
774                             color = rgbTriples + 10;
775                             for(r = 0; r <= 5; r++) /* FIXME */
776                                 for(g = 0; g <= 5; g++)
777                                     for(b = 0; b <= 5; b++) {
778                                         color->rgbtRed =   (r * 0xff) / 5;
779                                         color->rgbtGreen = (g * 0xff) / 5;
780                                         color->rgbtBlue =  (b * 0xff) / 5;
781                                         color++;
782                                     }
783                         }
784                         else
785                         {
786                             INT r, g, b;
787                             RGBQUAD *color;
788
789                             memcpy(rgbQuads, DefLogPaletteQuads,
790                                        10 * sizeof(RGBQUAD));
791                             memcpy(rgbQuads + 246, DefLogPaletteQuads + 10,
792                                    10 * sizeof(RGBQUAD));
793                             color = rgbQuads + 10;
794                             for(r = 0; r <= 5; r++) /* FIXME */
795                                 for(g = 0; g <= 5; g++)
796                                     for(b = 0; b <= 5; b++) {
797                                         color->rgbRed =   (r * 0xff) / 5;
798                                         color->rgbGreen = (g * 0xff) / 5;
799                                         color->rgbBlue =  (b * 0xff) / 5;
800                                         color->rgbReserved = 0;
801                                         color++;
802                                     }
803                         }
804                     }
805                 }
806             }
807         }
808         break;
809
810     case 15:
811         if (info->bmiHeader.biCompression == BI_BITFIELDS)
812         {
813             ((PDWORD)info->bmiColors)[0] = 0x7c00;
814             ((PDWORD)info->bmiColors)[1] = 0x03e0;
815             ((PDWORD)info->bmiColors)[2] = 0x001f;
816         }
817         break;
818
819     case 16:
820         if (info->bmiHeader.biCompression == BI_BITFIELDS)
821         {
822             ((PDWORD)info->bmiColors)[0] = 0xf800;
823             ((PDWORD)info->bmiColors)[1] = 0x07e0;
824             ((PDWORD)info->bmiColors)[2] = 0x001f;
825         }
826         break;
827     }
828
829     if (bits && lines)
830     {
831         /* If the bitmap object already have a dib section that contains image data, get the bits from it */
832         if(bmp->dib && bmp->dib->dsBm.bmBitsPixel >= 15 && bpp >= 15)
833         {
834             /*FIXME: Only RGB dibs supported for now */
835             unsigned int srcwidth = bmp->dib->dsBm.bmWidth, srcwidthb = bmp->dib->dsBm.bmWidthBytes;
836             unsigned int dstwidth = width;
837             int dstwidthb = DIB_GetDIBWidthBytes( width, bpp );
838             LPBYTE dbits = bits, sbits = (LPBYTE) bmp->dib->dsBm.bmBits + (startscan * srcwidthb);
839             unsigned int x, y, width, widthb;
840
841             if ((height < 0) ^ (bmp->dib->dsBmih.biHeight < 0))
842             {
843                 dbits = (LPBYTE)bits + (dstwidthb * (lines-1));
844                 dstwidthb = -dstwidthb;
845             }
846
847             switch( bpp ) {
848
849             case 15:
850             case 16: /* 16 bpp dstDIB */
851                 {
852                     LPWORD dstbits = (LPWORD)dbits;
853                     WORD rmask = 0x7c00, gmask= 0x03e0, bmask = 0x001f;
854
855                     /* FIXME: BI_BITFIELDS not supported yet */
856
857                     switch(bmp->dib->dsBm.bmBitsPixel) {
858
859                     case 16: /* 16 bpp srcDIB -> 16 bpp dstDIB */
860                         {
861                             widthb = min(srcwidthb, abs(dstwidthb));
862                             /* FIXME: BI_BITFIELDS not supported yet */
863                             for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
864                                 memcpy(dbits, sbits, widthb);
865                         }
866                         break;
867
868                     case 24: /* 24 bpp srcDIB -> 16 bpp dstDIB */
869                         {
870                             LPBYTE srcbits = sbits;
871
872                             width = min(srcwidth, dstwidth);
873                             for( y = 0; y < lines; y++) {
874                                 for( x = 0; x < width; x++, srcbits += 3)
875                                     *dstbits++ = ((srcbits[0] >> 3) & bmask) |
876                                                  (((WORD)srcbits[1] << 2) & gmask) |
877                                                  (((WORD)srcbits[2] << 7) & rmask);
878
879                                 dstbits = (LPWORD)(dbits+=dstwidthb);
880                                 srcbits = (sbits += srcwidthb);
881                             }
882                         }
883                         break;
884
885                     case 32: /* 32 bpp srcDIB -> 16 bpp dstDIB */
886                         {
887                             LPDWORD srcbits = (LPDWORD)sbits;
888                             DWORD val;
889
890                             width = min(srcwidth, dstwidth);
891                             for( y = 0; y < lines; y++) {
892                                 for( x = 0; x < width; x++ ) {
893                                     val = *srcbits++;
894                                     *dstbits++ = (WORD)(((val >> 3) & bmask) | ((val >> 6) & gmask) |
895                                                        ((val >> 9) & rmask));
896                                 }
897                                 dstbits = (LPWORD)(dbits+=dstwidthb);
898                                 srcbits = (LPDWORD)(sbits+=srcwidthb);
899                             }
900                         }
901                         break;
902
903                     default: /* ? bit bmp -> 16 bit DIB */
904                         FIXME("15/16 bit DIB %d bit bitmap\n",
905                         bmp->bitmap.bmBitsPixel);
906                         break;
907                     }
908                 }
909                 break;
910
911             case 24: /* 24 bpp dstDIB */
912                 {
913                     LPBYTE dstbits = dbits;
914
915                     switch(bmp->dib->dsBm.bmBitsPixel) {
916
917                     case 16: /* 16 bpp srcDIB -> 24 bpp dstDIB */
918                         {
919                             LPWORD srcbits = (LPWORD)sbits;
920                             WORD val;
921
922                             width = min(srcwidth, dstwidth);
923                             /* FIXME: BI_BITFIELDS not supported yet */
924                             for( y = 0; y < lines; y++) {
925                                 for( x = 0; x < width; x++ ) {
926                                     val = *srcbits++;
927                                     *dstbits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07));
928                                     *dstbits++ = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07));
929                                     *dstbits++ = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07));
930                                 }
931                                 dstbits = dbits+=dstwidthb;
932                                 srcbits = (LPWORD)(sbits+=srcwidthb);
933                             }
934                         }
935                         break;
936
937                     case 24: /* 24 bpp srcDIB -> 24 bpp dstDIB */
938                         {
939                             widthb = min(srcwidthb, abs(dstwidthb));
940                             for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
941                                 memcpy(dbits, sbits, widthb);
942                         }
943                         break;
944
945                     case 32: /* 32 bpp srcDIB -> 24 bpp dstDIB */
946                         {
947                             LPBYTE srcbits = sbits;
948
949                             width = min(srcwidth, dstwidth);
950                             for( y = 0; y < lines; y++) {
951                                 for( x = 0; x < width; x++, srcbits++ ) {
952                                     *dstbits++ = *srcbits++;
953                                     *dstbits++ = *srcbits++;
954                                     *dstbits++ = *srcbits++;
955                                 }
956                                 dstbits = dbits+=dstwidthb;
957                                 srcbits = sbits+=srcwidthb;
958                             }
959                         }
960                         break;
961
962                     default: /* ? bit bmp -> 24 bit DIB */
963                         FIXME("24 bit DIB %d bit bitmap\n",
964                               bmp->bitmap.bmBitsPixel);
965                         break;
966                     }
967                 }
968                 break;
969
970             case 32: /* 32 bpp dstDIB */
971                 {
972                     LPDWORD dstbits = (LPDWORD)dbits;
973
974                     /* FIXME: BI_BITFIELDS not supported yet */
975
976                     switch(bmp->dib->dsBm.bmBitsPixel) {
977                         case 16: /* 16 bpp srcDIB -> 32 bpp dstDIB */
978                         {
979                             LPWORD srcbits = (LPWORD)sbits;
980                             DWORD val;
981
982                             width = min(srcwidth, dstwidth);
983                             /* FIXME: BI_BITFIELDS not supported yet */
984                             for( y = 0; y < lines; y++) {
985                                 for( x = 0; x < width; x++ ) {
986                                     val = (DWORD)*srcbits++;
987                                     *dstbits++ = ((val << 3) & 0xf8) | ((val >> 2) & 0x07) |
988                                                  ((val << 6) & 0xf800) | ((val << 1) & 0x0700) |
989                                                  ((val << 9) & 0xf80000) | ((val << 4) & 0x070000);
990                                 }
991                                 dstbits=(LPDWORD)(dbits+=dstwidthb);
992                                 srcbits=(LPWORD)(sbits+=srcwidthb);
993                             }
994                         }
995                         break;
996
997                     case 24: /* 24 bpp srcDIB -> 32 bpp dstDIB */
998                         {
999                             LPBYTE srcbits = sbits;
1000
1001                             width = min(srcwidth, dstwidth);
1002                             for( y = 0; y < lines; y++) {
1003                                 for( x = 0; x < width; x++, srcbits+=3 )
1004                                     *dstbits++ =  srcbits[0] |
1005                                                  (srcbits[1] <<  8) |
1006                                                  (srcbits[2] << 16);
1007                                 dstbits=(LPDWORD)(dbits+=dstwidthb);
1008                                 srcbits=(sbits+=srcwidthb);
1009                             }
1010                         }
1011                         break;
1012
1013                     case 32: /* 32 bpp srcDIB -> 32 bpp dstDIB */
1014                         {
1015                             widthb = min(srcwidthb, abs(dstwidthb));
1016                             /* FIXME: BI_BITFIELDS not supported yet */
1017                             for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb) {
1018                                 memcpy(dbits, sbits, widthb);
1019                             }
1020                         }
1021                         break;
1022
1023                     default: /* ? bit bmp -> 32 bit DIB */
1024                         FIXME("32 bit DIB %d bit bitmap\n",
1025                         bmp->bitmap.bmBitsPixel);
1026                         break;
1027                     }
1028                 }
1029                 break;
1030
1031             default: /* ? bit DIB */
1032                 FIXME("Unsupported DIB depth %d\n", info->bmiHeader.biBitCount);
1033                 break;
1034             }
1035         }
1036         /* Otherwise, get bits from the XImage */
1037         else
1038         {
1039             if (!bmp->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) lines = 0;
1040             else
1041             {
1042                 if (bmp->funcs && bmp->funcs->pGetDIBits)
1043                     lines = bmp->funcs->pGetDIBits( dc->physDev, hbitmap, startscan,
1044                                                     lines, bits, info, coloruse );
1045                 else
1046                     lines = 0;  /* FIXME: should copy from bmp->bitmap.bmBits */
1047             }
1048         }
1049     }
1050     else lines = abs(height);
1051
1052     /* The knowledge base article Q81498 ("DIBs and Their Uses") states that
1053        if bits == NULL and bpp != 0, only biSizeImage and the color table are
1054        filled in. */
1055     if (!core_header)
1056     {
1057         /* FIXME: biSizeImage should be calculated according to the selected
1058            compression algorithm if biCompression != BI_RGB */
1059         info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes( width, height, bpp );
1060         TRACE("biSizeImage = %d, ", info->bmiHeader.biSizeImage);
1061     }
1062     TRACE("biWidth = %d, biHeight = %d\n", width, height);
1063
1064 done:
1065     release_dc_ptr( dc );
1066     GDI_ReleaseObj( hbitmap );
1067     return lines;
1068 }
1069
1070
1071 /***********************************************************************
1072  *           CreateDIBitmap    (GDI32.@)
1073  *
1074  * Creates a DDB (device dependent bitmap) from a DIB.
1075  * The DDB will have the same color depth as the reference DC.
1076  */
1077 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
1078                             DWORD init, LPCVOID bits, const BITMAPINFO *data,
1079                             UINT coloruse )
1080 {
1081     HBITMAP handle;
1082     LONG width;
1083     LONG height;
1084     WORD planes, bpp;
1085     DWORD compr, size;
1086     DC *dc;
1087
1088     if (DIB_GetBitmapInfo( header, &width, &height, &planes, &bpp, &compr, &size ) == -1) return 0;
1089     
1090     if (width < 0)
1091     {
1092         TRACE("Bitmap has a negative width\n");
1093         return 0;
1094     }
1095     
1096     /* Top-down DIBs have a negative height */
1097     if (height < 0) height = -height;
1098
1099     TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1100            hdc, header, init, bits, data, coloruse, width, height, bpp, compr);
1101     
1102     if (hdc == NULL)
1103         handle = CreateBitmap( width, height, 1, 1, NULL );
1104     else
1105         handle = CreateCompatibleBitmap( hdc, width, height );
1106
1107     if (handle)
1108     {
1109         if (init == CBM_INIT) SetDIBits( hdc, handle, 0, height, bits, data, coloruse );
1110
1111         else if (hdc && ((dc = get_dc_ptr( hdc )) != NULL) )
1112         {
1113             if (!BITMAP_SetOwnerDC( handle, dc ))
1114             {
1115                 DeleteObject( handle );
1116                 handle = 0;
1117             }
1118             release_dc_ptr( dc );
1119         }
1120     }
1121
1122     return handle;
1123 }
1124
1125 /***********************************************************************
1126  *           CreateDIBSection    (GDI.489)
1127  */
1128 HBITMAP16 WINAPI CreateDIBSection16 (HDC16 hdc, const BITMAPINFO *bmi, UINT16 usage,
1129                                      SEGPTR *bits16, HANDLE section, DWORD offset)
1130 {
1131     LPVOID bits32;
1132     HBITMAP hbitmap;
1133
1134     hbitmap = CreateDIBSection( HDC_32(hdc), bmi, usage, &bits32, section, offset );
1135     if (hbitmap)
1136     {
1137         BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr(hbitmap, BITMAP_MAGIC);
1138         if (bmp && bmp->dib && bits32)
1139         {
1140             const BITMAPINFOHEADER *bi = &bmi->bmiHeader;
1141             LONG width, height;
1142             WORD planes, bpp;
1143             DWORD compr, size;
1144             INT width_bytes;
1145             WORD count, sel;
1146             int i;
1147
1148             DIB_GetBitmapInfo(bi, &width, &height, &planes, &bpp, &compr, &size);
1149
1150             height = height >= 0 ? height : -height;
1151             width_bytes = DIB_GetDIBWidthBytes(width, bpp);
1152
1153             if (!size || (compr != BI_RLE4 && compr != BI_RLE8)) size = width_bytes * height;
1154
1155             /* calculate number of sel's needed for size with 64K steps */
1156             count = (size + 0xffff) / 0x10000;
1157             sel = AllocSelectorArray16(count);
1158
1159             for (i = 0; i < count; i++)
1160             {
1161                 SetSelectorBase(sel + (i << __AHSHIFT), (DWORD)bits32 + i * 0x10000);
1162                 SetSelectorLimit16(sel + (i << __AHSHIFT), size - 1); /* yep, limit is correct */
1163                 size -= 0x10000;
1164             }
1165             bmp->segptr_bits = MAKESEGPTR( sel, 0 );
1166             if (bits16) *bits16 = bmp->segptr_bits;
1167         }
1168         if (bmp) GDI_ReleaseObj( hbitmap );
1169     }
1170     return HBITMAP_16(hbitmap);
1171 }
1172
1173 /* Copy/synthesize RGB palette from BITMAPINFO. Ripped from dlls/winex11.drv/dib.c */
1174 static void DIB_CopyColorTable( DC *dc, BITMAPOBJ *bmp, WORD coloruse, const BITMAPINFO *info )
1175 {
1176     RGBQUAD *colorTable;
1177     unsigned int colors;
1178     int i;
1179     BOOL core_info = info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER);
1180
1181     if (core_info)
1182     {
1183         colors = 1 << ((const BITMAPCOREINFO*) info)->bmciHeader.bcBitCount;
1184     }
1185     else
1186     {
1187         colors = info->bmiHeader.biClrUsed;
1188         if (!colors) colors = 1 << info->bmiHeader.biBitCount;
1189     }
1190
1191     if (colors > 256) {
1192         ERR("called with >256 colors!\n");
1193         return;
1194     }
1195
1196     if (!(colorTable = HeapAlloc(GetProcessHeap(), 0, colors * sizeof(RGBQUAD) ))) return;
1197
1198     if(coloruse == DIB_RGB_COLORS)
1199     {
1200         if (core_info)
1201         {
1202            /* Convert RGBTRIPLEs to RGBQUADs */
1203            for (i=0; i < colors; i++)
1204            {
1205                colorTable[i].rgbRed   = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtRed;
1206                colorTable[i].rgbGreen = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtGreen;
1207                colorTable[i].rgbBlue  = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtBlue;
1208                colorTable[i].rgbReserved = 0;
1209            }
1210         }
1211         else
1212         {
1213             memcpy(colorTable, (const BYTE*) info + (WORD) info->bmiHeader.biSize, colors * sizeof(RGBQUAD));
1214         }
1215     }
1216     else
1217     {
1218         PALETTEENTRY entries[256];
1219         const WORD *index = (const WORD*) ((const BYTE*) info + (WORD) info->bmiHeader.biSize);
1220         UINT count = GetPaletteEntries( dc->hPalette, 0, colors, entries );
1221
1222         for (i = 0; i < colors; i++, index++)
1223         {
1224             PALETTEENTRY *entry = &entries[*index % count];
1225             colorTable[i].rgbRed = entry->peRed;
1226             colorTable[i].rgbGreen = entry->peGreen;
1227             colorTable[i].rgbBlue = entry->peBlue;
1228             colorTable[i].rgbReserved = 0;
1229         }
1230     }
1231     bmp->color_table = colorTable;
1232     bmp->nb_colors = colors;
1233 }
1234
1235 /***********************************************************************
1236  *           CreateDIBSection    (GDI32.@)
1237  */
1238 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
1239                                 VOID **bits, HANDLE section, DWORD offset)
1240 {
1241     HBITMAP ret = 0;
1242     DC *dc;
1243     BOOL bDesktopDC = FALSE;
1244     DIBSECTION *dib;
1245     BITMAPOBJ *bmp;
1246     int bitmap_type;
1247     LONG width, height;
1248     WORD planes, bpp;
1249     DWORD compression, sizeImage;
1250     void *mapBits = NULL;
1251
1252     if (((bitmap_type = DIB_GetBitmapInfo( &bmi->bmiHeader, &width, &height,
1253                                            &planes, &bpp, &compression, &sizeImage )) == -1))
1254         return 0;
1255
1256     if (compression != BI_RGB && compression != BI_BITFIELDS)
1257     {
1258         TRACE("can't create a compressed (%u) dibsection\n", compression);
1259         return 0;
1260     }
1261
1262     if (!(dib = HeapAlloc( GetProcessHeap(), 0, sizeof(*dib) ))) return 0;
1263
1264     TRACE("format (%d,%d), planes %d, bpp %d, size %d, %s\n",
1265           width, height, planes, bpp, sizeImage, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1266
1267     dib->dsBm.bmType       = 0;
1268     dib->dsBm.bmWidth      = width;
1269     dib->dsBm.bmHeight     = height >= 0 ? height : -height;
1270     dib->dsBm.bmWidthBytes = DIB_GetDIBWidthBytes(width, bpp);
1271     dib->dsBm.bmPlanes     = planes;
1272     dib->dsBm.bmBitsPixel  = bpp;
1273     dib->dsBm.bmBits       = NULL;
1274
1275     if (!bitmap_type)  /* core header */
1276     {
1277         /* convert the BITMAPCOREHEADER to a BITMAPINFOHEADER */
1278         dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1279         dib->dsBmih.biWidth = width;
1280         dib->dsBmih.biHeight = height;
1281         dib->dsBmih.biPlanes = planes;
1282         dib->dsBmih.biBitCount = bpp;
1283         dib->dsBmih.biCompression = compression;
1284         dib->dsBmih.biXPelsPerMeter = 0;
1285         dib->dsBmih.biYPelsPerMeter = 0;
1286         dib->dsBmih.biClrUsed = 0;
1287         dib->dsBmih.biClrImportant = 0;
1288     }
1289     else
1290     {
1291         /* truncate extended bitmap headers (BITMAPV4HEADER etc.) */
1292         dib->dsBmih = bmi->bmiHeader;
1293         dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1294     }
1295
1296     /* set number of entries in bmi.bmiColors table */
1297     if( bpp <= 8 )
1298         dib->dsBmih.biClrUsed = 1 << bpp;
1299
1300     dib->dsBmih.biSizeImage = dib->dsBm.bmWidthBytes * dib->dsBm.bmHeight;
1301
1302     /* set dsBitfields values */
1303     if (usage == DIB_PAL_COLORS || bpp <= 8)
1304     {
1305         dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
1306     }
1307     else switch( bpp )
1308     {
1309     case 15:
1310     case 16:
1311         dib->dsBitfields[0] = (compression == BI_BITFIELDS) ? *(const DWORD *)bmi->bmiColors       : 0x7c00;
1312         dib->dsBitfields[1] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 1) : 0x03e0;
1313         dib->dsBitfields[2] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 2) : 0x001f;
1314         break;
1315     case 24:
1316     case 32:
1317         dib->dsBitfields[0] = (compression == BI_BITFIELDS) ? *(const DWORD *)bmi->bmiColors       : 0xff0000;
1318         dib->dsBitfields[1] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 1) : 0x00ff00;
1319         dib->dsBitfields[2] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 2) : 0x0000ff;
1320         break;
1321     }
1322
1323     /* get storage location for DIB bits */
1324
1325     if (section)
1326     {
1327         SYSTEM_INFO SystemInfo;
1328         DWORD mapOffset;
1329         INT mapSize;
1330
1331         GetSystemInfo( &SystemInfo );
1332         mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
1333         mapSize = dib->dsBmih.biSizeImage + (offset - mapOffset);
1334         mapBits = MapViewOfFile( section, FILE_MAP_ALL_ACCESS, 0, mapOffset, mapSize );
1335         if (mapBits) dib->dsBm.bmBits = (char *)mapBits + (offset - mapOffset);
1336     }
1337     else
1338     {
1339         offset = 0;
1340         dib->dsBm.bmBits = VirtualAlloc( NULL, dib->dsBmih.biSizeImage,
1341                                          MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
1342     }
1343     dib->dshSection = section;
1344     dib->dsOffset = offset;
1345
1346     if (!dib->dsBm.bmBits)
1347     {
1348         HeapFree( GetProcessHeap(), 0, dib );
1349         return 0;
1350     }
1351
1352     /* If the reference hdc is null, take the desktop dc */
1353     if (hdc == 0)
1354     {
1355         hdc = CreateCompatibleDC(0);
1356         bDesktopDC = TRUE;
1357     }
1358
1359     if (!(dc = get_dc_ptr( hdc ))) goto error;
1360
1361     /* create Device Dependent Bitmap and add DIB pointer */
1362     ret = CreateBitmap( dib->dsBm.bmWidth, dib->dsBm.bmHeight, 1,
1363                         (bpp == 1) ? 1 : GetDeviceCaps(hdc, BITSPIXEL), NULL );
1364
1365     if (ret && ((bmp = GDI_GetObjPtr(ret, BITMAP_MAGIC))))
1366     {
1367         bmp->dib = dib;
1368         bmp->funcs = dc->funcs;
1369         /* create local copy of DIB palette */
1370         if (bpp <= 8) DIB_CopyColorTable( dc, bmp, usage, bmi );
1371         GDI_ReleaseObj( ret );
1372
1373         if (dc->funcs->pCreateDIBSection)
1374         {
1375             if (!dc->funcs->pCreateDIBSection(dc->physDev, ret, bmi, usage))
1376             {
1377                 DeleteObject( ret );
1378                 ret = 0;
1379             }
1380         }
1381     }
1382
1383     release_dc_ptr( dc );
1384     if (bDesktopDC) DeleteDC( hdc );
1385     if (ret && bits) *bits = dib->dsBm.bmBits;
1386     return ret;
1387
1388 error:
1389     if (bDesktopDC) DeleteDC( hdc );
1390     if (section) UnmapViewOfFile( mapBits );
1391     else if (!offset) VirtualFree( dib->dsBm.bmBits, 0, MEM_RELEASE );
1392     HeapFree( GetProcessHeap(), 0, dib );
1393     return 0;
1394 }