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