- Extended support for BITMAPCOREINFO / BITMAPCOREHEADER structures.
[wine] / dlls / gdi / 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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
47   * You should never access the color table using the bmiColors member,
48     because the passed structure may have one of the extended headers
49     mentioned above. Use this to calculate the location:
50     
51     BITMAPINFO* info;
52     void* colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
53
54     
55   * More information:
56     Search for "Bitmap Structures" in MSDN
57 */
58
59 #include <stdarg.h>
60 #include <stdlib.h>
61 #include <string.h>
62
63 #include "windef.h"
64 #include "winbase.h"
65 #include "gdi.h"
66 #include "wownt32.h"
67 #include "gdi_private.h"
68 #include "wine/debug.h"
69
70 WINE_DEFAULT_DEBUG_CHANNEL(bitmap);
71
72
73 /*
74   Some of the following helper functions are duplicated in
75   dlls/x11drv/dib.c
76 */
77
78 /***********************************************************************
79  *           DIB_GetDIBWidthBytes
80  *
81  * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
82  * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/bitmaps_87eb.asp
83  */
84 int DIB_GetDIBWidthBytes( int width, int depth )
85 {
86     int words;
87
88     switch(depth)
89     {
90         case 1:  words = (width + 31) / 32; break;
91         case 4:  words = (width + 7) / 8; break;
92         case 8:  words = (width + 3) / 4; break;
93         case 15:
94         case 16: words = (width + 1) / 2; break;
95         case 24: words = (width * 3 + 3)/4; break;
96
97         default:
98             WARN("(%d): Unsupported depth\n", depth );
99         /* fall through */
100         case 32:
101                 words = width;
102     }
103     return 4 * words;
104 }
105
106 /***********************************************************************
107  *           DIB_GetDIBImageBytes
108  *
109  * Return the number of bytes used to hold the image in a DIB bitmap.
110  */
111 int DIB_GetDIBImageBytes( int width, int height, int depth )
112 {
113     return DIB_GetDIBWidthBytes( width, depth ) * abs( height );
114 }
115
116
117 /***********************************************************************
118  *           DIB_BitmapInfoSize
119  *
120  * Return the size of the bitmap info structure including color table.
121  */
122 int DIB_BitmapInfoSize( const BITMAPINFO * info, WORD coloruse )
123 {
124     int colors;
125
126     if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
127     {
128         BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)info;
129         colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
130         return sizeof(BITMAPCOREHEADER) + colors *
131              ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
132     }
133     else  /* assume BITMAPINFOHEADER */
134     {
135         colors = info->bmiHeader.biClrUsed;
136         if (!colors && (info->bmiHeader.biBitCount <= 8))
137             colors = 1 << info->bmiHeader.biBitCount;
138         return sizeof(BITMAPINFOHEADER) + colors *
139                ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
140     }
141 }
142
143
144 /***********************************************************************
145  *           DIB_GetBitmapInfo
146  *
147  * Get the info from a bitmap header.
148  * Return 1 for INFOHEADER, 0 for COREHEADER,
149  * 4 for V4HEADER, 5 for V5HEADER, -1 for error.
150  */
151 static int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
152                               LONG *height, WORD *bpp, DWORD *compr )
153 {
154     if (header->biSize == sizeof(BITMAPINFOHEADER))
155     {
156         *width  = header->biWidth;
157         *height = header->biHeight;
158         *bpp    = header->biBitCount;
159         *compr  = header->biCompression;
160         return 1;
161     }
162     if (header->biSize == sizeof(BITMAPCOREHEADER))
163     {
164         BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)header;
165         *width  = core->bcWidth;
166         *height = core->bcHeight;
167         *bpp    = core->bcBitCount;
168         *compr  = 0;
169         return 0;
170     }
171     if (header->biSize == sizeof(BITMAPV4HEADER))
172     {
173         BITMAPV4HEADER *v4hdr = (BITMAPV4HEADER *)header;
174         *width  = v4hdr->bV4Width;
175         *height = v4hdr->bV4Height;
176         *bpp    = v4hdr->bV4BitCount;
177         *compr  = v4hdr->bV4V4Compression;
178         return 4;
179     }
180     if (header->biSize == sizeof(BITMAPV5HEADER))
181     {
182         BITMAPV5HEADER *v5hdr = (BITMAPV5HEADER *)header;
183         *width  = v5hdr->bV5Width;
184         *height = v5hdr->bV5Height;
185         *bpp    = v5hdr->bV5BitCount;
186         *compr  = v5hdr->bV5Compression;
187         return 5;
188     }
189     ERR("(%ld): unknown/wrong size for header\n", header->biSize );
190     return -1;
191 }
192
193
194 /***********************************************************************
195  *           StretchDIBits   (GDI32.@)
196  */
197 INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst,
198                        INT heightDst, INT xSrc, INT ySrc, INT widthSrc,
199                        INT heightSrc, const void *bits,
200                        const BITMAPINFO *info, UINT wUsage, DWORD dwRop )
201 {
202     DC *dc;
203
204     if (!bits || !info)
205         return 0;
206
207     dc = DC_GetDCUpdate( hdc );
208     if(!dc) return FALSE;
209
210     if(dc->funcs->pStretchDIBits)
211     {
212         heightSrc = dc->funcs->pStretchDIBits(dc->physDev, xDst, yDst, widthDst,
213                                               heightDst, xSrc, ySrc, widthSrc,
214                                               heightSrc, bits, info, wUsage, dwRop);
215         GDI_ReleaseObj( hdc );
216     }
217     else /* use StretchBlt */
218     {
219         HBITMAP hBitmap, hOldBitmap;
220         HPALETTE hpal = NULL;
221         HDC hdcMem;
222         LONG height;
223         LONG width;
224         WORD bpp;
225         DWORD compr;
226
227         if (DIB_GetBitmapInfo( (BITMAPINFOHEADER*) info, &width, &height, &bpp, &compr ) == -1)
228         {
229             ERR("Invalid bitmap\n");
230             return 0;
231         }
232
233         if (width < 0)
234         {
235             ERR("Bitmap has a negative width\n");
236             return 0;
237         }
238
239         GDI_ReleaseObj( hdc );
240         hdcMem = CreateCompatibleDC( hdc );
241         hBitmap = CreateCompatibleBitmap(hdc, width, height);
242         hOldBitmap = SelectObject( hdcMem, hBitmap );
243         if(wUsage == DIB_PAL_COLORS)
244         {
245             hpal = GetCurrentObject(hdc, OBJ_PAL);
246             hpal = SelectPalette(hdcMem, hpal, FALSE);
247         }
248
249         if (info->bmiHeader.biCompression == BI_RLE4 ||
250             info->bmiHeader.biCompression == BI_RLE8) {
251
252            /* when RLE compression is used, there may be some gaps (ie the DIB doesn't
253             * contain all the rectangle described in bmiHeader, but only part of it.
254             * This mean that those undescribed pixels must be left untouched.
255             * So, we first copy on a memory bitmap the current content of the
256             * destination rectangle, blit the DIB bits on top of it - hence leaving
257             * the gaps untouched -, and blitting the rectangle back.
258             * This insure that gaps are untouched on the destination rectangle
259             * Not doing so leads to trashed images (the gaps contain what was on the
260             * memory bitmap => generally black or garbage)
261             * Unfortunately, RLE DIBs without gaps will be slowed down. But this is
262             * another speed vs correctness issue. Anyway, if speed is needed, then the
263             * pStretchDIBits function shall be implemented.
264             * ericP (2000/09/09)
265             */
266
267             /* copy existing bitmap from destination dc */
268             StretchBlt( hdcMem, xSrc, abs(height) - heightSrc - ySrc,
269                         widthSrc, heightSrc, hdc, xDst, yDst, widthDst, heightDst,
270                         dwRop );
271         }
272
273         SetDIBits(hdcMem, hBitmap, 0, height, bits, info, wUsage);
274
275         /* Origin for DIBitmap may be bottom left (positive biHeight) or top
276            left (negative biHeight) */
277         StretchBlt( hdc, xDst, yDst, widthDst, heightDst,
278                     hdcMem, xSrc, abs(height) - heightSrc - ySrc,
279                     widthSrc, heightSrc, dwRop );
280         if(hpal)
281             SelectPalette(hdcMem, hpal, FALSE);
282         SelectObject( hdcMem, hOldBitmap );
283         DeleteDC( hdcMem );
284         DeleteObject( hBitmap );
285     }
286     return heightSrc;
287 }
288
289
290 /******************************************************************************
291  * SetDIBits [GDI32.@]
292  *
293  * Sets pixels in a bitmap using colors from DIB.
294  *
295  * PARAMS
296  *    hdc       [I] Handle to device context
297  *    hbitmap   [I] Handle to bitmap
298  *    startscan [I] Starting scan line
299  *    lines     [I] Number of scan lines
300  *    bits      [I] Array of bitmap bits
301  *    info      [I] Address of structure with data
302  *    coloruse  [I] Type of color indexes to use
303  *
304  * RETURNS
305  *    Success: Number of scan lines copied
306  *    Failure: 0
307  */
308 INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
309                       UINT lines, LPCVOID bits, const BITMAPINFO *info,
310                       UINT coloruse )
311 {
312     DC *dc;
313     BITMAPOBJ *bitmap;
314     INT result = 0;
315
316     if (!(bitmap = GDI_GetObjPtr( hbitmap, BITMAP_MAGIC ))) return 0;
317
318     if (!(dc = DC_GetDCUpdate( hdc )))
319     {
320         if (coloruse == DIB_RGB_COLORS) FIXME( "shouldn't require a DC for DIB_RGB_COLORS\n" );
321         GDI_ReleaseObj( hbitmap );
322         return 0;
323     }
324
325     if (!bitmap->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) goto done;
326
327     if (bitmap->funcs && bitmap->funcs->pSetDIBits)
328         result = bitmap->funcs->pSetDIBits( dc->physDev, hbitmap, startscan, lines,
329                                             bits, info, coloruse );
330     else
331         result = lines;
332
333  done:
334     GDI_ReleaseObj( hdc );
335     GDI_ReleaseObj( hbitmap );
336     return result;
337 }
338
339
340 /***********************************************************************
341  *           SetDIBitsToDevice   (GDI32.@)
342  */
343 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
344                            DWORD cy, INT xSrc, INT ySrc, UINT startscan,
345                            UINT lines, LPCVOID bits, const BITMAPINFO *info,
346                            UINT coloruse )
347 {
348     INT ret;
349     DC *dc;
350
351     if (!(dc = DC_GetDCUpdate( hdc ))) return 0;
352
353     if(dc->funcs->pSetDIBitsToDevice)
354         ret = dc->funcs->pSetDIBitsToDevice( dc->physDev, xDest, yDest, cx, cy, xSrc,
355                                              ySrc, startscan, lines, bits,
356                                              info, coloruse );
357     else {
358         FIXME("unimplemented on hdc %p\n", hdc);
359         ret = 0;
360     }
361
362     GDI_ReleaseObj( hdc );
363     return ret;
364 }
365
366 /***********************************************************************
367  *           SetDIBColorTable    (GDI32.@)
368  */
369 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, CONST RGBQUAD *colors )
370 {
371     DC * dc;
372     UINT result = 0;
373
374     if (!(dc = DC_GetDCUpdate( hdc ))) return 0;
375
376     if (dc->funcs->pSetDIBColorTable)
377         result = dc->funcs->pSetDIBColorTable(dc->physDev, startpos, entries, colors);
378
379     GDI_ReleaseObj( hdc );
380     return result;
381 }
382
383
384 /***********************************************************************
385  *           GetDIBColorTable    (GDI32.@)
386  */
387 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
388 {
389     DC * dc;
390     UINT result = 0;
391
392     if (!(dc = DC_GetDCUpdate( hdc ))) return 0;
393
394     if (dc->funcs->pGetDIBColorTable)
395         result = dc->funcs->pGetDIBColorTable(dc->physDev, startpos, entries, colors);
396
397     GDI_ReleaseObj( hdc );
398     return result;
399 }
400
401 /* FIXME the following two structs should be combined with __sysPalTemplate in
402    objects/color.c - this should happen after de-X11-ing both of these
403    files.
404    NB. RGBQUAD and PALETTEENTRY have different orderings of red, green
405    and blue - sigh */
406
407 static RGBQUAD EGAColorsQuads[16] = {
408 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
409     { 0x00, 0x00, 0x00, 0x00 },
410     { 0x00, 0x00, 0x80, 0x00 },
411     { 0x00, 0x80, 0x00, 0x00 },
412     { 0x00, 0x80, 0x80, 0x00 },
413     { 0x80, 0x00, 0x00, 0x00 },
414     { 0x80, 0x00, 0x80, 0x00 },
415     { 0x80, 0x80, 0x00, 0x00 },
416     { 0x80, 0x80, 0x80, 0x00 },
417     { 0xc0, 0xc0, 0xc0, 0x00 },
418     { 0x00, 0x00, 0xff, 0x00 },
419     { 0x00, 0xff, 0x00, 0x00 },
420     { 0x00, 0xff, 0xff, 0x00 },
421     { 0xff, 0x00, 0x00, 0x00 },
422     { 0xff, 0x00, 0xff, 0x00 },
423     { 0xff, 0xff, 0x00, 0x00 },
424     { 0xff, 0xff, 0xff, 0x00 }
425 };
426
427 static RGBTRIPLE EGAColorsTriples[16] = {
428 /* rgbBlue, rgbGreen, rgbRed */
429     { 0x00, 0x00, 0x00 },
430     { 0x00, 0x00, 0x80 },
431     { 0x00, 0x80, 0x00 },
432     { 0x00, 0x80, 0x80 },
433     { 0x80, 0x00, 0x00 },
434     { 0x80, 0x00, 0x80 },
435     { 0x80, 0x80, 0x00 },
436     { 0x80, 0x80, 0x80 },
437     { 0xc0, 0xc0, 0xc0 },
438     { 0x00, 0x00, 0xff },
439     { 0x00, 0xff, 0x00 },
440     { 0x00, 0xff, 0xff },
441     { 0xff, 0x00, 0x00 } ,
442     { 0xff, 0x00, 0xff },
443     { 0xff, 0xff, 0x00 },
444     { 0xff, 0xff, 0xff }
445 };
446
447 static RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
448 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
449     { 0x00, 0x00, 0x00, 0x00 },
450     { 0x00, 0x00, 0x80, 0x00 },
451     { 0x00, 0x80, 0x00, 0x00 },
452     { 0x00, 0x80, 0x80, 0x00 },
453     { 0x80, 0x00, 0x00, 0x00 },
454     { 0x80, 0x00, 0x80, 0x00 },
455     { 0x80, 0x80, 0x00, 0x00 },
456     { 0xc0, 0xc0, 0xc0, 0x00 },
457     { 0xc0, 0xdc, 0xc0, 0x00 },
458     { 0xf0, 0xca, 0xa6, 0x00 },
459     { 0xf0, 0xfb, 0xff, 0x00 },
460     { 0xa4, 0xa0, 0xa0, 0x00 },
461     { 0x80, 0x80, 0x80, 0x00 },
462     { 0x00, 0x00, 0xf0, 0x00 },
463     { 0x00, 0xff, 0x00, 0x00 },
464     { 0x00, 0xff, 0xff, 0x00 },
465     { 0xff, 0x00, 0x00, 0x00 },
466     { 0xff, 0x00, 0xff, 0x00 },
467     { 0xff, 0xff, 0x00, 0x00 },
468     { 0xff, 0xff, 0xff, 0x00 }
469 };
470
471 static RGBTRIPLE DefLogPaletteTriples[20] = { /* Copy of Default Logical Palette */
472 /* rgbBlue, rgbGreen, rgbRed */
473     { 0x00, 0x00, 0x00 },
474     { 0x00, 0x00, 0x80 },
475     { 0x00, 0x80, 0x00 },
476     { 0x00, 0x80, 0x80 },
477     { 0x80, 0x00, 0x00 },
478     { 0x80, 0x00, 0x80 },
479     { 0x80, 0x80, 0x00 },
480     { 0xc0, 0xc0, 0xc0 },
481     { 0xc0, 0xdc, 0xc0 },
482     { 0xf0, 0xca, 0xa6 },
483     { 0xf0, 0xfb, 0xff },
484     { 0xa4, 0xa0, 0xa0 },
485     { 0x80, 0x80, 0x80 },
486     { 0x00, 0x00, 0xf0 },
487     { 0x00, 0xff, 0x00 },
488     { 0x00, 0xff, 0xff },
489     { 0xff, 0x00, 0x00 },
490     { 0xff, 0x00, 0xff },
491     { 0xff, 0xff, 0x00 },
492     { 0xff, 0xff, 0xff}
493 };
494
495
496 /******************************************************************************
497  * GetDIBits [GDI32.@]
498  *
499  * Retrieves bits of bitmap and copies to buffer.
500  *
501  * RETURNS
502  *    Success: Number of scan lines copied from bitmap
503  *    Failure: 0
504  *
505  * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/bitmaps_87eb.asp
506  */
507 INT WINAPI GetDIBits(
508     HDC hdc,         /* [in]  Handle to device context */
509     HBITMAP hbitmap, /* [in]  Handle to bitmap */
510     UINT startscan,  /* [in]  First scan line to set in dest bitmap */
511     UINT lines,      /* [in]  Number of scan lines to copy */
512     LPVOID bits,       /* [out] Address of array for bitmap bits */
513     BITMAPINFO * info, /* [out] Address of structure with bitmap data */
514     UINT coloruse)   /* [in]  RGB or palette index */
515 {
516     DC * dc;
517     BITMAPOBJ * bmp;
518     int i;
519     HDC memdc;
520     int bitmap_type;
521     BOOL core_header;
522     LONG width;
523     LONG height;
524     WORD bpp;
525     DWORD compr;
526     void* colorPtr;
527     RGBTRIPLE* rgbTriples;
528     RGBQUAD* rgbQuads;
529
530     if (!info) return 0;
531
532     bitmap_type = DIB_GetBitmapInfo( (BITMAPINFOHEADER*) info, &width, &height, &bpp, &compr);
533     if (bitmap_type == -1)
534     {
535         ERR("Invalid bitmap format\n");
536         return 0;
537     }
538     core_header = (bitmap_type == 0);
539     memdc = CreateCompatibleDC(hdc);
540     if (!(dc = DC_GetDCUpdate( hdc )))
541     {
542         DeleteDC(memdc);
543         return 0;
544     }
545     if (!(bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
546     {
547         GDI_ReleaseObj( hdc );
548         DeleteDC(memdc);
549         return 0;
550     }
551
552     colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
553     rgbTriples = (RGBTRIPLE *) colorPtr;
554     rgbQuads = (RGBQUAD *) colorPtr;
555
556     /* Transfer color info */
557
558     if (bpp <= 8 && bpp > 0)
559     {
560         if (!core_header) info->bmiHeader.biClrUsed = 0;
561
562         /* If the bitmap object already has a dib section at the
563            same color depth then get the color map from it */
564         if (bmp->dib && bmp->dib->dsBm.bmBitsPixel == bpp) {
565             if(coloruse == DIB_RGB_COLORS) {
566                 HBITMAP oldbm = SelectObject(memdc, hbitmap);
567                 unsigned int colors = 1 << bpp;
568
569                 if (core_header)
570                 {
571                     /* Convert the color table (RGBQUAD to RGBTRIPLE) */                    
572                     RGBQUAD* buffer = HeapAlloc(GetProcessHeap(), 0, colors * sizeof(RGBQUAD));
573
574                     if (buffer)
575                     {
576                         RGBTRIPLE* index = rgbTriples;
577                         GetDIBColorTable(memdc, 0, colors, buffer);
578
579                         for (i=0; i < colors; i++, index++)
580                         {
581                             index->rgbtRed   = buffer[i].rgbRed;
582                             index->rgbtGreen = buffer[i].rgbGreen;
583                             index->rgbtBlue  = buffer[i].rgbBlue;
584                         }
585
586                         HeapFree(GetProcessHeap(), 0, buffer);
587                     }
588                 }
589                 else
590                 {
591                     GetDIBColorTable(memdc, 0, colors, colorPtr);
592                 }
593                 SelectObject(memdc, oldbm);
594             }
595             else {
596                 WORD *index = colorPtr;
597                 for(i = 0; i < 1 << info->bmiHeader.biBitCount; i++, index++)
598                     *index = i;
599             }
600         }
601         else {
602             if(bpp >= bmp->bitmap.bmBitsPixel) {
603                 /* Generate the color map from the selected palette */
604                 PALETTEENTRY * palEntry;
605                 PALETTEOBJ * palette;
606                 if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->hPalette, PALETTE_MAGIC ))) {
607                     GDI_ReleaseObj( hdc );
608                     GDI_ReleaseObj( hbitmap );
609                     DeleteDC(memdc);
610                     return 0;
611                 }
612                 palEntry = palette->logpalette.palPalEntry;
613                 for (i = 0; i < (1 << bmp->bitmap.bmBitsPixel); i++, palEntry++) {
614                     if (coloruse == DIB_RGB_COLORS) {
615                         if (core_header)
616                         {
617                             rgbTriples[i].rgbtRed   = palEntry->peRed;
618                             rgbTriples[i].rgbtGreen = palEntry->peGreen;
619                             rgbTriples[i].rgbtBlue  = palEntry->peBlue;
620                         }
621                         else
622                         {
623                             rgbQuads[i].rgbRed      = palEntry->peRed;
624                             rgbQuads[i].rgbGreen    = palEntry->peGreen;
625                             rgbQuads[i].rgbBlue     = palEntry->peBlue;
626                             rgbQuads[i].rgbReserved = 0;
627                         }
628                     }
629                     else ((WORD *)colorPtr)[i] = (WORD)i;
630                 }
631                 GDI_ReleaseObj( dc->hPalette );
632             } else {
633                 switch (bpp) {
634                 case 1:
635                     if (core_header)
636                     {
637                         rgbTriples[0].rgbtRed = rgbTriples[0].rgbtGreen =
638                             rgbTriples[0].rgbtBlue = 0;
639                         rgbTriples[1].rgbtRed = rgbTriples[1].rgbtGreen =
640                             rgbTriples[1].rgbtBlue = 0xff;
641                     }
642                     else
643                     {    
644                         rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen =
645                             rgbQuads[0].rgbBlue = 0;
646                         rgbQuads[0].rgbReserved = 0;
647                         rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen =
648                             rgbQuads[1].rgbBlue = 0xff;
649                         rgbQuads[1].rgbReserved = 0;
650                     }
651                     break;
652
653                 case 4:
654                     if (core_header)
655                         memcpy(colorPtr, EGAColorsTriples, sizeof(EGAColorsTriples));
656                     else
657                         memcpy(colorPtr, EGAColorsQuads, sizeof(EGAColorsQuads));
658
659                     break;
660
661                 case 8:
662                     {
663                         if (core_header)
664                         {
665                             INT r, g, b;
666                             RGBTRIPLE *color;
667
668                             memcpy(rgbTriples, DefLogPaletteTriples,
669                                        10 * sizeof(RGBTRIPLE));
670                             memcpy(rgbTriples + 246, DefLogPaletteTriples + 10,
671                                        10 * sizeof(RGBTRIPLE));
672                             color = rgbTriples + 10;
673                             for(r = 0; r <= 5; r++) /* FIXME */
674                                 for(g = 0; g <= 5; g++)
675                                     for(b = 0; b <= 5; b++) {
676                                         color->rgbtRed =   (r * 0xff) / 5;
677                                         color->rgbtGreen = (g * 0xff) / 5;
678                                         color->rgbtBlue =  (b * 0xff) / 5;
679                                         color++;
680                                     }
681                         }
682                         else
683                         {
684                             INT r, g, b;
685                             RGBQUAD *color;
686
687                             memcpy(rgbQuads, DefLogPaletteQuads,
688                                        10 * sizeof(RGBQUAD));
689                             memcpy(rgbQuads + 246, DefLogPaletteQuads + 10,
690                                    10 * sizeof(RGBQUAD));
691                             color = rgbQuads + 10;
692                             for(r = 0; r <= 5; r++) /* FIXME */
693                                 for(g = 0; g <= 5; g++)
694                                     for(b = 0; b <= 5; b++) {
695                                         color->rgbRed =   (r * 0xff) / 5;
696                                         color->rgbGreen = (g * 0xff) / 5;
697                                         color->rgbBlue =  (b * 0xff) / 5;
698                                         color->rgbReserved = 0;
699                                         color++;
700                                     }
701                         }
702                     }
703                 }
704             }
705         }
706     }
707
708     if (bits && lines)
709     {
710         /* If the bitmap object already have a dib section that contains image data, get the bits from it */
711         if(bmp->dib && bmp->dib->dsBm.bmBitsPixel >= 15 && bpp >= 15)
712         {
713             /*FIXME: Only RGB dibs supported for now */
714             unsigned int srcwidth = bmp->dib->dsBm.bmWidth, srcwidthb = bmp->dib->dsBm.bmWidthBytes;
715             unsigned int dstwidth = width;
716             int dstwidthb = DIB_GetDIBWidthBytes( width, bpp );
717             LPBYTE dbits = bits, sbits = (LPBYTE) bmp->dib->dsBm.bmBits + (startscan * srcwidthb);
718             unsigned int x, y, width, widthb;
719
720             if ((height < 0) ^ (bmp->dib->dsBmih.biHeight < 0))
721             {
722                 dbits = (LPBYTE)bits + (dstwidthb * (lines-1));
723                 dstwidthb = -dstwidthb;
724             }
725
726             switch( bpp ) {
727
728             case 15:
729             case 16: /* 16 bpp dstDIB */
730                 {
731                     LPWORD dstbits = (LPWORD)dbits;
732                     WORD rmask = 0x7c00, gmask= 0x03e0, bmask = 0x001f;
733
734                     /* FIXME: BI_BITFIELDS not supported yet */
735
736                     switch(bmp->dib->dsBm.bmBitsPixel) {
737
738                     case 16: /* 16 bpp srcDIB -> 16 bpp dstDIB */
739                         {
740                             widthb = min(srcwidthb, abs(dstwidthb));
741                             /* FIXME: BI_BITFIELDS not supported yet */
742                             for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
743                                 memcpy(dbits, sbits, widthb);
744                         }
745                         break;
746
747                     case 24: /* 24 bpp srcDIB -> 16 bpp dstDIB */
748                         {
749                             LPBYTE srcbits = sbits;
750
751                             width = min(srcwidth, dstwidth);
752                             for( y = 0; y < lines; y++) {
753                                 for( x = 0; x < width; x++, srcbits += 3)
754                                     *dstbits++ = ((srcbits[0] >> 3) & bmask) |
755                                                  (((WORD)srcbits[1] << 2) & gmask) |
756                                                  (((WORD)srcbits[2] << 7) & rmask);
757
758                                 dstbits = (LPWORD)(dbits+=dstwidthb);
759                                 srcbits = (sbits += srcwidthb);
760                             }
761                         }
762                         break;
763
764                     case 32: /* 32 bpp srcDIB -> 16 bpp dstDIB */
765                         {
766                             LPDWORD srcbits = (LPDWORD)sbits;
767                             DWORD val;
768
769                             width = min(srcwidth, dstwidth);
770                             for( y = 0; y < lines; y++) {
771                                 for( x = 0; x < width; x++ ) {
772                                     val = *srcbits++;
773                                     *dstbits++ = (WORD)(((val >> 3) & bmask) | ((val >> 6) & gmask) |
774                                                        ((val >> 9) & rmask));
775                                 }
776                                 dstbits = (LPWORD)(dbits+=dstwidthb);
777                                 srcbits = (LPDWORD)(sbits+=srcwidthb);
778                             }
779                         }
780                         break;
781
782                     default: /* ? bit bmp -> 16 bit DIB */
783                         FIXME("15/16 bit DIB %d bit bitmap\n",
784                         bmp->bitmap.bmBitsPixel);
785                         break;
786                     }
787                 }
788                 break;
789
790             case 24: /* 24 bpp dstDIB */
791                 {
792                     LPBYTE dstbits = dbits;
793
794                     switch(bmp->dib->dsBm.bmBitsPixel) {
795
796                     case 16: /* 16 bpp srcDIB -> 24 bpp dstDIB */
797                         {
798                             LPWORD srcbits = (LPWORD)sbits;
799                             WORD val;
800
801                             width = min(srcwidth, dstwidth);
802                             /* FIXME: BI_BITFIELDS not supported yet */
803                             for( y = 0; y < lines; y++) {
804                                 for( x = 0; x < width; x++ ) {
805                                     val = *srcbits++;
806                                     *dstbits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07));
807                                     *dstbits++ = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07));
808                                     *dstbits++ = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07));
809                                 }
810                                 dstbits = (LPBYTE)(dbits+=dstwidthb);
811                                 srcbits = (LPWORD)(sbits+=srcwidthb);
812                             }
813                         }
814                         break;
815
816                     case 24: /* 24 bpp srcDIB -> 24 bpp dstDIB */
817                         {
818                             widthb = min(srcwidthb, abs(dstwidthb));
819                             for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
820                                 memcpy(dbits, sbits, widthb);
821                         }
822                         break;
823
824                     case 32: /* 32 bpp srcDIB -> 24 bpp dstDIB */
825                         {
826                             LPBYTE srcbits = (LPBYTE)sbits;
827
828                             width = min(srcwidth, dstwidth);
829                             for( y = 0; y < lines; y++) {
830                                 for( x = 0; x < width; x++, srcbits++ ) {
831                                     *dstbits++ = *srcbits++;
832                                     *dstbits++ = *srcbits++;
833                                     *dstbits++ = *srcbits++;
834                                 }
835                                 dstbits=(LPBYTE)(dbits+=dstwidthb);
836                                 srcbits = (LPBYTE)(sbits+=srcwidthb);
837                             }
838                         }
839                         break;
840
841                     default: /* ? bit bmp -> 24 bit DIB */
842                         FIXME("24 bit DIB %d bit bitmap\n",
843                               bmp->bitmap.bmBitsPixel);
844                         break;
845                     }
846                 }
847                 break;
848
849             case 32: /* 32 bpp dstDIB */
850                 {
851                     LPDWORD dstbits = (LPDWORD)dbits;
852
853                     /* FIXME: BI_BITFIELDS not supported yet */
854
855                     switch(bmp->dib->dsBm.bmBitsPixel) {
856                         case 16: /* 16 bpp srcDIB -> 32 bpp dstDIB */
857                         {
858                             LPWORD srcbits = (LPWORD)sbits;
859                             DWORD val;
860
861                             width = min(srcwidth, dstwidth);
862                             /* FIXME: BI_BITFIELDS not supported yet */
863                             for( y = 0; y < lines; y++) {
864                                 for( x = 0; x < width; x++ ) {
865                                     val = (DWORD)*srcbits++;
866                                     *dstbits++ = ((val << 3) & 0xf8) | ((val >> 2) & 0x07) |
867                                                  ((val << 6) & 0xf800) | ((val << 1) & 0x0700) |
868                                                  ((val << 9) & 0xf80000) | ((val << 4) & 0x070000);
869                                 }
870                                 dstbits=(LPDWORD)(dbits+=dstwidthb);
871                                 srcbits=(LPWORD)(sbits+=srcwidthb);
872                             }
873                         }
874                         break;
875
876                     case 24: /* 24 bpp srcDIB -> 32 bpp dstDIB */
877                         {
878                             LPBYTE srcbits = sbits;
879
880                             width = min(srcwidth, dstwidth);
881                             for( y = 0; y < lines; y++) {
882                                 for( x = 0; x < width; x++, srcbits+=3 )
883                                     *dstbits++ = ((DWORD)*srcbits) & 0x00ffffff;
884                                 dstbits=(LPDWORD)(dbits+=dstwidthb);
885                                 srcbits=(sbits+=srcwidthb);
886                             }
887                         }
888                         break;
889
890                     case 32: /* 32 bpp srcDIB -> 32 bpp dstDIB */
891                         {
892                             widthb = min(srcwidthb, abs(dstwidthb));
893                             /* FIXME: BI_BITFIELDS not supported yet */
894                             for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb) {
895                                 memcpy(dbits, sbits, widthb);
896                             }
897                         }
898                         break;
899
900                     default: /* ? bit bmp -> 32 bit DIB */
901                         FIXME("32 bit DIB %d bit bitmap\n",
902                         bmp->bitmap.bmBitsPixel);
903                         break;
904                     }
905                 }
906                 break;
907
908             default: /* ? bit DIB */
909                 FIXME("Unsupported DIB depth %d\n", info->bmiHeader.biBitCount);
910                 break;
911             }
912         }
913         /* Otherwise, get bits from the XImage */
914         else
915         {
916             if (!bmp->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) lines = 0;
917             else
918             {
919                 if (bmp->funcs && bmp->funcs->pGetDIBits)
920                     lines = bmp->funcs->pGetDIBits( dc->physDev, hbitmap, startscan,
921                                                     lines, bits, info, coloruse );
922                 else
923                     lines = 0;  /* FIXME: should copy from bmp->bitmap.bmBits */
924             }
925         }
926     }
927     else
928     {
929         /* fill in struct members */
930
931         if (bpp == 0)
932         {
933             if (core_header)
934             {
935                 BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) info;
936                 coreheader->bcWidth = bmp->bitmap.bmWidth;
937                 coreheader->bcHeight = bmp->bitmap.bmHeight;
938                 coreheader->bcPlanes = 1;
939                 coreheader->bcBitCount = bmp->bitmap.bmBitsPixel;
940             }
941             else
942             {
943                 info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
944                 info->bmiHeader.biHeight = bmp->bitmap.bmHeight;
945                 info->bmiHeader.biPlanes = 1;
946                 info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
947                 info->bmiHeader.biSizeImage =
948                                  DIB_GetDIBImageBytes( bmp->bitmap.bmWidth,
949                                                        bmp->bitmap.bmHeight,
950                                                        bmp->bitmap.bmBitsPixel );
951                 info->bmiHeader.biCompression = 0;
952             }
953             lines = abs(bmp->bitmap.bmHeight);
954         }
955     }
956
957     if (!core_header)
958     {
959         TRACE("biSizeImage = %ld, ", info->bmiHeader.biSizeImage);
960     }
961     TRACE("biWidth = %ld, biHeight = %ld\n", width, height);
962
963     GDI_ReleaseObj( hdc );
964     GDI_ReleaseObj( hbitmap );
965     DeleteDC(memdc);
966     return lines;
967 }
968
969
970 /***********************************************************************
971  *           CreateDIBitmap    (GDI32.@)
972  *
973  * Creates a DDB (device dependent bitmap) from a DIB.
974  * The DDB will have the same color depth as the reference DC.
975  */
976 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
977                             DWORD init, LPCVOID bits, const BITMAPINFO *data,
978                             UINT coloruse )
979 {
980     HBITMAP handle;
981     LONG width;
982     LONG height;
983     WORD bpp;
984     DWORD compr;
985     DC *dc;
986
987     if (DIB_GetBitmapInfo( header, &width, &height, &bpp, &compr ) == -1) return 0;
988     
989     if (width < 0)
990     {
991         TRACE("Bitmap has a negative width\n");
992         return 0;
993     }
994     
995     /* Top-down DIBs have a negative height */
996     if (height < 0) height = -height;
997
998     TRACE("hdc=%p, header=%p, init=%lu, bits=%p, data=%p, coloruse=%u (bitmap: width=%ld, height=%ld, bpp=%u, compr=%lu)\n",
999            hdc, header, init, bits, data, coloruse, width, height, bpp, compr);
1000     
1001     if (hdc == NULL)
1002         handle = CreateBitmap( width, height, 1, 1, NULL );
1003     else
1004         handle = CreateCompatibleBitmap( hdc, width, height );
1005
1006     if (handle)
1007     {
1008         if (init == CBM_INIT) SetDIBits( hdc, handle, 0, height, bits, data, coloruse );
1009
1010         else if (hdc && ((dc = DC_GetDCPtr( hdc )) != NULL) )
1011         {
1012             if (!BITMAP_SetOwnerDC( handle, dc ))
1013             {
1014                 DeleteObject( handle );
1015                 handle = 0;
1016             }
1017             GDI_ReleaseObj( hdc );
1018         }
1019     }
1020
1021     return handle;
1022 }
1023
1024 /***********************************************************************
1025  *           CreateDIBSection    (GDI.489)
1026  */
1027 HBITMAP16 WINAPI CreateDIBSection16 (HDC16 hdc, const BITMAPINFO *bmi, UINT16 usage,
1028                                      SEGPTR *bits16, HANDLE section, DWORD offset)
1029 {
1030     LPVOID bits32;
1031     HBITMAP hbitmap;
1032
1033     hbitmap = CreateDIBSection( HDC_32(hdc), bmi, usage, &bits32, section, offset );
1034     if (hbitmap)
1035     {
1036         BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr(hbitmap, BITMAP_MAGIC);
1037         if (bmp && bmp->dib && bits32)
1038         {
1039             const BITMAPINFOHEADER *bi = &bmi->bmiHeader;
1040             LONG width, height;
1041             WORD bpp;
1042             DWORD compr;
1043             BOOL core_header;
1044             INT width_bytes;
1045             INT size;
1046             WORD count, sel;
1047             int i;
1048
1049             core_header = (DIB_GetBitmapInfo(bi, &width, &height, &bpp, &compr) == 0);
1050
1051             height = height >= 0 ? height : -height;
1052             width_bytes = DIB_GetDIBWidthBytes(width, bpp);
1053             
1054             if (core_header)
1055             {
1056                 size = width_bytes * height;
1057             }
1058             else
1059             {
1060                 size = (bi->biSizeImage && compr != BI_RGB) ?
1061                         bi->biSizeImage : width_bytes * height;
1062             }
1063
1064             /* calculate number of sel's needed for size with 64K steps */
1065             count = (size + 0xffff) / 0x10000;
1066             sel = AllocSelectorArray16(count);
1067
1068             for (i = 0; i < count; i++)
1069             {
1070                 SetSelectorBase(sel + (i << __AHSHIFT), (DWORD)bits32 + i * 0x10000);
1071                 SetSelectorLimit16(sel + (i << __AHSHIFT), size - 1); /* yep, limit is correct */
1072                 size -= 0x10000;
1073             }
1074             bmp->segptr_bits = MAKESEGPTR( sel, 0 );
1075             if (bits16) *bits16 = bmp->segptr_bits;
1076         }
1077         if (bmp) GDI_ReleaseObj( hbitmap );
1078     }
1079     return HBITMAP_16(hbitmap);
1080 }
1081
1082 /***********************************************************************
1083  *           DIB_CreateDIBSection
1084  */
1085 HBITMAP DIB_CreateDIBSection(HDC hdc, const BITMAPINFO *bmi, UINT usage,
1086                              VOID **bits, HANDLE section,
1087                              DWORD offset, DWORD ovr_pitch)
1088 {
1089     HBITMAP hbitmap = 0;
1090     DC *dc;
1091     BOOL bDesktopDC = FALSE;
1092
1093     /* If the reference hdc is null, take the desktop dc */
1094     if (hdc == 0)
1095     {
1096         hdc = CreateCompatibleDC(0);
1097         bDesktopDC = TRUE;
1098     }
1099
1100     if ((dc = DC_GetDCPtr( hdc )))
1101     {
1102         if(dc->funcs->pCreateDIBSection)
1103             hbitmap = dc->funcs->pCreateDIBSection(dc->physDev, bmi, usage, bits, section, offset, ovr_pitch);
1104         GDI_ReleaseObj(hdc);
1105     }
1106
1107     if (bDesktopDC)
1108       DeleteDC(hdc);
1109
1110     return hbitmap;
1111 }
1112
1113 /***********************************************************************
1114  *           CreateDIBSection    (GDI32.@)
1115  */
1116 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
1117                                 VOID **bits, HANDLE section,
1118                                 DWORD offset)
1119 {
1120     return DIB_CreateDIBSection(hdc, bmi, usage, bits, section, offset, 0);
1121 }