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