winecfg: Add ability to change colors and non-client sizes.
[wine.git] / dlls / gdi32 / dib.c
blob049b343cb714619395d652a4ebef54db5915afe5
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 return 0;
591 if (!(bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
593 GDI_ReleaseObj( hdc );
594 return 0;
597 colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
598 rgbTriples = (RGBTRIPLE *) colorPtr;
599 rgbQuads = (RGBQUAD *) colorPtr;
601 /* Transfer color info */
603 if (bpp <= 8 && bpp > 0)
605 if (!core_header) info->bmiHeader.biClrUsed = 0;
607 /* If the bitmap object already has a dib section at the
608 same color depth then get the color map from it */
609 if (bmp->dib && bmp->dib->dsBm.bmBitsPixel == bpp) {
610 if(coloruse == DIB_RGB_COLORS) {
611 unsigned int colors = min( bmp->nb_colors, 1 << bpp );
613 if (core_header)
615 /* Convert the color table (RGBQUAD to RGBTRIPLE) */
616 RGBTRIPLE* index = rgbTriples;
618 for (i=0; i < colors; i++, index++)
620 index->rgbtRed = bmp->color_table[i].rgbRed;
621 index->rgbtGreen = bmp->color_table[i].rgbGreen;
622 index->rgbtBlue = bmp->color_table[i].rgbBlue;
625 else
627 if (colors != 1 << bpp) info->bmiHeader.biClrUsed = colors;
628 memcpy(colorPtr, bmp->color_table, colors * sizeof(RGBQUAD));
631 else {
632 WORD *index = colorPtr;
633 for(i = 0; i < 1 << info->bmiHeader.biBitCount; i++, index++)
634 *index = i;
637 else {
638 if(bpp >= bmp->bitmap.bmBitsPixel) {
639 /* Generate the color map from the selected palette */
640 PALETTEENTRY palEntry[256];
642 memset( palEntry, 0, sizeof(palEntry) );
643 if (!GetPaletteEntries( dc->hPalette, 0, 1 << bmp->bitmap.bmBitsPixel, palEntry ))
645 GDI_ReleaseObj( hdc );
646 GDI_ReleaseObj( hbitmap );
647 return 0;
649 for (i = 0; i < (1 << bmp->bitmap.bmBitsPixel); i++) {
650 if (coloruse == DIB_RGB_COLORS) {
651 if (core_header)
653 rgbTriples[i].rgbtRed = palEntry[i].peRed;
654 rgbTriples[i].rgbtGreen = palEntry[i].peGreen;
655 rgbTriples[i].rgbtBlue = palEntry[i].peBlue;
657 else
659 rgbQuads[i].rgbRed = palEntry[i].peRed;
660 rgbQuads[i].rgbGreen = palEntry[i].peGreen;
661 rgbQuads[i].rgbBlue = palEntry[i].peBlue;
662 rgbQuads[i].rgbReserved = 0;
665 else ((WORD *)colorPtr)[i] = (WORD)i;
667 } else {
668 switch (bpp) {
669 case 1:
670 if (core_header)
672 rgbTriples[0].rgbtRed = rgbTriples[0].rgbtGreen =
673 rgbTriples[0].rgbtBlue = 0;
674 rgbTriples[1].rgbtRed = rgbTriples[1].rgbtGreen =
675 rgbTriples[1].rgbtBlue = 0xff;
677 else
679 rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen =
680 rgbQuads[0].rgbBlue = 0;
681 rgbQuads[0].rgbReserved = 0;
682 rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen =
683 rgbQuads[1].rgbBlue = 0xff;
684 rgbQuads[1].rgbReserved = 0;
686 break;
688 case 4:
689 if (core_header)
690 memcpy(colorPtr, EGAColorsTriples, sizeof(EGAColorsTriples));
691 else
692 memcpy(colorPtr, EGAColorsQuads, sizeof(EGAColorsQuads));
694 break;
696 case 8:
698 if (core_header)
700 INT r, g, b;
701 RGBTRIPLE *color;
703 memcpy(rgbTriples, DefLogPaletteTriples,
704 10 * sizeof(RGBTRIPLE));
705 memcpy(rgbTriples + 246, DefLogPaletteTriples + 10,
706 10 * sizeof(RGBTRIPLE));
707 color = rgbTriples + 10;
708 for(r = 0; r <= 5; r++) /* FIXME */
709 for(g = 0; g <= 5; g++)
710 for(b = 0; b <= 5; b++) {
711 color->rgbtRed = (r * 0xff) / 5;
712 color->rgbtGreen = (g * 0xff) / 5;
713 color->rgbtBlue = (b * 0xff) / 5;
714 color++;
717 else
719 INT r, g, b;
720 RGBQUAD *color;
722 memcpy(rgbQuads, DefLogPaletteQuads,
723 10 * sizeof(RGBQUAD));
724 memcpy(rgbQuads + 246, DefLogPaletteQuads + 10,
725 10 * sizeof(RGBQUAD));
726 color = rgbQuads + 10;
727 for(r = 0; r <= 5; r++) /* FIXME */
728 for(g = 0; g <= 5; g++)
729 for(b = 0; b <= 5; b++) {
730 color->rgbRed = (r * 0xff) / 5;
731 color->rgbGreen = (g * 0xff) / 5;
732 color->rgbBlue = (b * 0xff) / 5;
733 color->rgbReserved = 0;
734 color++;
743 if (bits && lines)
745 /* If the bitmap object already have a dib section that contains image data, get the bits from it */
746 if(bmp->dib && bmp->dib->dsBm.bmBitsPixel >= 15 && bpp >= 15)
748 /*FIXME: Only RGB dibs supported for now */
749 unsigned int srcwidth = bmp->dib->dsBm.bmWidth, srcwidthb = bmp->dib->dsBm.bmWidthBytes;
750 unsigned int dstwidth = width;
751 int dstwidthb = DIB_GetDIBWidthBytes( width, bpp );
752 LPBYTE dbits = bits, sbits = (LPBYTE) bmp->dib->dsBm.bmBits + (startscan * srcwidthb);
753 unsigned int x, y, width, widthb;
755 if ((height < 0) ^ (bmp->dib->dsBmih.biHeight < 0))
757 dbits = (LPBYTE)bits + (dstwidthb * (lines-1));
758 dstwidthb = -dstwidthb;
761 switch( bpp ) {
763 case 15:
764 case 16: /* 16 bpp dstDIB */
766 LPWORD dstbits = (LPWORD)dbits;
767 WORD rmask = 0x7c00, gmask= 0x03e0, bmask = 0x001f;
769 /* FIXME: BI_BITFIELDS not supported yet */
771 switch(bmp->dib->dsBm.bmBitsPixel) {
773 case 16: /* 16 bpp srcDIB -> 16 bpp dstDIB */
775 widthb = min(srcwidthb, abs(dstwidthb));
776 /* FIXME: BI_BITFIELDS not supported yet */
777 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
778 memcpy(dbits, sbits, widthb);
780 break;
782 case 24: /* 24 bpp srcDIB -> 16 bpp dstDIB */
784 LPBYTE srcbits = sbits;
786 width = min(srcwidth, dstwidth);
787 for( y = 0; y < lines; y++) {
788 for( x = 0; x < width; x++, srcbits += 3)
789 *dstbits++ = ((srcbits[0] >> 3) & bmask) |
790 (((WORD)srcbits[1] << 2) & gmask) |
791 (((WORD)srcbits[2] << 7) & rmask);
793 dstbits = (LPWORD)(dbits+=dstwidthb);
794 srcbits = (sbits += srcwidthb);
797 break;
799 case 32: /* 32 bpp srcDIB -> 16 bpp dstDIB */
801 LPDWORD srcbits = (LPDWORD)sbits;
802 DWORD val;
804 width = min(srcwidth, dstwidth);
805 for( y = 0; y < lines; y++) {
806 for( x = 0; x < width; x++ ) {
807 val = *srcbits++;
808 *dstbits++ = (WORD)(((val >> 3) & bmask) | ((val >> 6) & gmask) |
809 ((val >> 9) & rmask));
811 dstbits = (LPWORD)(dbits+=dstwidthb);
812 srcbits = (LPDWORD)(sbits+=srcwidthb);
815 break;
817 default: /* ? bit bmp -> 16 bit DIB */
818 FIXME("15/16 bit DIB %d bit bitmap\n",
819 bmp->bitmap.bmBitsPixel);
820 break;
823 break;
825 case 24: /* 24 bpp dstDIB */
827 LPBYTE dstbits = dbits;
829 switch(bmp->dib->dsBm.bmBitsPixel) {
831 case 16: /* 16 bpp srcDIB -> 24 bpp dstDIB */
833 LPWORD srcbits = (LPWORD)sbits;
834 WORD val;
836 width = min(srcwidth, dstwidth);
837 /* FIXME: BI_BITFIELDS not supported yet */
838 for( y = 0; y < lines; y++) {
839 for( x = 0; x < width; x++ ) {
840 val = *srcbits++;
841 *dstbits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07));
842 *dstbits++ = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07));
843 *dstbits++ = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07));
845 dstbits = (LPBYTE)(dbits+=dstwidthb);
846 srcbits = (LPWORD)(sbits+=srcwidthb);
849 break;
851 case 24: /* 24 bpp srcDIB -> 24 bpp dstDIB */
853 widthb = min(srcwidthb, abs(dstwidthb));
854 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
855 memcpy(dbits, sbits, widthb);
857 break;
859 case 32: /* 32 bpp srcDIB -> 24 bpp dstDIB */
861 LPBYTE srcbits = (LPBYTE)sbits;
863 width = min(srcwidth, dstwidth);
864 for( y = 0; y < lines; y++) {
865 for( x = 0; x < width; x++, srcbits++ ) {
866 *dstbits++ = *srcbits++;
867 *dstbits++ = *srcbits++;
868 *dstbits++ = *srcbits++;
870 dstbits=(LPBYTE)(dbits+=dstwidthb);
871 srcbits = (LPBYTE)(sbits+=srcwidthb);
874 break;
876 default: /* ? bit bmp -> 24 bit DIB */
877 FIXME("24 bit DIB %d bit bitmap\n",
878 bmp->bitmap.bmBitsPixel);
879 break;
882 break;
884 case 32: /* 32 bpp dstDIB */
886 LPDWORD dstbits = (LPDWORD)dbits;
888 /* FIXME: BI_BITFIELDS not supported yet */
890 switch(bmp->dib->dsBm.bmBitsPixel) {
891 case 16: /* 16 bpp srcDIB -> 32 bpp dstDIB */
893 LPWORD srcbits = (LPWORD)sbits;
894 DWORD val;
896 width = min(srcwidth, dstwidth);
897 /* FIXME: BI_BITFIELDS not supported yet */
898 for( y = 0; y < lines; y++) {
899 for( x = 0; x < width; x++ ) {
900 val = (DWORD)*srcbits++;
901 *dstbits++ = ((val << 3) & 0xf8) | ((val >> 2) & 0x07) |
902 ((val << 6) & 0xf800) | ((val << 1) & 0x0700) |
903 ((val << 9) & 0xf80000) | ((val << 4) & 0x070000);
905 dstbits=(LPDWORD)(dbits+=dstwidthb);
906 srcbits=(LPWORD)(sbits+=srcwidthb);
909 break;
911 case 24: /* 24 bpp srcDIB -> 32 bpp dstDIB */
913 LPBYTE srcbits = sbits;
915 width = min(srcwidth, dstwidth);
916 for( y = 0; y < lines; y++) {
917 for( x = 0; x < width; x++, srcbits+=3 )
918 *dstbits++ = srcbits[0] |
919 (srcbits[1] << 8) |
920 (srcbits[2] << 16);
921 dstbits=(LPDWORD)(dbits+=dstwidthb);
922 srcbits=(sbits+=srcwidthb);
925 break;
927 case 32: /* 32 bpp srcDIB -> 32 bpp dstDIB */
929 widthb = min(srcwidthb, abs(dstwidthb));
930 /* FIXME: BI_BITFIELDS not supported yet */
931 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb) {
932 memcpy(dbits, sbits, widthb);
935 break;
937 default: /* ? bit bmp -> 32 bit DIB */
938 FIXME("32 bit DIB %d bit bitmap\n",
939 bmp->bitmap.bmBitsPixel);
940 break;
943 break;
945 default: /* ? bit DIB */
946 FIXME("Unsupported DIB depth %d\n", info->bmiHeader.biBitCount);
947 break;
950 /* Otherwise, get bits from the XImage */
951 else
953 if (!bmp->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) lines = 0;
954 else
956 if (bmp->funcs && bmp->funcs->pGetDIBits)
957 lines = bmp->funcs->pGetDIBits( dc->physDev, hbitmap, startscan,
958 lines, bits, info, coloruse );
959 else
960 lines = 0; /* FIXME: should copy from bmp->bitmap.bmBits */
964 else
966 /* fill in struct members */
968 if (bpp == 0)
970 if (core_header)
972 BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) info;
973 coreheader->bcWidth = bmp->bitmap.bmWidth;
974 coreheader->bcHeight = bmp->bitmap.bmHeight;
975 coreheader->bcPlanes = 1;
976 coreheader->bcBitCount = bmp->bitmap.bmBitsPixel;
978 else
980 info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
981 info->bmiHeader.biHeight = bmp->bitmap.bmHeight;
982 info->bmiHeader.biPlanes = 1;
983 info->bmiHeader.biSizeImage =
984 DIB_GetDIBImageBytes( bmp->bitmap.bmWidth,
985 bmp->bitmap.bmHeight,
986 bmp->bitmap.bmBitsPixel );
987 switch(bmp->bitmap.bmBitsPixel)
989 case 15:
990 info->bmiHeader.biBitCount = 16;
991 info->bmiHeader.biCompression = BI_RGB;
992 break;
994 case 16:
995 info->bmiHeader.biBitCount = 16;
996 info->bmiHeader.biCompression = BI_BITFIELDS;
997 ((PDWORD)info->bmiColors)[0] = 0xf800;
998 ((PDWORD)info->bmiColors)[1] = 0x07e0;
999 ((PDWORD)info->bmiColors)[2] = 0x001f;
1000 break;
1002 default:
1003 info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
1004 info->bmiHeader.biCompression = BI_RGB;
1005 break;
1007 info->bmiHeader.biXPelsPerMeter = 0;
1008 info->bmiHeader.biYPelsPerMeter = 0;
1009 info->bmiHeader.biClrUsed = 0;
1010 info->bmiHeader.biClrImportant = 0;
1012 /* Windows 2000 doesn't touch the additional struct members if
1013 it's a BITMAPV4HEADER or a BITMAPV5HEADER */
1015 lines = abs(bmp->bitmap.bmHeight);
1017 else
1019 /* The knowledge base article Q81498 ("DIBs and Their Uses") states that
1020 if bits == NULL and bpp != 0, only biSizeImage and the color table are
1021 filled in. */
1022 if (!core_header)
1024 /* FIXME: biSizeImage should be calculated according to the selected
1025 compression algorithm if biCompression != BI_RGB */
1026 info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes( width, height, bpp );
1028 lines = abs(height);
1032 if (!core_header)
1034 TRACE("biSizeImage = %d, ", info->bmiHeader.biSizeImage);
1036 TRACE("biWidth = %d, biHeight = %d\n", width, height);
1038 GDI_ReleaseObj( hdc );
1039 GDI_ReleaseObj( hbitmap );
1040 return lines;
1044 /***********************************************************************
1045 * CreateDIBitmap (GDI32.@)
1047 * Creates a DDB (device dependent bitmap) from a DIB.
1048 * The DDB will have the same color depth as the reference DC.
1050 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
1051 DWORD init, LPCVOID bits, const BITMAPINFO *data,
1052 UINT coloruse )
1054 HBITMAP handle;
1055 LONG width;
1056 LONG height;
1057 WORD planes, bpp;
1058 DWORD compr, size;
1059 DC *dc;
1061 if (DIB_GetBitmapInfo( header, &width, &height, &planes, &bpp, &compr, &size ) == -1) return 0;
1063 if (width < 0)
1065 TRACE("Bitmap has a negative width\n");
1066 return 0;
1069 /* Top-down DIBs have a negative height */
1070 if (height < 0) height = -height;
1072 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1073 hdc, header, init, bits, data, coloruse, width, height, bpp, compr);
1075 if (hdc == NULL)
1076 handle = CreateBitmap( width, height, 1, 1, NULL );
1077 else
1078 handle = CreateCompatibleBitmap( hdc, width, height );
1080 if (handle)
1082 if (init == CBM_INIT) SetDIBits( hdc, handle, 0, height, bits, data, coloruse );
1084 else if (hdc && ((dc = DC_GetDCPtr( hdc )) != NULL) )
1086 if (!BITMAP_SetOwnerDC( handle, dc ))
1088 DeleteObject( handle );
1089 handle = 0;
1091 GDI_ReleaseObj( hdc );
1095 return handle;
1098 /***********************************************************************
1099 * CreateDIBSection (GDI.489)
1101 HBITMAP16 WINAPI CreateDIBSection16 (HDC16 hdc, const BITMAPINFO *bmi, UINT16 usage,
1102 SEGPTR *bits16, HANDLE section, DWORD offset)
1104 LPVOID bits32;
1105 HBITMAP hbitmap;
1107 hbitmap = CreateDIBSection( HDC_32(hdc), bmi, usage, &bits32, section, offset );
1108 if (hbitmap)
1110 BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr(hbitmap, BITMAP_MAGIC);
1111 if (bmp && bmp->dib && bits32)
1113 const BITMAPINFOHEADER *bi = &bmi->bmiHeader;
1114 LONG width, height;
1115 WORD planes, bpp;
1116 DWORD compr, size;
1117 INT width_bytes;
1118 WORD count, sel;
1119 int i;
1121 DIB_GetBitmapInfo(bi, &width, &height, &planes, &bpp, &compr, &size);
1123 height = height >= 0 ? height : -height;
1124 width_bytes = DIB_GetDIBWidthBytes(width, bpp);
1126 if (!size || (compr != BI_RLE4 && compr != BI_RLE8)) size = width_bytes * height;
1128 /* calculate number of sel's needed for size with 64K steps */
1129 count = (size + 0xffff) / 0x10000;
1130 sel = AllocSelectorArray16(count);
1132 for (i = 0; i < count; i++)
1134 SetSelectorBase(sel + (i << __AHSHIFT), (DWORD)bits32 + i * 0x10000);
1135 SetSelectorLimit16(sel + (i << __AHSHIFT), size - 1); /* yep, limit is correct */
1136 size -= 0x10000;
1138 bmp->segptr_bits = MAKESEGPTR( sel, 0 );
1139 if (bits16) *bits16 = bmp->segptr_bits;
1141 if (bmp) GDI_ReleaseObj( hbitmap );
1143 return HBITMAP_16(hbitmap);
1146 /* Copy/synthetize RGB palette from BITMAPINFO. Ripped from dlls/winex11.drv/dib.c */
1147 static void DIB_CopyColorTable( DC *dc, BITMAPOBJ *bmp, WORD coloruse, const BITMAPINFO *info )
1149 RGBQUAD *colorTable;
1150 unsigned int colors;
1151 int i;
1152 BOOL core_info = info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER);
1154 if (core_info)
1156 colors = 1 << ((const BITMAPCOREINFO*) info)->bmciHeader.bcBitCount;
1158 else
1160 colors = info->bmiHeader.biClrUsed;
1161 if (!colors) colors = 1 << info->bmiHeader.biBitCount;
1164 if (colors > 256) {
1165 ERR("called with >256 colors!\n");
1166 return;
1169 if (!(colorTable = HeapAlloc(GetProcessHeap(), 0, colors * sizeof(RGBQUAD) ))) return;
1171 if(coloruse == DIB_RGB_COLORS)
1173 if (core_info)
1175 /* Convert RGBTRIPLEs to RGBQUADs */
1176 for (i=0; i < colors; i++)
1178 colorTable[i].rgbRed = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtRed;
1179 colorTable[i].rgbGreen = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtGreen;
1180 colorTable[i].rgbBlue = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtBlue;
1181 colorTable[i].rgbReserved = 0;
1184 else
1186 memcpy(colorTable, (const BYTE*) info + (WORD) info->bmiHeader.biSize, colors * sizeof(RGBQUAD));
1189 else
1191 PALETTEENTRY entries[256];
1192 const WORD *index = (const WORD*) ((const BYTE*) info + (WORD) info->bmiHeader.biSize);
1193 UINT count = GetPaletteEntries( dc->hPalette, 0, colors, entries );
1195 for (i = 0; i < colors; i++, index++)
1197 PALETTEENTRY *entry = &entries[*index % count];
1198 colorTable[i].rgbRed = entry->peRed;
1199 colorTable[i].rgbGreen = entry->peGreen;
1200 colorTable[i].rgbBlue = entry->peBlue;
1201 colorTable[i].rgbReserved = 0;
1204 bmp->color_table = colorTable;
1205 bmp->nb_colors = colors;
1208 /***********************************************************************
1209 * CreateDIBSection (GDI32.@)
1211 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
1212 VOID **bits, HANDLE section, DWORD offset)
1214 HBITMAP ret = 0;
1215 DC *dc;
1216 BOOL bDesktopDC = FALSE;
1217 DIBSECTION *dib;
1218 BITMAPOBJ *bmp;
1219 int bitmap_type;
1220 LONG width, height;
1221 WORD planes, bpp;
1222 DWORD compression, sizeImage;
1223 void *mapBits = NULL;
1225 if (((bitmap_type = DIB_GetBitmapInfo( &bmi->bmiHeader, &width, &height,
1226 &planes, &bpp, &compression, &sizeImage )) == -1))
1227 return 0;
1229 if (compression != BI_RGB && compression != BI_BITFIELDS)
1231 TRACE("can't create a compressed (%u) dibsection\n", compression);
1232 return 0;
1235 if (!(dib = HeapAlloc( GetProcessHeap(), 0, sizeof(*dib) ))) return 0;
1237 TRACE("format (%d,%d), planes %d, bpp %d, size %d, %s\n",
1238 width, height, planes, bpp, sizeImage, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1240 dib->dsBm.bmType = 0;
1241 dib->dsBm.bmWidth = width;
1242 dib->dsBm.bmHeight = height >= 0 ? height : -height;
1243 dib->dsBm.bmWidthBytes = DIB_GetDIBWidthBytes(width, bpp);
1244 dib->dsBm.bmPlanes = planes;
1245 dib->dsBm.bmBitsPixel = bpp;
1246 dib->dsBm.bmBits = NULL;
1248 if (!bitmap_type) /* core header */
1250 /* convert the BITMAPCOREHEADER to a BITMAPINFOHEADER */
1251 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1252 dib->dsBmih.biWidth = width;
1253 dib->dsBmih.biHeight = height;
1254 dib->dsBmih.biPlanes = planes;
1255 dib->dsBmih.biBitCount = bpp;
1256 dib->dsBmih.biCompression = compression;
1257 dib->dsBmih.biXPelsPerMeter = 0;
1258 dib->dsBmih.biYPelsPerMeter = 0;
1259 dib->dsBmih.biClrUsed = 0;
1260 dib->dsBmih.biClrImportant = 0;
1262 else
1264 /* truncate extended bitmap headers (BITMAPV4HEADER etc.) */
1265 dib->dsBmih = bmi->bmiHeader;
1266 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1269 /* set number of entries in bmi.bmiColors table */
1270 if( bpp <= 8 )
1271 dib->dsBmih.biClrUsed = 1 << bpp;
1273 dib->dsBmih.biSizeImage = dib->dsBm.bmWidthBytes * dib->dsBm.bmHeight;
1275 /* set dsBitfields values */
1276 if (usage == DIB_PAL_COLORS || bpp <= 8)
1278 dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
1280 else switch( bpp )
1282 case 15:
1283 case 16:
1284 dib->dsBitfields[0] = (compression == BI_BITFIELDS) ? *(const DWORD *)bmi->bmiColors : 0x7c00;
1285 dib->dsBitfields[1] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 1) : 0x03e0;
1286 dib->dsBitfields[2] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 2) : 0x001f;
1287 break;
1288 case 24:
1289 case 32:
1290 dib->dsBitfields[0] = (compression == BI_BITFIELDS) ? *(const DWORD *)bmi->bmiColors : 0xff0000;
1291 dib->dsBitfields[1] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 1) : 0x00ff00;
1292 dib->dsBitfields[2] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 2) : 0x0000ff;
1293 break;
1296 /* get storage location for DIB bits */
1298 if (section)
1300 SYSTEM_INFO SystemInfo;
1301 DWORD mapOffset;
1302 INT mapSize;
1304 GetSystemInfo( &SystemInfo );
1305 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
1306 mapSize = dib->dsBmih.biSizeImage + (offset - mapOffset);
1307 mapBits = MapViewOfFile( section, FILE_MAP_ALL_ACCESS, 0, mapOffset, mapSize );
1308 if (mapBits) dib->dsBm.bmBits = (char *)mapBits + (offset - mapOffset);
1310 else
1312 offset = 0;
1313 dib->dsBm.bmBits = VirtualAlloc( NULL, dib->dsBmih.biSizeImage,
1314 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
1316 dib->dshSection = section;
1317 dib->dsOffset = offset;
1319 if (!dib->dsBm.bmBits)
1321 HeapFree( GetProcessHeap(), 0, dib );
1322 return 0;
1325 /* If the reference hdc is null, take the desktop dc */
1326 if (hdc == 0)
1328 hdc = CreateCompatibleDC(0);
1329 bDesktopDC = TRUE;
1332 if (!(dc = DC_GetDCPtr( hdc ))) goto error;
1334 /* create Device Dependent Bitmap and add DIB pointer */
1335 ret = CreateBitmap( dib->dsBm.bmWidth, dib->dsBm.bmHeight, 1,
1336 (bpp == 1) ? 1 : GetDeviceCaps(hdc, BITSPIXEL), NULL );
1338 if (ret && ((bmp = GDI_GetObjPtr(ret, BITMAP_MAGIC))))
1340 bmp->dib = dib;
1341 bmp->funcs = dc->funcs;
1342 /* create local copy of DIB palette */
1343 if (bpp <= 8) DIB_CopyColorTable( dc, bmp, usage, bmi );
1344 GDI_ReleaseObj( ret );
1346 if (dc->funcs->pCreateDIBSection)
1348 if (!dc->funcs->pCreateDIBSection(dc->physDev, ret, bmi, usage))
1350 DeleteObject( ret );
1351 ret = 0;
1356 GDI_ReleaseObj(hdc);
1357 if (bDesktopDC) DeleteDC( hdc );
1358 if (ret && bits) *bits = dib->dsBm.bmBits;
1359 return ret;
1361 error:
1362 if (bDesktopDC) DeleteDC( hdc );
1363 if (section) UnmapViewOfFile( mapBits );
1364 else if (!offset) VirtualFree( dib->dsBm.bmBits, 0, MEM_RELEASE );
1365 HeapFree( GetProcessHeap(), 0, dib );
1366 return 0;