push 071493016fe1a315c0eb45bb83b2bbe9c1381c65
[wine/hacks.git] / dlls / gdi32 / dib.c
blob2b5ae374d44f4d068c441fa06dbc4927156c438b
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.
86 int DIB_GetDIBWidthBytes( int width, int depth )
88 int words;
90 switch(depth)
92 case 1: words = (width + 31) / 32; break;
93 case 4: words = (width + 7) / 8; break;
94 case 8: words = (width + 3) / 4; break;
95 case 15:
96 case 16: words = (width + 1) / 2; break;
97 case 24: words = (width * 3 + 3)/4; break;
99 default:
100 WARN("(%d): Unsupported depth\n", depth );
101 /* fall through */
102 case 32:
103 words = width;
105 return 4 * words;
108 /***********************************************************************
109 * DIB_GetDIBImageBytes
111 * Return the number of bytes used to hold the image in a DIB bitmap.
113 int DIB_GetDIBImageBytes( int width, int height, int depth )
115 return DIB_GetDIBWidthBytes( width, depth ) * abs( height );
119 /***********************************************************************
120 * DIB_BitmapInfoSize
122 * Return the size of the bitmap info structure including color table.
124 int DIB_BitmapInfoSize( const BITMAPINFO * info, WORD coloruse )
126 int colors;
128 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
130 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
131 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
132 return sizeof(BITMAPCOREHEADER) + colors *
133 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
135 else /* assume BITMAPINFOHEADER */
137 colors = info->bmiHeader.biClrUsed;
138 if (colors > 256) colors = 256;
139 if (!colors && (info->bmiHeader.biBitCount <= 8))
140 colors = 1 << info->bmiHeader.biBitCount;
141 return sizeof(BITMAPINFOHEADER) + colors *
142 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
147 /***********************************************************************
148 * DIB_GetBitmapInfo
150 * Get the info from a bitmap header.
151 * Return 0 for COREHEADER, 1 for INFOHEADER, -1 for error.
153 static int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
154 LONG *height, WORD *planes, WORD *bpp, DWORD *compr, DWORD *size )
156 if (header->biSize == sizeof(BITMAPCOREHEADER))
158 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)header;
159 *width = core->bcWidth;
160 *height = core->bcHeight;
161 *planes = core->bcPlanes;
162 *bpp = core->bcBitCount;
163 *compr = 0;
164 *size = 0;
165 return 0;
167 if (header->biSize >= sizeof(BITMAPINFOHEADER)) /* assume BITMAPINFOHEADER */
169 *width = header->biWidth;
170 *height = header->biHeight;
171 *planes = header->biPlanes;
172 *bpp = header->biBitCount;
173 *compr = header->biCompression;
174 *size = header->biSizeImage;
175 return 1;
177 ERR("(%d): unknown/wrong size for header\n", header->biSize );
178 return -1;
182 /***********************************************************************
183 * StretchDIBits (GDI32.@)
185 INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst,
186 INT heightDst, INT xSrc, INT ySrc, INT widthSrc,
187 INT heightSrc, const void *bits,
188 const BITMAPINFO *info, UINT wUsage, DWORD dwRop )
190 DC *dc;
191 INT ret;
193 if (!bits || !info)
194 return 0;
196 if (!(dc = get_dc_ptr( hdc ))) return 0;
198 if(dc->funcs->pStretchDIBits)
200 update_dc( dc );
201 ret = dc->funcs->pStretchDIBits(dc->physDev, xDst, yDst, widthDst,
202 heightDst, xSrc, ySrc, widthSrc,
203 heightSrc, bits, info, wUsage, dwRop);
204 release_dc_ptr( dc );
206 else /* use StretchBlt */
208 LONG height;
209 LONG width;
210 WORD planes, bpp;
211 DWORD compr, size;
212 HBITMAP hBitmap;
213 BOOL fastpath = FALSE;
215 release_dc_ptr( dc );
217 if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size ) == -1)
219 ERR("Invalid bitmap\n");
220 return 0;
223 if (width < 0)
225 ERR("Bitmap has a negative width\n");
226 return 0;
229 hBitmap = GetCurrentObject(hdc, OBJ_BITMAP);
231 if (xDst == 0 && yDst == 0 && xSrc == 0 && ySrc == 0 &&
232 widthDst == widthSrc && heightDst == heightSrc &&
233 info->bmiHeader.biCompression == BI_RGB &&
234 dwRop == SRCCOPY)
236 BITMAPOBJ *bmp;
237 if ((bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBitmap, BITMAP_MAGIC )))
239 if (bmp->bitmap.bmBitsPixel == bpp &&
240 bmp->bitmap.bmWidth == widthSrc &&
241 bmp->bitmap.bmHeight == heightSrc &&
242 bmp->bitmap.bmPlanes == planes)
243 fastpath = TRUE;
244 GDI_ReleaseObj( hBitmap );
248 if (fastpath)
250 /* fast path */
251 TRACE("using fast path\n");
252 ret = SetDIBits( hdc, hBitmap, 0, height, bits, info, wUsage);
254 else
256 /* slow path - need to use StretchBlt */
257 HBITMAP hOldBitmap;
258 HPALETTE hpal = NULL;
259 HDC hdcMem;
261 hdcMem = CreateCompatibleDC( hdc );
262 hBitmap = CreateCompatibleBitmap(hdc, width, height);
263 hOldBitmap = SelectObject( hdcMem, hBitmap );
264 if(wUsage == DIB_PAL_COLORS)
266 hpal = GetCurrentObject(hdc, OBJ_PAL);
267 hpal = SelectPalette(hdcMem, hpal, FALSE);
270 if (info->bmiHeader.biCompression == BI_RLE4 ||
271 info->bmiHeader.biCompression == BI_RLE8) {
273 /* when RLE compression is used, there may be some gaps (ie the DIB doesn't
274 * contain all the rectangle described in bmiHeader, but only part of it.
275 * This mean that those undescribed pixels must be left untouched.
276 * So, we first copy on a memory bitmap the current content of the
277 * destination rectangle, blit the DIB bits on top of it - hence leaving
278 * the gaps untouched -, and blitting the rectangle back.
279 * This insure that gaps are untouched on the destination rectangle
280 * Not doing so leads to trashed images (the gaps contain what was on the
281 * memory bitmap => generally black or garbage)
282 * Unfortunately, RLE DIBs without gaps will be slowed down. But this is
283 * another speed vs correctness issue. Anyway, if speed is needed, then the
284 * pStretchDIBits function shall be implemented.
285 * ericP (2000/09/09)
288 /* copy existing bitmap from destination dc */
289 StretchBlt( hdcMem, xSrc, abs(height) - heightSrc - ySrc,
290 widthSrc, heightSrc, hdc, xDst, yDst, widthDst, heightDst,
291 dwRop );
294 ret = SetDIBits(hdcMem, hBitmap, 0, height, bits, info, wUsage);
296 /* Origin for DIBitmap may be bottom left (positive biHeight) or top
297 left (negative biHeight) */
298 if (ret) StretchBlt( hdc, xDst, yDst, widthDst, heightDst,
299 hdcMem, xSrc, abs(height) - heightSrc - ySrc,
300 widthSrc, heightSrc, dwRop );
301 if(hpal)
302 SelectPalette(hdcMem, hpal, FALSE);
303 SelectObject( hdcMem, hOldBitmap );
304 DeleteDC( hdcMem );
305 DeleteObject( hBitmap );
308 return ret;
312 /******************************************************************************
313 * SetDIBits [GDI32.@]
315 * Sets pixels in a bitmap using colors from DIB.
317 * PARAMS
318 * hdc [I] Handle to device context
319 * hbitmap [I] Handle to bitmap
320 * startscan [I] Starting scan line
321 * lines [I] Number of scan lines
322 * bits [I] Array of bitmap bits
323 * info [I] Address of structure with data
324 * coloruse [I] Type of color indexes to use
326 * RETURNS
327 * Success: Number of scan lines copied
328 * Failure: 0
330 INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
331 UINT lines, LPCVOID bits, const BITMAPINFO *info,
332 UINT coloruse )
334 DC *dc;
335 BITMAPOBJ *bitmap;
336 INT result = 0;
338 if (!(dc = get_dc_ptr( hdc )))
340 if (coloruse == DIB_RGB_COLORS) FIXME( "shouldn't require a DC for DIB_RGB_COLORS\n" );
341 return 0;
344 update_dc( dc );
346 if (!(bitmap = GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
348 release_dc_ptr( dc );
349 return 0;
352 if (!bitmap->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) goto done;
354 result = lines;
355 if (bitmap->funcs)
357 if (bitmap->funcs != dc->funcs)
358 ERR( "not supported: DDB bitmap %p not belonging to device %p\n", hbitmap, hdc );
359 else if (dc->funcs->pSetDIBits)
360 result = dc->funcs->pSetDIBits( dc->physDev, hbitmap, startscan, lines,
361 bits, info, coloruse );
364 done:
365 GDI_ReleaseObj( hbitmap );
366 release_dc_ptr( dc );
367 return result;
371 /***********************************************************************
372 * SetDIBitsToDevice (GDI32.@)
374 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
375 DWORD cy, INT xSrc, INT ySrc, UINT startscan,
376 UINT lines, LPCVOID bits, const BITMAPINFO *info,
377 UINT coloruse )
379 INT ret;
380 DC *dc;
382 if (!bits) return 0;
384 if (!(dc = get_dc_ptr( hdc ))) return 0;
386 if(dc->funcs->pSetDIBitsToDevice)
388 update_dc( dc );
389 ret = dc->funcs->pSetDIBitsToDevice( dc->physDev, xDest, yDest, cx, cy, xSrc,
390 ySrc, startscan, lines, bits,
391 info, coloruse );
393 else {
394 FIXME("unimplemented on hdc %p\n", hdc);
395 ret = 0;
398 release_dc_ptr( dc );
399 return ret;
402 /***********************************************************************
403 * SetDIBColorTable (GDI32.@)
405 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, CONST RGBQUAD *colors )
407 DC * dc;
408 UINT result = 0;
409 BITMAPOBJ * bitmap;
411 if (!(dc = get_dc_ptr( hdc ))) return 0;
413 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, BITMAP_MAGIC )))
415 /* Check if currently selected bitmap is a DIB */
416 if (bitmap->color_table)
418 if (startpos < bitmap->nb_colors)
420 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
421 memcpy(bitmap->color_table + startpos, colors, entries * sizeof(RGBQUAD));
422 result = entries;
425 GDI_ReleaseObj( dc->hBitmap );
428 if (dc->funcs->pSetDIBColorTable)
429 dc->funcs->pSetDIBColorTable(dc->physDev, startpos, entries, colors);
431 release_dc_ptr( dc );
432 return result;
436 /***********************************************************************
437 * GetDIBColorTable (GDI32.@)
439 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
441 DC * dc;
442 UINT result = 0;
444 if (!(dc = get_dc_ptr( hdc ))) return 0;
446 if (dc->funcs->pGetDIBColorTable)
447 result = dc->funcs->pGetDIBColorTable(dc->physDev, startpos, entries, colors);
448 else
450 BITMAPOBJ *bitmap = GDI_GetObjPtr( dc->hBitmap, BITMAP_MAGIC );
451 if (bitmap)
453 /* Check if currently selected bitmap is a DIB */
454 if (bitmap->color_table)
456 if (startpos < bitmap->nb_colors)
458 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
459 memcpy(colors, bitmap->color_table + startpos, entries * sizeof(RGBQUAD));
460 result = entries;
463 GDI_ReleaseObj( dc->hBitmap );
466 release_dc_ptr( dc );
467 return result;
470 /* FIXME the following two structs should be combined with __sysPalTemplate in
471 objects/color.c - this should happen after de-X11-ing both of these
472 files.
473 NB. RGBQUAD and PALETTEENTRY have different orderings of red, green
474 and blue - sigh */
476 static const RGBQUAD EGAColorsQuads[16] = {
477 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
478 { 0x00, 0x00, 0x00, 0x00 },
479 { 0x00, 0x00, 0x80, 0x00 },
480 { 0x00, 0x80, 0x00, 0x00 },
481 { 0x00, 0x80, 0x80, 0x00 },
482 { 0x80, 0x00, 0x00, 0x00 },
483 { 0x80, 0x00, 0x80, 0x00 },
484 { 0x80, 0x80, 0x00, 0x00 },
485 { 0x80, 0x80, 0x80, 0x00 },
486 { 0xc0, 0xc0, 0xc0, 0x00 },
487 { 0x00, 0x00, 0xff, 0x00 },
488 { 0x00, 0xff, 0x00, 0x00 },
489 { 0x00, 0xff, 0xff, 0x00 },
490 { 0xff, 0x00, 0x00, 0x00 },
491 { 0xff, 0x00, 0xff, 0x00 },
492 { 0xff, 0xff, 0x00, 0x00 },
493 { 0xff, 0xff, 0xff, 0x00 }
496 static const RGBTRIPLE EGAColorsTriples[16] = {
497 /* rgbBlue, rgbGreen, rgbRed */
498 { 0x00, 0x00, 0x00 },
499 { 0x00, 0x00, 0x80 },
500 { 0x00, 0x80, 0x00 },
501 { 0x00, 0x80, 0x80 },
502 { 0x80, 0x00, 0x00 },
503 { 0x80, 0x00, 0x80 },
504 { 0x80, 0x80, 0x00 },
505 { 0x80, 0x80, 0x80 },
506 { 0xc0, 0xc0, 0xc0 },
507 { 0x00, 0x00, 0xff },
508 { 0x00, 0xff, 0x00 },
509 { 0x00, 0xff, 0xff },
510 { 0xff, 0x00, 0x00 } ,
511 { 0xff, 0x00, 0xff },
512 { 0xff, 0xff, 0x00 },
513 { 0xff, 0xff, 0xff }
516 static const RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
517 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
518 { 0x00, 0x00, 0x00, 0x00 },
519 { 0x00, 0x00, 0x80, 0x00 },
520 { 0x00, 0x80, 0x00, 0x00 },
521 { 0x00, 0x80, 0x80, 0x00 },
522 { 0x80, 0x00, 0x00, 0x00 },
523 { 0x80, 0x00, 0x80, 0x00 },
524 { 0x80, 0x80, 0x00, 0x00 },
525 { 0xc0, 0xc0, 0xc0, 0x00 },
526 { 0xc0, 0xdc, 0xc0, 0x00 },
527 { 0xf0, 0xca, 0xa6, 0x00 },
528 { 0xf0, 0xfb, 0xff, 0x00 },
529 { 0xa4, 0xa0, 0xa0, 0x00 },
530 { 0x80, 0x80, 0x80, 0x00 },
531 { 0x00, 0x00, 0xf0, 0x00 },
532 { 0x00, 0xff, 0x00, 0x00 },
533 { 0x00, 0xff, 0xff, 0x00 },
534 { 0xff, 0x00, 0x00, 0x00 },
535 { 0xff, 0x00, 0xff, 0x00 },
536 { 0xff, 0xff, 0x00, 0x00 },
537 { 0xff, 0xff, 0xff, 0x00 }
540 static const RGBTRIPLE DefLogPaletteTriples[20] = { /* Copy of Default Logical Palette */
541 /* rgbBlue, rgbGreen, rgbRed */
542 { 0x00, 0x00, 0x00 },
543 { 0x00, 0x00, 0x80 },
544 { 0x00, 0x80, 0x00 },
545 { 0x00, 0x80, 0x80 },
546 { 0x80, 0x00, 0x00 },
547 { 0x80, 0x00, 0x80 },
548 { 0x80, 0x80, 0x00 },
549 { 0xc0, 0xc0, 0xc0 },
550 { 0xc0, 0xdc, 0xc0 },
551 { 0xf0, 0xca, 0xa6 },
552 { 0xf0, 0xfb, 0xff },
553 { 0xa4, 0xa0, 0xa0 },
554 { 0x80, 0x80, 0x80 },
555 { 0x00, 0x00, 0xf0 },
556 { 0x00, 0xff, 0x00 },
557 { 0x00, 0xff, 0xff },
558 { 0xff, 0x00, 0x00 },
559 { 0xff, 0x00, 0xff },
560 { 0xff, 0xff, 0x00 },
561 { 0xff, 0xff, 0xff}
565 /******************************************************************************
566 * GetDIBits [GDI32.@]
568 * Retrieves bits of bitmap and copies to buffer.
570 * RETURNS
571 * Success: Number of scan lines copied from bitmap
572 * Failure: 0
574 INT WINAPI GetDIBits(
575 HDC hdc, /* [in] Handle to device context */
576 HBITMAP hbitmap, /* [in] Handle to bitmap */
577 UINT startscan, /* [in] First scan line to set in dest bitmap */
578 UINT lines, /* [in] Number of scan lines to copy */
579 LPVOID bits, /* [out] Address of array for bitmap bits */
580 BITMAPINFO * info, /* [out] Address of structure with bitmap data */
581 UINT coloruse) /* [in] RGB or palette index */
583 DC * dc;
584 BITMAPOBJ * bmp;
585 int i;
586 int bitmap_type;
587 BOOL core_header;
588 LONG width;
589 LONG height;
590 WORD planes, bpp;
591 DWORD compr, size;
592 void* colorPtr;
593 RGBTRIPLE* rgbTriples;
594 RGBQUAD* rgbQuads;
596 if (!info) return 0;
598 bitmap_type = DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size);
599 if (bitmap_type == -1)
601 ERR("Invalid bitmap format\n");
602 return 0;
604 core_header = (bitmap_type == 0);
605 if (!(dc = get_dc_ptr( hdc )))
607 SetLastError( ERROR_INVALID_PARAMETER );
608 return 0;
610 update_dc( dc );
611 if (!(bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
613 release_dc_ptr( dc );
614 return 0;
617 colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
618 rgbTriples = (RGBTRIPLE *) colorPtr;
619 rgbQuads = (RGBQUAD *) colorPtr;
621 /* Transfer color info */
623 if (bpp <= 8 && bpp > 0)
625 if (!core_header) info->bmiHeader.biClrUsed = 0;
627 /* If the bitmap object already has a dib section at the
628 same color depth then get the color map from it */
629 if (bmp->dib && bmp->dib->dsBm.bmBitsPixel == bpp) {
630 if(coloruse == DIB_RGB_COLORS) {
631 unsigned int colors = min( bmp->nb_colors, 1 << bpp );
633 if (core_header)
635 /* Convert the color table (RGBQUAD to RGBTRIPLE) */
636 RGBTRIPLE* index = rgbTriples;
638 for (i=0; i < colors; i++, index++)
640 index->rgbtRed = bmp->color_table[i].rgbRed;
641 index->rgbtGreen = bmp->color_table[i].rgbGreen;
642 index->rgbtBlue = bmp->color_table[i].rgbBlue;
645 else
647 if (colors != 1 << bpp) info->bmiHeader.biClrUsed = colors;
648 memcpy(colorPtr, bmp->color_table, colors * sizeof(RGBQUAD));
651 else {
652 WORD *index = colorPtr;
653 for(i = 0; i < 1 << info->bmiHeader.biBitCount; i++, index++)
654 *index = i;
657 else {
658 if(bpp >= bmp->bitmap.bmBitsPixel) {
659 /* Generate the color map from the selected palette */
660 PALETTEENTRY palEntry[256];
662 memset( palEntry, 0, sizeof(palEntry) );
663 if (!GetPaletteEntries( dc->hPalette, 0, 1 << bmp->bitmap.bmBitsPixel, palEntry ))
665 release_dc_ptr( dc );
666 GDI_ReleaseObj( hbitmap );
667 return 0;
669 for (i = 0; i < (1 << bmp->bitmap.bmBitsPixel); i++) {
670 if (coloruse == DIB_RGB_COLORS) {
671 if (core_header)
673 rgbTriples[i].rgbtRed = palEntry[i].peRed;
674 rgbTriples[i].rgbtGreen = palEntry[i].peGreen;
675 rgbTriples[i].rgbtBlue = palEntry[i].peBlue;
677 else
679 rgbQuads[i].rgbRed = palEntry[i].peRed;
680 rgbQuads[i].rgbGreen = palEntry[i].peGreen;
681 rgbQuads[i].rgbBlue = palEntry[i].peBlue;
682 rgbQuads[i].rgbReserved = 0;
685 else ((WORD *)colorPtr)[i] = (WORD)i;
687 } else {
688 switch (bpp) {
689 case 1:
690 if (core_header)
692 rgbTriples[0].rgbtRed = rgbTriples[0].rgbtGreen =
693 rgbTriples[0].rgbtBlue = 0;
694 rgbTriples[1].rgbtRed = rgbTriples[1].rgbtGreen =
695 rgbTriples[1].rgbtBlue = 0xff;
697 else
699 rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen =
700 rgbQuads[0].rgbBlue = 0;
701 rgbQuads[0].rgbReserved = 0;
702 rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen =
703 rgbQuads[1].rgbBlue = 0xff;
704 rgbQuads[1].rgbReserved = 0;
706 break;
708 case 4:
709 if (core_header)
710 memcpy(colorPtr, EGAColorsTriples, sizeof(EGAColorsTriples));
711 else
712 memcpy(colorPtr, EGAColorsQuads, sizeof(EGAColorsQuads));
714 break;
716 case 8:
718 if (core_header)
720 INT r, g, b;
721 RGBTRIPLE *color;
723 memcpy(rgbTriples, DefLogPaletteTriples,
724 10 * sizeof(RGBTRIPLE));
725 memcpy(rgbTriples + 246, DefLogPaletteTriples + 10,
726 10 * sizeof(RGBTRIPLE));
727 color = rgbTriples + 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->rgbtRed = (r * 0xff) / 5;
732 color->rgbtGreen = (g * 0xff) / 5;
733 color->rgbtBlue = (b * 0xff) / 5;
734 color++;
737 else
739 INT r, g, b;
740 RGBQUAD *color;
742 memcpy(rgbQuads, DefLogPaletteQuads,
743 10 * sizeof(RGBQUAD));
744 memcpy(rgbQuads + 246, DefLogPaletteQuads + 10,
745 10 * sizeof(RGBQUAD));
746 color = rgbQuads + 10;
747 for(r = 0; r <= 5; r++) /* FIXME */
748 for(g = 0; g <= 5; g++)
749 for(b = 0; b <= 5; b++) {
750 color->rgbRed = (r * 0xff) / 5;
751 color->rgbGreen = (g * 0xff) / 5;
752 color->rgbBlue = (b * 0xff) / 5;
753 color->rgbReserved = 0;
754 color++;
763 if (bits && lines)
765 /* If the bitmap object already have a dib section that contains image data, get the bits from it */
766 if(bmp->dib && bmp->dib->dsBm.bmBitsPixel >= 15 && bpp >= 15)
768 /*FIXME: Only RGB dibs supported for now */
769 unsigned int srcwidth = bmp->dib->dsBm.bmWidth, srcwidthb = bmp->dib->dsBm.bmWidthBytes;
770 unsigned int dstwidth = width;
771 int dstwidthb = DIB_GetDIBWidthBytes( width, bpp );
772 LPBYTE dbits = bits, sbits = (LPBYTE) bmp->dib->dsBm.bmBits + (startscan * srcwidthb);
773 unsigned int x, y, width, widthb;
775 if ((height < 0) ^ (bmp->dib->dsBmih.biHeight < 0))
777 dbits = (LPBYTE)bits + (dstwidthb * (lines-1));
778 dstwidthb = -dstwidthb;
781 switch( bpp ) {
783 case 15:
784 case 16: /* 16 bpp dstDIB */
786 LPWORD dstbits = (LPWORD)dbits;
787 WORD rmask = 0x7c00, gmask= 0x03e0, bmask = 0x001f;
789 /* FIXME: BI_BITFIELDS not supported yet */
791 switch(bmp->dib->dsBm.bmBitsPixel) {
793 case 16: /* 16 bpp srcDIB -> 16 bpp dstDIB */
795 widthb = min(srcwidthb, abs(dstwidthb));
796 /* FIXME: BI_BITFIELDS not supported yet */
797 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
798 memcpy(dbits, sbits, widthb);
800 break;
802 case 24: /* 24 bpp srcDIB -> 16 bpp dstDIB */
804 LPBYTE srcbits = sbits;
806 width = min(srcwidth, dstwidth);
807 for( y = 0; y < lines; y++) {
808 for( x = 0; x < width; x++, srcbits += 3)
809 *dstbits++ = ((srcbits[0] >> 3) & bmask) |
810 (((WORD)srcbits[1] << 2) & gmask) |
811 (((WORD)srcbits[2] << 7) & rmask);
813 dstbits = (LPWORD)(dbits+=dstwidthb);
814 srcbits = (sbits += srcwidthb);
817 break;
819 case 32: /* 32 bpp srcDIB -> 16 bpp dstDIB */
821 LPDWORD srcbits = (LPDWORD)sbits;
822 DWORD val;
824 width = min(srcwidth, dstwidth);
825 for( y = 0; y < lines; y++) {
826 for( x = 0; x < width; x++ ) {
827 val = *srcbits++;
828 *dstbits++ = (WORD)(((val >> 3) & bmask) | ((val >> 6) & gmask) |
829 ((val >> 9) & rmask));
831 dstbits = (LPWORD)(dbits+=dstwidthb);
832 srcbits = (LPDWORD)(sbits+=srcwidthb);
835 break;
837 default: /* ? bit bmp -> 16 bit DIB */
838 FIXME("15/16 bit DIB %d bit bitmap\n",
839 bmp->bitmap.bmBitsPixel);
840 break;
843 break;
845 case 24: /* 24 bpp dstDIB */
847 LPBYTE dstbits = dbits;
849 switch(bmp->dib->dsBm.bmBitsPixel) {
851 case 16: /* 16 bpp srcDIB -> 24 bpp dstDIB */
853 LPWORD srcbits = (LPWORD)sbits;
854 WORD val;
856 width = min(srcwidth, dstwidth);
857 /* FIXME: BI_BITFIELDS not supported yet */
858 for( y = 0; y < lines; y++) {
859 for( x = 0; x < width; x++ ) {
860 val = *srcbits++;
861 *dstbits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07));
862 *dstbits++ = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07));
863 *dstbits++ = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07));
865 dstbits = dbits+=dstwidthb;
866 srcbits = (LPWORD)(sbits+=srcwidthb);
869 break;
871 case 24: /* 24 bpp srcDIB -> 24 bpp dstDIB */
873 widthb = min(srcwidthb, abs(dstwidthb));
874 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
875 memcpy(dbits, sbits, widthb);
877 break;
879 case 32: /* 32 bpp srcDIB -> 24 bpp dstDIB */
881 LPBYTE srcbits = sbits;
883 width = min(srcwidth, dstwidth);
884 for( y = 0; y < lines; y++) {
885 for( x = 0; x < width; x++, srcbits++ ) {
886 *dstbits++ = *srcbits++;
887 *dstbits++ = *srcbits++;
888 *dstbits++ = *srcbits++;
890 dstbits = dbits+=dstwidthb;
891 srcbits = sbits+=srcwidthb;
894 break;
896 default: /* ? bit bmp -> 24 bit DIB */
897 FIXME("24 bit DIB %d bit bitmap\n",
898 bmp->bitmap.bmBitsPixel);
899 break;
902 break;
904 case 32: /* 32 bpp dstDIB */
906 LPDWORD dstbits = (LPDWORD)dbits;
908 /* FIXME: BI_BITFIELDS not supported yet */
910 switch(bmp->dib->dsBm.bmBitsPixel) {
911 case 16: /* 16 bpp srcDIB -> 32 bpp dstDIB */
913 LPWORD srcbits = (LPWORD)sbits;
914 DWORD val;
916 width = min(srcwidth, dstwidth);
917 /* FIXME: BI_BITFIELDS not supported yet */
918 for( y = 0; y < lines; y++) {
919 for( x = 0; x < width; x++ ) {
920 val = (DWORD)*srcbits++;
921 *dstbits++ = ((val << 3) & 0xf8) | ((val >> 2) & 0x07) |
922 ((val << 6) & 0xf800) | ((val << 1) & 0x0700) |
923 ((val << 9) & 0xf80000) | ((val << 4) & 0x070000);
925 dstbits=(LPDWORD)(dbits+=dstwidthb);
926 srcbits=(LPWORD)(sbits+=srcwidthb);
929 break;
931 case 24: /* 24 bpp srcDIB -> 32 bpp dstDIB */
933 LPBYTE srcbits = sbits;
935 width = min(srcwidth, dstwidth);
936 for( y = 0; y < lines; y++) {
937 for( x = 0; x < width; x++, srcbits+=3 )
938 *dstbits++ = srcbits[0] |
939 (srcbits[1] << 8) |
940 (srcbits[2] << 16);
941 dstbits=(LPDWORD)(dbits+=dstwidthb);
942 srcbits=(sbits+=srcwidthb);
945 break;
947 case 32: /* 32 bpp srcDIB -> 32 bpp dstDIB */
949 widthb = min(srcwidthb, abs(dstwidthb));
950 /* FIXME: BI_BITFIELDS not supported yet */
951 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb) {
952 memcpy(dbits, sbits, widthb);
955 break;
957 default: /* ? bit bmp -> 32 bit DIB */
958 FIXME("32 bit DIB %d bit bitmap\n",
959 bmp->bitmap.bmBitsPixel);
960 break;
963 break;
965 default: /* ? bit DIB */
966 FIXME("Unsupported DIB depth %d\n", info->bmiHeader.biBitCount);
967 break;
970 /* Otherwise, get bits from the XImage */
971 else
973 if (!bmp->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) lines = 0;
974 else
976 if (bmp->funcs && bmp->funcs->pGetDIBits)
977 lines = bmp->funcs->pGetDIBits( dc->physDev, hbitmap, startscan,
978 lines, bits, info, coloruse );
979 else
980 lines = 0; /* FIXME: should copy from bmp->bitmap.bmBits */
984 else
986 /* fill in struct members */
988 if (bpp == 0)
990 if (core_header)
992 BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) info;
993 coreheader->bcWidth = bmp->bitmap.bmWidth;
994 coreheader->bcHeight = bmp->bitmap.bmHeight;
995 coreheader->bcPlanes = 1;
996 coreheader->bcBitCount = bmp->bitmap.bmBitsPixel;
998 else
1000 info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
1001 info->bmiHeader.biHeight = bmp->bitmap.bmHeight;
1002 info->bmiHeader.biPlanes = 1;
1003 info->bmiHeader.biSizeImage =
1004 DIB_GetDIBImageBytes( bmp->bitmap.bmWidth,
1005 bmp->bitmap.bmHeight,
1006 bmp->bitmap.bmBitsPixel );
1007 switch(bmp->bitmap.bmBitsPixel)
1009 case 15:
1010 info->bmiHeader.biBitCount = 16;
1011 info->bmiHeader.biCompression = BI_RGB;
1012 break;
1014 case 16:
1015 if (bits)
1017 /* Add color only when bits is given, as per MSDN */
1018 ((PDWORD)info->bmiColors)[0] = 0xf800;
1019 ((PDWORD)info->bmiColors)[1] = 0x07e0;
1020 ((PDWORD)info->bmiColors)[2] = 0x001f;
1022 info->bmiHeader.biBitCount = 16;
1023 info->bmiHeader.biCompression = BI_BITFIELDS;
1024 break;
1026 default:
1027 info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
1028 info->bmiHeader.biCompression = BI_RGB;
1029 break;
1031 info->bmiHeader.biXPelsPerMeter = 0;
1032 info->bmiHeader.biYPelsPerMeter = 0;
1033 info->bmiHeader.biClrUsed = 0;
1034 info->bmiHeader.biClrImportant = 0;
1036 /* Windows 2000 doesn't touch the additional struct members if
1037 it's a BITMAPV4HEADER or a BITMAPV5HEADER */
1039 lines = abs(bmp->bitmap.bmHeight);
1041 else
1043 /* The knowledge base article Q81498 ("DIBs and Their Uses") states that
1044 if bits == NULL and bpp != 0, only biSizeImage and the color table are
1045 filled in. */
1046 if (!core_header)
1048 /* FIXME: biSizeImage should be calculated according to the selected
1049 compression algorithm if biCompression != BI_RGB */
1050 info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes( width, height, bpp );
1052 lines = abs(height);
1056 if (!core_header)
1058 TRACE("biSizeImage = %d, ", info->bmiHeader.biSizeImage);
1060 TRACE("biWidth = %d, biHeight = %d\n", width, height);
1062 release_dc_ptr( dc );
1063 GDI_ReleaseObj( hbitmap );
1064 return lines;
1068 /***********************************************************************
1069 * CreateDIBitmap (GDI32.@)
1071 * Creates a DDB (device dependent bitmap) from a DIB.
1072 * The DDB will have the same color depth as the reference DC.
1074 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
1075 DWORD init, LPCVOID bits, const BITMAPINFO *data,
1076 UINT coloruse )
1078 HBITMAP handle;
1079 LONG width;
1080 LONG height;
1081 WORD planes, bpp;
1082 DWORD compr, size;
1083 DC *dc;
1085 if (DIB_GetBitmapInfo( header, &width, &height, &planes, &bpp, &compr, &size ) == -1) return 0;
1087 if (width < 0)
1089 TRACE("Bitmap has a negative width\n");
1090 return 0;
1093 /* Top-down DIBs have a negative height */
1094 if (height < 0) height = -height;
1096 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1097 hdc, header, init, bits, data, coloruse, width, height, bpp, compr);
1099 if (hdc == NULL)
1100 handle = CreateBitmap( width, height, 1, 1, NULL );
1101 else
1102 handle = CreateCompatibleBitmap( hdc, width, height );
1104 if (handle)
1106 if (init == CBM_INIT) SetDIBits( hdc, handle, 0, height, bits, data, coloruse );
1108 else if (hdc && ((dc = get_dc_ptr( hdc )) != NULL) )
1110 if (!BITMAP_SetOwnerDC( handle, dc ))
1112 DeleteObject( handle );
1113 handle = 0;
1115 release_dc_ptr( dc );
1119 return handle;
1122 /***********************************************************************
1123 * CreateDIBSection (GDI.489)
1125 HBITMAP16 WINAPI CreateDIBSection16 (HDC16 hdc, const BITMAPINFO *bmi, UINT16 usage,
1126 SEGPTR *bits16, HANDLE section, DWORD offset)
1128 LPVOID bits32;
1129 HBITMAP hbitmap;
1131 hbitmap = CreateDIBSection( HDC_32(hdc), bmi, usage, &bits32, section, offset );
1132 if (hbitmap)
1134 BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr(hbitmap, BITMAP_MAGIC);
1135 if (bmp && bmp->dib && bits32)
1137 const BITMAPINFOHEADER *bi = &bmi->bmiHeader;
1138 LONG width, height;
1139 WORD planes, bpp;
1140 DWORD compr, size;
1141 INT width_bytes;
1142 WORD count, sel;
1143 int i;
1145 DIB_GetBitmapInfo(bi, &width, &height, &planes, &bpp, &compr, &size);
1147 height = height >= 0 ? height : -height;
1148 width_bytes = DIB_GetDIBWidthBytes(width, bpp);
1150 if (!size || (compr != BI_RLE4 && compr != BI_RLE8)) size = width_bytes * height;
1152 /* calculate number of sel's needed for size with 64K steps */
1153 count = (size + 0xffff) / 0x10000;
1154 sel = AllocSelectorArray16(count);
1156 for (i = 0; i < count; i++)
1158 SetSelectorBase(sel + (i << __AHSHIFT), (DWORD)bits32 + i * 0x10000);
1159 SetSelectorLimit16(sel + (i << __AHSHIFT), size - 1); /* yep, limit is correct */
1160 size -= 0x10000;
1162 bmp->segptr_bits = MAKESEGPTR( sel, 0 );
1163 if (bits16) *bits16 = bmp->segptr_bits;
1165 if (bmp) GDI_ReleaseObj( hbitmap );
1167 return HBITMAP_16(hbitmap);
1170 /* Copy/synthesize RGB palette from BITMAPINFO. Ripped from dlls/winex11.drv/dib.c */
1171 static void DIB_CopyColorTable( DC *dc, BITMAPOBJ *bmp, WORD coloruse, const BITMAPINFO *info )
1173 RGBQUAD *colorTable;
1174 unsigned int colors;
1175 int i;
1176 BOOL core_info = info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER);
1178 if (core_info)
1180 colors = 1 << ((const BITMAPCOREINFO*) info)->bmciHeader.bcBitCount;
1182 else
1184 colors = info->bmiHeader.biClrUsed;
1185 if (!colors) colors = 1 << info->bmiHeader.biBitCount;
1188 if (colors > 256) {
1189 ERR("called with >256 colors!\n");
1190 return;
1193 if (!(colorTable = HeapAlloc(GetProcessHeap(), 0, colors * sizeof(RGBQUAD) ))) return;
1195 if(coloruse == DIB_RGB_COLORS)
1197 if (core_info)
1199 /* Convert RGBTRIPLEs to RGBQUADs */
1200 for (i=0; i < colors; i++)
1202 colorTable[i].rgbRed = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtRed;
1203 colorTable[i].rgbGreen = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtGreen;
1204 colorTable[i].rgbBlue = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtBlue;
1205 colorTable[i].rgbReserved = 0;
1208 else
1210 memcpy(colorTable, (const BYTE*) info + (WORD) info->bmiHeader.biSize, colors * sizeof(RGBQUAD));
1213 else
1215 PALETTEENTRY entries[256];
1216 const WORD *index = (const WORD*) ((const BYTE*) info + (WORD) info->bmiHeader.biSize);
1217 UINT count = GetPaletteEntries( dc->hPalette, 0, colors, entries );
1219 for (i = 0; i < colors; i++, index++)
1221 PALETTEENTRY *entry = &entries[*index % count];
1222 colorTable[i].rgbRed = entry->peRed;
1223 colorTable[i].rgbGreen = entry->peGreen;
1224 colorTable[i].rgbBlue = entry->peBlue;
1225 colorTable[i].rgbReserved = 0;
1228 bmp->color_table = colorTable;
1229 bmp->nb_colors = colors;
1232 /***********************************************************************
1233 * CreateDIBSection (GDI32.@)
1235 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
1236 VOID **bits, HANDLE section, DWORD offset)
1238 HBITMAP ret = 0;
1239 DC *dc;
1240 BOOL bDesktopDC = FALSE;
1241 DIBSECTION *dib;
1242 BITMAPOBJ *bmp;
1243 int bitmap_type;
1244 LONG width, height;
1245 WORD planes, bpp;
1246 DWORD compression, sizeImage;
1247 void *mapBits = NULL;
1249 if (((bitmap_type = DIB_GetBitmapInfo( &bmi->bmiHeader, &width, &height,
1250 &planes, &bpp, &compression, &sizeImage )) == -1))
1251 return 0;
1253 if (compression != BI_RGB && compression != BI_BITFIELDS)
1255 TRACE("can't create a compressed (%u) dibsection\n", compression);
1256 return 0;
1259 if (!(dib = HeapAlloc( GetProcessHeap(), 0, sizeof(*dib) ))) return 0;
1261 TRACE("format (%d,%d), planes %d, bpp %d, size %d, %s\n",
1262 width, height, planes, bpp, sizeImage, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1264 dib->dsBm.bmType = 0;
1265 dib->dsBm.bmWidth = width;
1266 dib->dsBm.bmHeight = height >= 0 ? height : -height;
1267 dib->dsBm.bmWidthBytes = DIB_GetDIBWidthBytes(width, bpp);
1268 dib->dsBm.bmPlanes = planes;
1269 dib->dsBm.bmBitsPixel = bpp;
1270 dib->dsBm.bmBits = NULL;
1272 if (!bitmap_type) /* core header */
1274 /* convert the BITMAPCOREHEADER to a BITMAPINFOHEADER */
1275 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1276 dib->dsBmih.biWidth = width;
1277 dib->dsBmih.biHeight = height;
1278 dib->dsBmih.biPlanes = planes;
1279 dib->dsBmih.biBitCount = bpp;
1280 dib->dsBmih.biCompression = compression;
1281 dib->dsBmih.biXPelsPerMeter = 0;
1282 dib->dsBmih.biYPelsPerMeter = 0;
1283 dib->dsBmih.biClrUsed = 0;
1284 dib->dsBmih.biClrImportant = 0;
1286 else
1288 /* truncate extended bitmap headers (BITMAPV4HEADER etc.) */
1289 dib->dsBmih = bmi->bmiHeader;
1290 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1293 /* set number of entries in bmi.bmiColors table */
1294 if( bpp <= 8 )
1295 dib->dsBmih.biClrUsed = 1 << bpp;
1297 dib->dsBmih.biSizeImage = dib->dsBm.bmWidthBytes * dib->dsBm.bmHeight;
1299 /* set dsBitfields values */
1300 if (usage == DIB_PAL_COLORS || bpp <= 8)
1302 dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
1304 else switch( bpp )
1306 case 15:
1307 case 16:
1308 dib->dsBitfields[0] = (compression == BI_BITFIELDS) ? *(const DWORD *)bmi->bmiColors : 0x7c00;
1309 dib->dsBitfields[1] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 1) : 0x03e0;
1310 dib->dsBitfields[2] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 2) : 0x001f;
1311 break;
1312 case 24:
1313 case 32:
1314 dib->dsBitfields[0] = (compression == BI_BITFIELDS) ? *(const DWORD *)bmi->bmiColors : 0xff0000;
1315 dib->dsBitfields[1] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 1) : 0x00ff00;
1316 dib->dsBitfields[2] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 2) : 0x0000ff;
1317 break;
1320 /* get storage location for DIB bits */
1322 if (section)
1324 SYSTEM_INFO SystemInfo;
1325 DWORD mapOffset;
1326 INT mapSize;
1328 GetSystemInfo( &SystemInfo );
1329 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
1330 mapSize = dib->dsBmih.biSizeImage + (offset - mapOffset);
1331 mapBits = MapViewOfFile( section, FILE_MAP_ALL_ACCESS, 0, mapOffset, mapSize );
1332 if (mapBits) dib->dsBm.bmBits = (char *)mapBits + (offset - mapOffset);
1334 else
1336 offset = 0;
1337 dib->dsBm.bmBits = VirtualAlloc( NULL, dib->dsBmih.biSizeImage,
1338 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
1340 dib->dshSection = section;
1341 dib->dsOffset = offset;
1343 if (!dib->dsBm.bmBits)
1345 HeapFree( GetProcessHeap(), 0, dib );
1346 return 0;
1349 /* If the reference hdc is null, take the desktop dc */
1350 if (hdc == 0)
1352 hdc = CreateCompatibleDC(0);
1353 bDesktopDC = TRUE;
1356 if (!(dc = get_dc_ptr( hdc ))) goto error;
1358 /* create Device Dependent Bitmap and add DIB pointer */
1359 ret = CreateBitmap( dib->dsBm.bmWidth, dib->dsBm.bmHeight, 1,
1360 (bpp == 1) ? 1 : GetDeviceCaps(hdc, BITSPIXEL), NULL );
1362 if (ret && ((bmp = GDI_GetObjPtr(ret, BITMAP_MAGIC))))
1364 bmp->dib = dib;
1365 bmp->funcs = dc->funcs;
1366 /* create local copy of DIB palette */
1367 if (bpp <= 8) DIB_CopyColorTable( dc, bmp, usage, bmi );
1368 GDI_ReleaseObj( ret );
1370 if (dc->funcs->pCreateDIBSection)
1372 if (!dc->funcs->pCreateDIBSection(dc->physDev, ret, bmi, usage))
1374 DeleteObject( ret );
1375 ret = 0;
1380 release_dc_ptr( dc );
1381 if (bDesktopDC) DeleteDC( hdc );
1382 if (ret && bits) *bits = dib->dsBm.bmBits;
1383 return ret;
1385 error:
1386 if (bDesktopDC) DeleteDC( hdc );
1387 if (section) UnmapViewOfFile( mapBits );
1388 else if (!offset) VirtualFree( dib->dsBm.bmBits, 0, MEM_RELEASE );
1389 HeapFree( GetProcessHeap(), 0, dib );
1390 return 0;