shell32/explorer: Support different structure sizes in Shell_NotifyIcon.
[wine/gsoc_dplay.git] / dlls / gdi32 / dib.c
blob7b9ef6d9bf942770060b4f1fed1d876531a4a100
1 /*
2 * GDI device-independent bitmaps
4 * Copyright 1993,1994 Alexandre Julliard
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.
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.
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
22 Important information:
24 * Current Windows versions support two different DIB structures:
26 - BITMAPCOREINFO / BITMAPCOREHEADER (legacy structures; used in OS/2)
27 - BITMAPINFO / BITMAPINFOHEADER
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.
35 * The palettes are stored in different formats:
37 - BITMAPCOREINFO: Array of RGBTRIPLE
38 - BITMAPINFO: Array of RGBQUAD
41 * There are even more DIB headers, but they all extend BITMAPINFOHEADER:
43 - BITMAPV4HEADER: Introduced in Windows 95 / NT 4.0
44 - BITMAPV5HEADER: Introduced in Windows 98 / 2000
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.
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:
55 BITMAPINFO* info;
56 void* colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
59 * More information:
60 Search for "Bitmap Structures" in MSDN
63 #include <stdarg.h>
64 #include <stdlib.h>
65 #include <string.h>
67 #include "windef.h"
68 #include "winbase.h"
69 #include "wownt32.h"
70 #include "gdi_private.h"
71 #include "wine/debug.h"
73 WINE_DEFAULT_DEBUG_CHANNEL(bitmap);
77 Some of the following helper functions are duplicated in
78 dlls/x11drv/dib.c
81 /***********************************************************************
82 * DIB_GetDIBWidthBytes
84 * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
85 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/bitmaps_87eb.asp
87 int DIB_GetDIBWidthBytes( int width, int depth )
89 int words;
91 switch(depth)
93 case 1: words = (width + 31) / 32; break;
94 case 4: words = (width + 7) / 8; break;
95 case 8: words = (width + 3) / 4; break;
96 case 15:
97 case 16: words = (width + 1) / 2; break;
98 case 24: words = (width * 3 + 3)/4; break;
100 default:
101 WARN("(%d): Unsupported depth\n", depth );
102 /* fall through */
103 case 32:
104 words = width;
106 return 4 * words;
109 /***********************************************************************
110 * DIB_GetDIBImageBytes
112 * Return the number of bytes used to hold the image in a DIB bitmap.
114 int DIB_GetDIBImageBytes( int width, int height, int depth )
116 return DIB_GetDIBWidthBytes( width, depth ) * abs( height );
120 /***********************************************************************
121 * DIB_BitmapInfoSize
123 * Return the size of the bitmap info structure including color table.
125 int DIB_BitmapInfoSize( const BITMAPINFO * info, WORD coloruse )
127 int colors;
129 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
131 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
132 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
133 return sizeof(BITMAPCOREHEADER) + colors *
134 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
136 else /* assume BITMAPINFOHEADER */
138 colors = info->bmiHeader.biClrUsed;
139 if (colors > 256) colors = 256;
140 if (!colors && (info->bmiHeader.biBitCount <= 8))
141 colors = 1 << info->bmiHeader.biBitCount;
142 return sizeof(BITMAPINFOHEADER) + colors *
143 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
148 /***********************************************************************
149 * DIB_GetBitmapInfo
151 * Get the info from a bitmap header.
152 * Return 1 for INFOHEADER, 0 for COREHEADER,
153 * 4 for V4HEADER, 5 for V5HEADER, -1 for error.
155 static int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
156 LONG *height, WORD *planes, WORD *bpp, DWORD *compr, DWORD *size )
158 if (header->biSize == sizeof(BITMAPINFOHEADER))
160 *width = header->biWidth;
161 *height = header->biHeight;
162 *planes = header->biPlanes;
163 *bpp = header->biBitCount;
164 *compr = header->biCompression;
165 *size = header->biSizeImage;
166 return 1;
168 if (header->biSize == sizeof(BITMAPCOREHEADER))
170 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)header;
171 *width = core->bcWidth;
172 *height = core->bcHeight;
173 *planes = core->bcPlanes;
174 *bpp = core->bcBitCount;
175 *compr = 0;
176 *size = 0;
177 return 0;
179 if (header->biSize == sizeof(BITMAPV4HEADER))
181 const BITMAPV4HEADER *v4hdr = (const BITMAPV4HEADER *)header;
182 *width = v4hdr->bV4Width;
183 *height = v4hdr->bV4Height;
184 *planes = v4hdr->bV4Planes;
185 *bpp = v4hdr->bV4BitCount;
186 *compr = v4hdr->bV4V4Compression;
187 *size = v4hdr->bV4SizeImage;
188 return 4;
190 if (header->biSize == sizeof(BITMAPV5HEADER))
192 const BITMAPV5HEADER *v5hdr = (const BITMAPV5HEADER *)header;
193 *width = v5hdr->bV5Width;
194 *height = v5hdr->bV5Height;
195 *planes = v5hdr->bV5Planes;
196 *bpp = v5hdr->bV5BitCount;
197 *compr = v5hdr->bV5Compression;
198 *size = v5hdr->bV5SizeImage;
199 return 5;
201 ERR("(%d): unknown/wrong size for header\n", header->biSize );
202 return -1;
206 /***********************************************************************
207 * StretchDIBits (GDI32.@)
209 INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst,
210 INT heightDst, INT xSrc, INT ySrc, INT widthSrc,
211 INT heightSrc, const void *bits,
212 const BITMAPINFO *info, UINT wUsage, DWORD dwRop )
214 DC *dc;
216 if (!bits || !info)
217 return 0;
219 dc = DC_GetDCUpdate( hdc );
220 if(!dc) return FALSE;
222 if(dc->funcs->pStretchDIBits)
224 heightSrc = dc->funcs->pStretchDIBits(dc->physDev, xDst, yDst, widthDst,
225 heightDst, xSrc, ySrc, widthSrc,
226 heightSrc, bits, info, wUsage, dwRop);
227 GDI_ReleaseObj( hdc );
229 else /* use StretchBlt */
231 HBITMAP hBitmap, hOldBitmap;
232 HPALETTE hpal = NULL;
233 HDC hdcMem;
234 LONG height;
235 LONG width;
236 WORD planes, bpp;
237 DWORD compr, size;
239 GDI_ReleaseObj( hdc );
241 if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size ) == -1)
243 ERR("Invalid bitmap\n");
244 return 0;
247 if (width < 0)
249 ERR("Bitmap has a negative width\n");
250 return 0;
253 hdcMem = CreateCompatibleDC( hdc );
254 hBitmap = CreateCompatibleBitmap(hdc, width, height);
255 hOldBitmap = SelectObject( hdcMem, hBitmap );
256 if(wUsage == DIB_PAL_COLORS)
258 hpal = GetCurrentObject(hdc, OBJ_PAL);
259 hpal = SelectPalette(hdcMem, hpal, FALSE);
262 if (info->bmiHeader.biCompression == BI_RLE4 ||
263 info->bmiHeader.biCompression == BI_RLE8) {
265 /* when RLE compression is used, there may be some gaps (ie the DIB doesn't
266 * contain all the rectangle described in bmiHeader, but only part of it.
267 * This mean that those undescribed pixels must be left untouched.
268 * So, we first copy on a memory bitmap the current content of the
269 * destination rectangle, blit the DIB bits on top of it - hence leaving
270 * the gaps untouched -, and blitting the rectangle back.
271 * This insure that gaps are untouched on the destination rectangle
272 * Not doing so leads to trashed images (the gaps contain what was on the
273 * memory bitmap => generally black or garbage)
274 * Unfortunately, RLE DIBs without gaps will be slowed down. But this is
275 * another speed vs correctness issue. Anyway, if speed is needed, then the
276 * pStretchDIBits function shall be implemented.
277 * ericP (2000/09/09)
280 /* copy existing bitmap from destination dc */
281 StretchBlt( hdcMem, xSrc, abs(height) - heightSrc - ySrc,
282 widthSrc, heightSrc, hdc, xDst, yDst, widthDst, heightDst,
283 dwRop );
286 SetDIBits(hdcMem, hBitmap, 0, height, bits, info, wUsage);
288 /* Origin for DIBitmap may be bottom left (positive biHeight) or top
289 left (negative biHeight) */
290 StretchBlt( hdc, xDst, yDst, widthDst, heightDst,
291 hdcMem, xSrc, abs(height) - heightSrc - ySrc,
292 widthSrc, heightSrc, dwRop );
293 if(hpal)
294 SelectPalette(hdcMem, hpal, FALSE);
295 SelectObject( hdcMem, hOldBitmap );
296 DeleteDC( hdcMem );
297 DeleteObject( hBitmap );
299 return heightSrc;
303 /******************************************************************************
304 * SetDIBits [GDI32.@]
306 * Sets pixels in a bitmap using colors from DIB.
308 * PARAMS
309 * hdc [I] Handle to device context
310 * hbitmap [I] Handle to bitmap
311 * startscan [I] Starting scan line
312 * lines [I] Number of scan lines
313 * bits [I] Array of bitmap bits
314 * info [I] Address of structure with data
315 * coloruse [I] Type of color indexes to use
317 * RETURNS
318 * Success: Number of scan lines copied
319 * Failure: 0
321 INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
322 UINT lines, LPCVOID bits, const BITMAPINFO *info,
323 UINT coloruse )
325 DC *dc;
326 BITMAPOBJ *bitmap;
327 INT result = 0;
329 if (!(dc = DC_GetDCUpdate( hdc )))
331 if (coloruse == DIB_RGB_COLORS) FIXME( "shouldn't require a DC for DIB_RGB_COLORS\n" );
332 return 0;
335 if (!(bitmap = GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
337 GDI_ReleaseObj( hdc );
338 return 0;
341 if (!bitmap->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) goto done;
343 if (bitmap->funcs && bitmap->funcs->pSetDIBits)
344 result = bitmap->funcs->pSetDIBits( dc->physDev, hbitmap, startscan, lines,
345 bits, info, coloruse );
346 else
347 result = lines;
349 done:
350 GDI_ReleaseObj( hbitmap );
351 GDI_ReleaseObj( hdc );
352 return result;
356 /***********************************************************************
357 * SetDIBitsToDevice (GDI32.@)
359 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
360 DWORD cy, INT xSrc, INT ySrc, UINT startscan,
361 UINT lines, LPCVOID bits, const BITMAPINFO *info,
362 UINT coloruse )
364 INT ret;
365 DC *dc;
367 if (!(dc = DC_GetDCUpdate( hdc ))) return 0;
369 if(dc->funcs->pSetDIBitsToDevice)
370 ret = dc->funcs->pSetDIBitsToDevice( dc->physDev, xDest, yDest, cx, cy, xSrc,
371 ySrc, startscan, lines, bits,
372 info, coloruse );
373 else {
374 FIXME("unimplemented on hdc %p\n", hdc);
375 ret = 0;
378 GDI_ReleaseObj( hdc );
379 return ret;
382 /***********************************************************************
383 * SetDIBColorTable (GDI32.@)
385 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, CONST RGBQUAD *colors )
387 DC * dc;
388 UINT result = 0;
389 BITMAPOBJ * bitmap;
391 if (!(dc = DC_GetDCPtr( hdc ))) return 0;
393 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, BITMAP_MAGIC )))
395 /* Check if currently selected bitmap is a DIB */
396 if (bitmap->color_table)
398 if (startpos < bitmap->nb_colors)
400 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
401 memcpy(bitmap->color_table + startpos, colors, entries * sizeof(RGBQUAD));
402 result = entries;
405 GDI_ReleaseObj( dc->hBitmap );
408 if (dc->funcs->pSetDIBColorTable)
409 dc->funcs->pSetDIBColorTable(dc->physDev, startpos, entries, colors);
411 GDI_ReleaseObj( hdc );
412 return result;
416 /***********************************************************************
417 * GetDIBColorTable (GDI32.@)
419 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
421 DC * dc;
422 UINT result = 0;
424 if (!(dc = DC_GetDCPtr( hdc ))) return 0;
426 if (dc->funcs->pGetDIBColorTable)
427 result = dc->funcs->pGetDIBColorTable(dc->physDev, startpos, entries, colors);
428 else
430 BITMAPOBJ *bitmap = GDI_GetObjPtr( dc->hBitmap, BITMAP_MAGIC );
431 if (bitmap)
433 /* Check if currently selected bitmap is a DIB */
434 if (bitmap->color_table)
436 if (startpos < bitmap->nb_colors)
438 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
439 memcpy(colors, bitmap->color_table + startpos, entries * sizeof(RGBQUAD));
440 result = entries;
443 GDI_ReleaseObj( dc->hBitmap );
446 GDI_ReleaseObj( hdc );
447 return result;
450 /* FIXME the following two structs should be combined with __sysPalTemplate in
451 objects/color.c - this should happen after de-X11-ing both of these
452 files.
453 NB. RGBQUAD and PALETTEENTRY have different orderings of red, green
454 and blue - sigh */
456 static const RGBQUAD EGAColorsQuads[16] = {
457 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
458 { 0x00, 0x00, 0x00, 0x00 },
459 { 0x00, 0x00, 0x80, 0x00 },
460 { 0x00, 0x80, 0x00, 0x00 },
461 { 0x00, 0x80, 0x80, 0x00 },
462 { 0x80, 0x00, 0x00, 0x00 },
463 { 0x80, 0x00, 0x80, 0x00 },
464 { 0x80, 0x80, 0x00, 0x00 },
465 { 0x80, 0x80, 0x80, 0x00 },
466 { 0xc0, 0xc0, 0xc0, 0x00 },
467 { 0x00, 0x00, 0xff, 0x00 },
468 { 0x00, 0xff, 0x00, 0x00 },
469 { 0x00, 0xff, 0xff, 0x00 },
470 { 0xff, 0x00, 0x00, 0x00 },
471 { 0xff, 0x00, 0xff, 0x00 },
472 { 0xff, 0xff, 0x00, 0x00 },
473 { 0xff, 0xff, 0xff, 0x00 }
476 static const RGBTRIPLE EGAColorsTriples[16] = {
477 /* rgbBlue, rgbGreen, rgbRed */
478 { 0x00, 0x00, 0x00 },
479 { 0x00, 0x00, 0x80 },
480 { 0x00, 0x80, 0x00 },
481 { 0x00, 0x80, 0x80 },
482 { 0x80, 0x00, 0x00 },
483 { 0x80, 0x00, 0x80 },
484 { 0x80, 0x80, 0x00 },
485 { 0x80, 0x80, 0x80 },
486 { 0xc0, 0xc0, 0xc0 },
487 { 0x00, 0x00, 0xff },
488 { 0x00, 0xff, 0x00 },
489 { 0x00, 0xff, 0xff },
490 { 0xff, 0x00, 0x00 } ,
491 { 0xff, 0x00, 0xff },
492 { 0xff, 0xff, 0x00 },
493 { 0xff, 0xff, 0xff }
496 static const RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
497 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
498 { 0x00, 0x00, 0x00, 0x00 },
499 { 0x00, 0x00, 0x80, 0x00 },
500 { 0x00, 0x80, 0x00, 0x00 },
501 { 0x00, 0x80, 0x80, 0x00 },
502 { 0x80, 0x00, 0x00, 0x00 },
503 { 0x80, 0x00, 0x80, 0x00 },
504 { 0x80, 0x80, 0x00, 0x00 },
505 { 0xc0, 0xc0, 0xc0, 0x00 },
506 { 0xc0, 0xdc, 0xc0, 0x00 },
507 { 0xf0, 0xca, 0xa6, 0x00 },
508 { 0xf0, 0xfb, 0xff, 0x00 },
509 { 0xa4, 0xa0, 0xa0, 0x00 },
510 { 0x80, 0x80, 0x80, 0x00 },
511 { 0x00, 0x00, 0xf0, 0x00 },
512 { 0x00, 0xff, 0x00, 0x00 },
513 { 0x00, 0xff, 0xff, 0x00 },
514 { 0xff, 0x00, 0x00, 0x00 },
515 { 0xff, 0x00, 0xff, 0x00 },
516 { 0xff, 0xff, 0x00, 0x00 },
517 { 0xff, 0xff, 0xff, 0x00 }
520 static const RGBTRIPLE DefLogPaletteTriples[20] = { /* Copy of Default Logical Palette */
521 /* rgbBlue, rgbGreen, rgbRed */
522 { 0x00, 0x00, 0x00 },
523 { 0x00, 0x00, 0x80 },
524 { 0x00, 0x80, 0x00 },
525 { 0x00, 0x80, 0x80 },
526 { 0x80, 0x00, 0x00 },
527 { 0x80, 0x00, 0x80 },
528 { 0x80, 0x80, 0x00 },
529 { 0xc0, 0xc0, 0xc0 },
530 { 0xc0, 0xdc, 0xc0 },
531 { 0xf0, 0xca, 0xa6 },
532 { 0xf0, 0xfb, 0xff },
533 { 0xa4, 0xa0, 0xa0 },
534 { 0x80, 0x80, 0x80 },
535 { 0x00, 0x00, 0xf0 },
536 { 0x00, 0xff, 0x00 },
537 { 0x00, 0xff, 0xff },
538 { 0xff, 0x00, 0x00 },
539 { 0xff, 0x00, 0xff },
540 { 0xff, 0xff, 0x00 },
541 { 0xff, 0xff, 0xff}
545 /******************************************************************************
546 * GetDIBits [GDI32.@]
548 * Retrieves bits of bitmap and copies to buffer.
550 * RETURNS
551 * Success: Number of scan lines copied from bitmap
552 * Failure: 0
554 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/bitmaps_87eb.asp
556 INT WINAPI GetDIBits(
557 HDC hdc, /* [in] Handle to device context */
558 HBITMAP hbitmap, /* [in] Handle to bitmap */
559 UINT startscan, /* [in] First scan line to set in dest bitmap */
560 UINT lines, /* [in] Number of scan lines to copy */
561 LPVOID bits, /* [out] Address of array for bitmap bits */
562 BITMAPINFO * info, /* [out] Address of structure with bitmap data */
563 UINT coloruse) /* [in] RGB or palette index */
565 DC * dc;
566 BITMAPOBJ * bmp;
567 int i;
568 int bitmap_type;
569 BOOL core_header;
570 LONG width;
571 LONG height;
572 WORD planes, bpp;
573 DWORD compr, size;
574 void* colorPtr;
575 RGBTRIPLE* rgbTriples;
576 RGBQUAD* rgbQuads;
578 if (!info) return 0;
580 bitmap_type = DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size);
581 if (bitmap_type == -1)
583 ERR("Invalid bitmap format\n");
584 return 0;
586 core_header = (bitmap_type == 0);
587 if (!(dc = DC_GetDCUpdate( hdc )))
589 SetLastError( ERROR_INVALID_PARAMETER );
590 return 0;
592 if (!(bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
594 GDI_ReleaseObj( hdc );
595 return 0;
598 colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
599 rgbTriples = (RGBTRIPLE *) colorPtr;
600 rgbQuads = (RGBQUAD *) colorPtr;
602 /* Transfer color info */
604 if (bpp <= 8 && bpp > 0)
606 if (!core_header) info->bmiHeader.biClrUsed = 0;
608 /* If the bitmap object already has a dib section at the
609 same color depth then get the color map from it */
610 if (bmp->dib && bmp->dib->dsBm.bmBitsPixel == bpp) {
611 if(coloruse == DIB_RGB_COLORS) {
612 unsigned int colors = min( bmp->nb_colors, 1 << bpp );
614 if (core_header)
616 /* Convert the color table (RGBQUAD to RGBTRIPLE) */
617 RGBTRIPLE* index = rgbTriples;
619 for (i=0; i < colors; i++, index++)
621 index->rgbtRed = bmp->color_table[i].rgbRed;
622 index->rgbtGreen = bmp->color_table[i].rgbGreen;
623 index->rgbtBlue = bmp->color_table[i].rgbBlue;
626 else
628 if (colors != 1 << bpp) info->bmiHeader.biClrUsed = colors;
629 memcpy(colorPtr, bmp->color_table, colors * sizeof(RGBQUAD));
632 else {
633 WORD *index = colorPtr;
634 for(i = 0; i < 1 << info->bmiHeader.biBitCount; i++, index++)
635 *index = i;
638 else {
639 if(bpp >= bmp->bitmap.bmBitsPixel) {
640 /* Generate the color map from the selected palette */
641 PALETTEENTRY palEntry[256];
643 memset( palEntry, 0, sizeof(palEntry) );
644 if (!GetPaletteEntries( dc->hPalette, 0, 1 << bmp->bitmap.bmBitsPixel, palEntry ))
646 GDI_ReleaseObj( hdc );
647 GDI_ReleaseObj( hbitmap );
648 return 0;
650 for (i = 0; i < (1 << bmp->bitmap.bmBitsPixel); i++) {
651 if (coloruse == DIB_RGB_COLORS) {
652 if (core_header)
654 rgbTriples[i].rgbtRed = palEntry[i].peRed;
655 rgbTriples[i].rgbtGreen = palEntry[i].peGreen;
656 rgbTriples[i].rgbtBlue = palEntry[i].peBlue;
658 else
660 rgbQuads[i].rgbRed = palEntry[i].peRed;
661 rgbQuads[i].rgbGreen = palEntry[i].peGreen;
662 rgbQuads[i].rgbBlue = palEntry[i].peBlue;
663 rgbQuads[i].rgbReserved = 0;
666 else ((WORD *)colorPtr)[i] = (WORD)i;
668 } else {
669 switch (bpp) {
670 case 1:
671 if (core_header)
673 rgbTriples[0].rgbtRed = rgbTriples[0].rgbtGreen =
674 rgbTriples[0].rgbtBlue = 0;
675 rgbTriples[1].rgbtRed = rgbTriples[1].rgbtGreen =
676 rgbTriples[1].rgbtBlue = 0xff;
678 else
680 rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen =
681 rgbQuads[0].rgbBlue = 0;
682 rgbQuads[0].rgbReserved = 0;
683 rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen =
684 rgbQuads[1].rgbBlue = 0xff;
685 rgbQuads[1].rgbReserved = 0;
687 break;
689 case 4:
690 if (core_header)
691 memcpy(colorPtr, EGAColorsTriples, sizeof(EGAColorsTriples));
692 else
693 memcpy(colorPtr, EGAColorsQuads, sizeof(EGAColorsQuads));
695 break;
697 case 8:
699 if (core_header)
701 INT r, g, b;
702 RGBTRIPLE *color;
704 memcpy(rgbTriples, DefLogPaletteTriples,
705 10 * sizeof(RGBTRIPLE));
706 memcpy(rgbTriples + 246, DefLogPaletteTriples + 10,
707 10 * sizeof(RGBTRIPLE));
708 color = rgbTriples + 10;
709 for(r = 0; r <= 5; r++) /* FIXME */
710 for(g = 0; g <= 5; g++)
711 for(b = 0; b <= 5; b++) {
712 color->rgbtRed = (r * 0xff) / 5;
713 color->rgbtGreen = (g * 0xff) / 5;
714 color->rgbtBlue = (b * 0xff) / 5;
715 color++;
718 else
720 INT r, g, b;
721 RGBQUAD *color;
723 memcpy(rgbQuads, DefLogPaletteQuads,
724 10 * sizeof(RGBQUAD));
725 memcpy(rgbQuads + 246, DefLogPaletteQuads + 10,
726 10 * sizeof(RGBQUAD));
727 color = rgbQuads + 10;
728 for(r = 0; r <= 5; r++) /* FIXME */
729 for(g = 0; g <= 5; g++)
730 for(b = 0; b <= 5; b++) {
731 color->rgbRed = (r * 0xff) / 5;
732 color->rgbGreen = (g * 0xff) / 5;
733 color->rgbBlue = (b * 0xff) / 5;
734 color->rgbReserved = 0;
735 color++;
744 if (bits && lines)
746 /* If the bitmap object already have a dib section that contains image data, get the bits from it */
747 if(bmp->dib && bmp->dib->dsBm.bmBitsPixel >= 15 && bpp >= 15)
749 /*FIXME: Only RGB dibs supported for now */
750 unsigned int srcwidth = bmp->dib->dsBm.bmWidth, srcwidthb = bmp->dib->dsBm.bmWidthBytes;
751 unsigned int dstwidth = width;
752 int dstwidthb = DIB_GetDIBWidthBytes( width, bpp );
753 LPBYTE dbits = bits, sbits = (LPBYTE) bmp->dib->dsBm.bmBits + (startscan * srcwidthb);
754 unsigned int x, y, width, widthb;
756 if ((height < 0) ^ (bmp->dib->dsBmih.biHeight < 0))
758 dbits = (LPBYTE)bits + (dstwidthb * (lines-1));
759 dstwidthb = -dstwidthb;
762 switch( bpp ) {
764 case 15:
765 case 16: /* 16 bpp dstDIB */
767 LPWORD dstbits = (LPWORD)dbits;
768 WORD rmask = 0x7c00, gmask= 0x03e0, bmask = 0x001f;
770 /* FIXME: BI_BITFIELDS not supported yet */
772 switch(bmp->dib->dsBm.bmBitsPixel) {
774 case 16: /* 16 bpp srcDIB -> 16 bpp dstDIB */
776 widthb = min(srcwidthb, abs(dstwidthb));
777 /* FIXME: BI_BITFIELDS not supported yet */
778 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
779 memcpy(dbits, sbits, widthb);
781 break;
783 case 24: /* 24 bpp srcDIB -> 16 bpp dstDIB */
785 LPBYTE srcbits = sbits;
787 width = min(srcwidth, dstwidth);
788 for( y = 0; y < lines; y++) {
789 for( x = 0; x < width; x++, srcbits += 3)
790 *dstbits++ = ((srcbits[0] >> 3) & bmask) |
791 (((WORD)srcbits[1] << 2) & gmask) |
792 (((WORD)srcbits[2] << 7) & rmask);
794 dstbits = (LPWORD)(dbits+=dstwidthb);
795 srcbits = (sbits += srcwidthb);
798 break;
800 case 32: /* 32 bpp srcDIB -> 16 bpp dstDIB */
802 LPDWORD srcbits = (LPDWORD)sbits;
803 DWORD val;
805 width = min(srcwidth, dstwidth);
806 for( y = 0; y < lines; y++) {
807 for( x = 0; x < width; x++ ) {
808 val = *srcbits++;
809 *dstbits++ = (WORD)(((val >> 3) & bmask) | ((val >> 6) & gmask) |
810 ((val >> 9) & rmask));
812 dstbits = (LPWORD)(dbits+=dstwidthb);
813 srcbits = (LPDWORD)(sbits+=srcwidthb);
816 break;
818 default: /* ? bit bmp -> 16 bit DIB */
819 FIXME("15/16 bit DIB %d bit bitmap\n",
820 bmp->bitmap.bmBitsPixel);
821 break;
824 break;
826 case 24: /* 24 bpp dstDIB */
828 LPBYTE dstbits = dbits;
830 switch(bmp->dib->dsBm.bmBitsPixel) {
832 case 16: /* 16 bpp srcDIB -> 24 bpp dstDIB */
834 LPWORD srcbits = (LPWORD)sbits;
835 WORD val;
837 width = min(srcwidth, dstwidth);
838 /* FIXME: BI_BITFIELDS not supported yet */
839 for( y = 0; y < lines; y++) {
840 for( x = 0; x < width; x++ ) {
841 val = *srcbits++;
842 *dstbits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07));
843 *dstbits++ = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07));
844 *dstbits++ = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07));
846 dstbits = (LPBYTE)(dbits+=dstwidthb);
847 srcbits = (LPWORD)(sbits+=srcwidthb);
850 break;
852 case 24: /* 24 bpp srcDIB -> 24 bpp dstDIB */
854 widthb = min(srcwidthb, abs(dstwidthb));
855 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
856 memcpy(dbits, sbits, widthb);
858 break;
860 case 32: /* 32 bpp srcDIB -> 24 bpp dstDIB */
862 LPBYTE srcbits = (LPBYTE)sbits;
864 width = min(srcwidth, dstwidth);
865 for( y = 0; y < lines; y++) {
866 for( x = 0; x < width; x++, srcbits++ ) {
867 *dstbits++ = *srcbits++;
868 *dstbits++ = *srcbits++;
869 *dstbits++ = *srcbits++;
871 dstbits=(LPBYTE)(dbits+=dstwidthb);
872 srcbits = (LPBYTE)(sbits+=srcwidthb);
875 break;
877 default: /* ? bit bmp -> 24 bit DIB */
878 FIXME("24 bit DIB %d bit bitmap\n",
879 bmp->bitmap.bmBitsPixel);
880 break;
883 break;
885 case 32: /* 32 bpp dstDIB */
887 LPDWORD dstbits = (LPDWORD)dbits;
889 /* FIXME: BI_BITFIELDS not supported yet */
891 switch(bmp->dib->dsBm.bmBitsPixel) {
892 case 16: /* 16 bpp srcDIB -> 32 bpp dstDIB */
894 LPWORD srcbits = (LPWORD)sbits;
895 DWORD val;
897 width = min(srcwidth, dstwidth);
898 /* FIXME: BI_BITFIELDS not supported yet */
899 for( y = 0; y < lines; y++) {
900 for( x = 0; x < width; x++ ) {
901 val = (DWORD)*srcbits++;
902 *dstbits++ = ((val << 3) & 0xf8) | ((val >> 2) & 0x07) |
903 ((val << 6) & 0xf800) | ((val << 1) & 0x0700) |
904 ((val << 9) & 0xf80000) | ((val << 4) & 0x070000);
906 dstbits=(LPDWORD)(dbits+=dstwidthb);
907 srcbits=(LPWORD)(sbits+=srcwidthb);
910 break;
912 case 24: /* 24 bpp srcDIB -> 32 bpp dstDIB */
914 LPBYTE srcbits = sbits;
916 width = min(srcwidth, dstwidth);
917 for( y = 0; y < lines; y++) {
918 for( x = 0; x < width; x++, srcbits+=3 )
919 *dstbits++ = srcbits[0] |
920 (srcbits[1] << 8) |
921 (srcbits[2] << 16);
922 dstbits=(LPDWORD)(dbits+=dstwidthb);
923 srcbits=(sbits+=srcwidthb);
926 break;
928 case 32: /* 32 bpp srcDIB -> 32 bpp dstDIB */
930 widthb = min(srcwidthb, abs(dstwidthb));
931 /* FIXME: BI_BITFIELDS not supported yet */
932 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb) {
933 memcpy(dbits, sbits, widthb);
936 break;
938 default: /* ? bit bmp -> 32 bit DIB */
939 FIXME("32 bit DIB %d bit bitmap\n",
940 bmp->bitmap.bmBitsPixel);
941 break;
944 break;
946 default: /* ? bit DIB */
947 FIXME("Unsupported DIB depth %d\n", info->bmiHeader.biBitCount);
948 break;
951 /* Otherwise, get bits from the XImage */
952 else
954 if (!bmp->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) lines = 0;
955 else
957 if (bmp->funcs && bmp->funcs->pGetDIBits)
958 lines = bmp->funcs->pGetDIBits( dc->physDev, hbitmap, startscan,
959 lines, bits, info, coloruse );
960 else
961 lines = 0; /* FIXME: should copy from bmp->bitmap.bmBits */
965 else
967 /* fill in struct members */
969 if (bpp == 0)
971 if (core_header)
973 BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) info;
974 coreheader->bcWidth = bmp->bitmap.bmWidth;
975 coreheader->bcHeight = bmp->bitmap.bmHeight;
976 coreheader->bcPlanes = 1;
977 coreheader->bcBitCount = bmp->bitmap.bmBitsPixel;
979 else
981 info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
982 info->bmiHeader.biHeight = bmp->bitmap.bmHeight;
983 info->bmiHeader.biPlanes = 1;
984 info->bmiHeader.biSizeImage =
985 DIB_GetDIBImageBytes( bmp->bitmap.bmWidth,
986 bmp->bitmap.bmHeight,
987 bmp->bitmap.bmBitsPixel );
988 switch(bmp->bitmap.bmBitsPixel)
990 case 15:
991 info->bmiHeader.biBitCount = 16;
992 info->bmiHeader.biCompression = BI_RGB;
993 break;
995 case 16:
996 info->bmiHeader.biBitCount = 16;
997 info->bmiHeader.biCompression = BI_BITFIELDS;
998 ((PDWORD)info->bmiColors)[0] = 0xf800;
999 ((PDWORD)info->bmiColors)[1] = 0x07e0;
1000 ((PDWORD)info->bmiColors)[2] = 0x001f;
1001 break;
1003 default:
1004 info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
1005 info->bmiHeader.biCompression = BI_RGB;
1006 break;
1008 info->bmiHeader.biXPelsPerMeter = 0;
1009 info->bmiHeader.biYPelsPerMeter = 0;
1010 info->bmiHeader.biClrUsed = 0;
1011 info->bmiHeader.biClrImportant = 0;
1013 /* Windows 2000 doesn't touch the additional struct members if
1014 it's a BITMAPV4HEADER or a BITMAPV5HEADER */
1016 lines = abs(bmp->bitmap.bmHeight);
1018 else
1020 /* The knowledge base article Q81498 ("DIBs and Their Uses") states that
1021 if bits == NULL and bpp != 0, only biSizeImage and the color table are
1022 filled in. */
1023 if (!core_header)
1025 /* FIXME: biSizeImage should be calculated according to the selected
1026 compression algorithm if biCompression != BI_RGB */
1027 info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes( width, height, bpp );
1029 lines = abs(height);
1033 if (!core_header)
1035 TRACE("biSizeImage = %d, ", info->bmiHeader.biSizeImage);
1037 TRACE("biWidth = %d, biHeight = %d\n", width, height);
1039 GDI_ReleaseObj( hdc );
1040 GDI_ReleaseObj( hbitmap );
1041 return lines;
1045 /***********************************************************************
1046 * CreateDIBitmap (GDI32.@)
1048 * Creates a DDB (device dependent bitmap) from a DIB.
1049 * The DDB will have the same color depth as the reference DC.
1051 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
1052 DWORD init, LPCVOID bits, const BITMAPINFO *data,
1053 UINT coloruse )
1055 HBITMAP handle;
1056 LONG width;
1057 LONG height;
1058 WORD planes, bpp;
1059 DWORD compr, size;
1060 DC *dc;
1062 if (DIB_GetBitmapInfo( header, &width, &height, &planes, &bpp, &compr, &size ) == -1) return 0;
1064 if (width < 0)
1066 TRACE("Bitmap has a negative width\n");
1067 return 0;
1070 /* Top-down DIBs have a negative height */
1071 if (height < 0) height = -height;
1073 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1074 hdc, header, init, bits, data, coloruse, width, height, bpp, compr);
1076 if (hdc == NULL)
1077 handle = CreateBitmap( width, height, 1, 1, NULL );
1078 else
1079 handle = CreateCompatibleBitmap( hdc, width, height );
1081 if (handle)
1083 if (init == CBM_INIT) SetDIBits( hdc, handle, 0, height, bits, data, coloruse );
1085 else if (hdc && ((dc = DC_GetDCPtr( hdc )) != NULL) )
1087 if (!BITMAP_SetOwnerDC( handle, dc ))
1089 DeleteObject( handle );
1090 handle = 0;
1092 GDI_ReleaseObj( hdc );
1096 return handle;
1099 /***********************************************************************
1100 * CreateDIBSection (GDI.489)
1102 HBITMAP16 WINAPI CreateDIBSection16 (HDC16 hdc, const BITMAPINFO *bmi, UINT16 usage,
1103 SEGPTR *bits16, HANDLE section, DWORD offset)
1105 LPVOID bits32;
1106 HBITMAP hbitmap;
1108 hbitmap = CreateDIBSection( HDC_32(hdc), bmi, usage, &bits32, section, offset );
1109 if (hbitmap)
1111 BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr(hbitmap, BITMAP_MAGIC);
1112 if (bmp && bmp->dib && bits32)
1114 const BITMAPINFOHEADER *bi = &bmi->bmiHeader;
1115 LONG width, height;
1116 WORD planes, bpp;
1117 DWORD compr, size;
1118 INT width_bytes;
1119 WORD count, sel;
1120 int i;
1122 DIB_GetBitmapInfo(bi, &width, &height, &planes, &bpp, &compr, &size);
1124 height = height >= 0 ? height : -height;
1125 width_bytes = DIB_GetDIBWidthBytes(width, bpp);
1127 if (!size || (compr != BI_RLE4 && compr != BI_RLE8)) size = width_bytes * height;
1129 /* calculate number of sel's needed for size with 64K steps */
1130 count = (size + 0xffff) / 0x10000;
1131 sel = AllocSelectorArray16(count);
1133 for (i = 0; i < count; i++)
1135 SetSelectorBase(sel + (i << __AHSHIFT), (DWORD)bits32 + i * 0x10000);
1136 SetSelectorLimit16(sel + (i << __AHSHIFT), size - 1); /* yep, limit is correct */
1137 size -= 0x10000;
1139 bmp->segptr_bits = MAKESEGPTR( sel, 0 );
1140 if (bits16) *bits16 = bmp->segptr_bits;
1142 if (bmp) GDI_ReleaseObj( hbitmap );
1144 return HBITMAP_16(hbitmap);
1147 /* Copy/synthetize RGB palette from BITMAPINFO. Ripped from dlls/winex11.drv/dib.c */
1148 static void DIB_CopyColorTable( DC *dc, BITMAPOBJ *bmp, WORD coloruse, const BITMAPINFO *info )
1150 RGBQUAD *colorTable;
1151 unsigned int colors;
1152 int i;
1153 BOOL core_info = info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER);
1155 if (core_info)
1157 colors = 1 << ((const BITMAPCOREINFO*) info)->bmciHeader.bcBitCount;
1159 else
1161 colors = info->bmiHeader.biClrUsed;
1162 if (!colors) colors = 1 << info->bmiHeader.biBitCount;
1165 if (colors > 256) {
1166 ERR("called with >256 colors!\n");
1167 return;
1170 if (!(colorTable = HeapAlloc(GetProcessHeap(), 0, colors * sizeof(RGBQUAD) ))) return;
1172 if(coloruse == DIB_RGB_COLORS)
1174 if (core_info)
1176 /* Convert RGBTRIPLEs to RGBQUADs */
1177 for (i=0; i < colors; i++)
1179 colorTable[i].rgbRed = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtRed;
1180 colorTable[i].rgbGreen = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtGreen;
1181 colorTable[i].rgbBlue = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtBlue;
1182 colorTable[i].rgbReserved = 0;
1185 else
1187 memcpy(colorTable, (const BYTE*) info + (WORD) info->bmiHeader.biSize, colors * sizeof(RGBQUAD));
1190 else
1192 PALETTEENTRY entries[256];
1193 const WORD *index = (const WORD*) ((const BYTE*) info + (WORD) info->bmiHeader.biSize);
1194 UINT count = GetPaletteEntries( dc->hPalette, 0, colors, entries );
1196 for (i = 0; i < colors; i++, index++)
1198 PALETTEENTRY *entry = &entries[*index % count];
1199 colorTable[i].rgbRed = entry->peRed;
1200 colorTable[i].rgbGreen = entry->peGreen;
1201 colorTable[i].rgbBlue = entry->peBlue;
1202 colorTable[i].rgbReserved = 0;
1205 bmp->color_table = colorTable;
1206 bmp->nb_colors = colors;
1209 /***********************************************************************
1210 * CreateDIBSection (GDI32.@)
1212 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
1213 VOID **bits, HANDLE section, DWORD offset)
1215 HBITMAP ret = 0;
1216 DC *dc;
1217 BOOL bDesktopDC = FALSE;
1218 DIBSECTION *dib;
1219 BITMAPOBJ *bmp;
1220 int bitmap_type;
1221 LONG width, height;
1222 WORD planes, bpp;
1223 DWORD compression, sizeImage;
1224 void *mapBits = NULL;
1226 if (((bitmap_type = DIB_GetBitmapInfo( &bmi->bmiHeader, &width, &height,
1227 &planes, &bpp, &compression, &sizeImage )) == -1))
1228 return 0;
1230 if (compression != BI_RGB && compression != BI_BITFIELDS)
1232 TRACE("can't create a compressed (%u) dibsection\n", compression);
1233 return 0;
1236 if (!(dib = HeapAlloc( GetProcessHeap(), 0, sizeof(*dib) ))) return 0;
1238 TRACE("format (%d,%d), planes %d, bpp %d, size %d, %s\n",
1239 width, height, planes, bpp, sizeImage, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1241 dib->dsBm.bmType = 0;
1242 dib->dsBm.bmWidth = width;
1243 dib->dsBm.bmHeight = height >= 0 ? height : -height;
1244 dib->dsBm.bmWidthBytes = DIB_GetDIBWidthBytes(width, bpp);
1245 dib->dsBm.bmPlanes = planes;
1246 dib->dsBm.bmBitsPixel = bpp;
1247 dib->dsBm.bmBits = NULL;
1249 if (!bitmap_type) /* core header */
1251 /* convert the BITMAPCOREHEADER to a BITMAPINFOHEADER */
1252 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1253 dib->dsBmih.biWidth = width;
1254 dib->dsBmih.biHeight = height;
1255 dib->dsBmih.biPlanes = planes;
1256 dib->dsBmih.biBitCount = bpp;
1257 dib->dsBmih.biCompression = compression;
1258 dib->dsBmih.biXPelsPerMeter = 0;
1259 dib->dsBmih.biYPelsPerMeter = 0;
1260 dib->dsBmih.biClrUsed = 0;
1261 dib->dsBmih.biClrImportant = 0;
1263 else
1265 /* truncate extended bitmap headers (BITMAPV4HEADER etc.) */
1266 dib->dsBmih = bmi->bmiHeader;
1267 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1270 /* set number of entries in bmi.bmiColors table */
1271 if( bpp <= 8 )
1272 dib->dsBmih.biClrUsed = 1 << bpp;
1274 dib->dsBmih.biSizeImage = dib->dsBm.bmWidthBytes * dib->dsBm.bmHeight;
1276 /* set dsBitfields values */
1277 if (usage == DIB_PAL_COLORS || bpp <= 8)
1279 dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
1281 else switch( bpp )
1283 case 15:
1284 case 16:
1285 dib->dsBitfields[0] = (compression == BI_BITFIELDS) ? *(const DWORD *)bmi->bmiColors : 0x7c00;
1286 dib->dsBitfields[1] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 1) : 0x03e0;
1287 dib->dsBitfields[2] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 2) : 0x001f;
1288 break;
1289 case 24:
1290 case 32:
1291 dib->dsBitfields[0] = (compression == BI_BITFIELDS) ? *(const DWORD *)bmi->bmiColors : 0xff0000;
1292 dib->dsBitfields[1] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 1) : 0x00ff00;
1293 dib->dsBitfields[2] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 2) : 0x0000ff;
1294 break;
1297 /* get storage location for DIB bits */
1299 if (section)
1301 SYSTEM_INFO SystemInfo;
1302 DWORD mapOffset;
1303 INT mapSize;
1305 GetSystemInfo( &SystemInfo );
1306 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
1307 mapSize = dib->dsBmih.biSizeImage + (offset - mapOffset);
1308 mapBits = MapViewOfFile( section, FILE_MAP_ALL_ACCESS, 0, mapOffset, mapSize );
1309 if (mapBits) dib->dsBm.bmBits = (char *)mapBits + (offset - mapOffset);
1311 else
1313 offset = 0;
1314 dib->dsBm.bmBits = VirtualAlloc( NULL, dib->dsBmih.biSizeImage,
1315 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
1317 dib->dshSection = section;
1318 dib->dsOffset = offset;
1320 if (!dib->dsBm.bmBits)
1322 HeapFree( GetProcessHeap(), 0, dib );
1323 return 0;
1326 /* If the reference hdc is null, take the desktop dc */
1327 if (hdc == 0)
1329 hdc = CreateCompatibleDC(0);
1330 bDesktopDC = TRUE;
1333 if (!(dc = DC_GetDCPtr( hdc ))) goto error;
1335 /* create Device Dependent Bitmap and add DIB pointer */
1336 ret = CreateBitmap( dib->dsBm.bmWidth, dib->dsBm.bmHeight, 1,
1337 (bpp == 1) ? 1 : GetDeviceCaps(hdc, BITSPIXEL), NULL );
1339 if (ret && ((bmp = GDI_GetObjPtr(ret, BITMAP_MAGIC))))
1341 bmp->dib = dib;
1342 bmp->funcs = dc->funcs;
1343 /* create local copy of DIB palette */
1344 if (bpp <= 8) DIB_CopyColorTable( dc, bmp, usage, bmi );
1345 GDI_ReleaseObj( ret );
1347 if (dc->funcs->pCreateDIBSection)
1349 if (!dc->funcs->pCreateDIBSection(dc->physDev, ret, bmi, usage))
1351 DeleteObject( ret );
1352 ret = 0;
1357 GDI_ReleaseObj(hdc);
1358 if (bDesktopDC) DeleteDC( hdc );
1359 if (ret && bits) *bits = dib->dsBm.bmBits;
1360 return ret;
1362 error:
1363 if (bDesktopDC) DeleteDC( hdc );
1364 if (section) UnmapViewOfFile( mapBits );
1365 else if (!offset) VirtualFree( dib->dsBm.bmBits, 0, MEM_RELEASE );
1366 HeapFree( GetProcessHeap(), 0, dib );
1367 return 0;