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