gdi32: Optimise StretchBlt for the case where no stretching is being done and the...
[wine/winequartzdrv.git] / dlls / gdi32 / dib.c
blobd53b8f2e1735081a029f554765416fca060fe93d
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 0 for COREHEADER, 1 for INFOHEADER, -1 for error.
154 static int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
155 LONG *height, WORD *planes, WORD *bpp, DWORD *compr, DWORD *size )
157 if (header->biSize == sizeof(BITMAPCOREHEADER))
159 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)header;
160 *width = core->bcWidth;
161 *height = core->bcHeight;
162 *planes = core->bcPlanes;
163 *bpp = core->bcBitCount;
164 *compr = 0;
165 *size = 0;
166 return 0;
168 if (header->biSize >= sizeof(BITMAPINFOHEADER)) /* assume BITMAPINFOHEADER */
170 *width = header->biWidth;
171 *height = header->biHeight;
172 *planes = header->biPlanes;
173 *bpp = header->biBitCount;
174 *compr = header->biCompression;
175 *size = header->biSizeImage;
176 return 1;
178 ERR("(%d): unknown/wrong size for header\n", header->biSize );
179 return -1;
183 /***********************************************************************
184 * StretchDIBits (GDI32.@)
186 INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst,
187 INT heightDst, INT xSrc, INT ySrc, INT widthSrc,
188 INT heightSrc, const void *bits,
189 const BITMAPINFO *info, UINT wUsage, DWORD dwRop )
191 DC *dc;
193 if (!bits || !info)
194 return 0;
196 if (!(dc = get_dc_ptr( hdc ))) return FALSE;
198 if(dc->funcs->pStretchDIBits)
200 update_dc( dc );
201 heightSrc = 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 heightSrc = 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 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 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 heightSrc;
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 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/bitmaps_87eb.asp
576 INT WINAPI GetDIBits(
577 HDC hdc, /* [in] Handle to device context */
578 HBITMAP hbitmap, /* [in] Handle to bitmap */
579 UINT startscan, /* [in] First scan line to set in dest bitmap */
580 UINT lines, /* [in] Number of scan lines to copy */
581 LPVOID bits, /* [out] Address of array for bitmap bits */
582 BITMAPINFO * info, /* [out] Address of structure with bitmap data */
583 UINT coloruse) /* [in] RGB or palette index */
585 DC * dc;
586 BITMAPOBJ * bmp;
587 int i;
588 int bitmap_type;
589 BOOL core_header;
590 LONG width;
591 LONG height;
592 WORD planes, bpp;
593 DWORD compr, size;
594 void* colorPtr;
595 RGBTRIPLE* rgbTriples;
596 RGBQUAD* rgbQuads;
598 if (!info) return 0;
600 bitmap_type = DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size);
601 if (bitmap_type == -1)
603 ERR("Invalid bitmap format\n");
604 return 0;
606 core_header = (bitmap_type == 0);
607 if (!(dc = get_dc_ptr( hdc )))
609 SetLastError( ERROR_INVALID_PARAMETER );
610 return 0;
612 update_dc( dc );
613 if (!(bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
615 release_dc_ptr( dc );
616 return 0;
619 colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
620 rgbTriples = (RGBTRIPLE *) colorPtr;
621 rgbQuads = (RGBQUAD *) colorPtr;
623 /* Transfer color info */
625 if (bpp <= 8 && bpp > 0)
627 if (!core_header) info->bmiHeader.biClrUsed = 0;
629 /* If the bitmap object already has a dib section at the
630 same color depth then get the color map from it */
631 if (bmp->dib && bmp->dib->dsBm.bmBitsPixel == bpp) {
632 if(coloruse == DIB_RGB_COLORS) {
633 unsigned int colors = min( bmp->nb_colors, 1 << bpp );
635 if (core_header)
637 /* Convert the color table (RGBQUAD to RGBTRIPLE) */
638 RGBTRIPLE* index = rgbTriples;
640 for (i=0; i < colors; i++, index++)
642 index->rgbtRed = bmp->color_table[i].rgbRed;
643 index->rgbtGreen = bmp->color_table[i].rgbGreen;
644 index->rgbtBlue = bmp->color_table[i].rgbBlue;
647 else
649 if (colors != 1 << bpp) info->bmiHeader.biClrUsed = colors;
650 memcpy(colorPtr, bmp->color_table, colors * sizeof(RGBQUAD));
653 else {
654 WORD *index = colorPtr;
655 for(i = 0; i < 1 << info->bmiHeader.biBitCount; i++, index++)
656 *index = i;
659 else {
660 if(bpp >= bmp->bitmap.bmBitsPixel) {
661 /* Generate the color map from the selected palette */
662 PALETTEENTRY palEntry[256];
664 memset( palEntry, 0, sizeof(palEntry) );
665 if (!GetPaletteEntries( dc->hPalette, 0, 1 << bmp->bitmap.bmBitsPixel, palEntry ))
667 release_dc_ptr( dc );
668 GDI_ReleaseObj( hbitmap );
669 return 0;
671 for (i = 0; i < (1 << bmp->bitmap.bmBitsPixel); i++) {
672 if (coloruse == DIB_RGB_COLORS) {
673 if (core_header)
675 rgbTriples[i].rgbtRed = palEntry[i].peRed;
676 rgbTriples[i].rgbtGreen = palEntry[i].peGreen;
677 rgbTriples[i].rgbtBlue = palEntry[i].peBlue;
679 else
681 rgbQuads[i].rgbRed = palEntry[i].peRed;
682 rgbQuads[i].rgbGreen = palEntry[i].peGreen;
683 rgbQuads[i].rgbBlue = palEntry[i].peBlue;
684 rgbQuads[i].rgbReserved = 0;
687 else ((WORD *)colorPtr)[i] = (WORD)i;
689 } else {
690 switch (bpp) {
691 case 1:
692 if (core_header)
694 rgbTriples[0].rgbtRed = rgbTriples[0].rgbtGreen =
695 rgbTriples[0].rgbtBlue = 0;
696 rgbTriples[1].rgbtRed = rgbTriples[1].rgbtGreen =
697 rgbTriples[1].rgbtBlue = 0xff;
699 else
701 rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen =
702 rgbQuads[0].rgbBlue = 0;
703 rgbQuads[0].rgbReserved = 0;
704 rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen =
705 rgbQuads[1].rgbBlue = 0xff;
706 rgbQuads[1].rgbReserved = 0;
708 break;
710 case 4:
711 if (core_header)
712 memcpy(colorPtr, EGAColorsTriples, sizeof(EGAColorsTriples));
713 else
714 memcpy(colorPtr, EGAColorsQuads, sizeof(EGAColorsQuads));
716 break;
718 case 8:
720 if (core_header)
722 INT r, g, b;
723 RGBTRIPLE *color;
725 memcpy(rgbTriples, DefLogPaletteTriples,
726 10 * sizeof(RGBTRIPLE));
727 memcpy(rgbTriples + 246, DefLogPaletteTriples + 10,
728 10 * sizeof(RGBTRIPLE));
729 color = rgbTriples + 10;
730 for(r = 0; r <= 5; r++) /* FIXME */
731 for(g = 0; g <= 5; g++)
732 for(b = 0; b <= 5; b++) {
733 color->rgbtRed = (r * 0xff) / 5;
734 color->rgbtGreen = (g * 0xff) / 5;
735 color->rgbtBlue = (b * 0xff) / 5;
736 color++;
739 else
741 INT r, g, b;
742 RGBQUAD *color;
744 memcpy(rgbQuads, DefLogPaletteQuads,
745 10 * sizeof(RGBQUAD));
746 memcpy(rgbQuads + 246, DefLogPaletteQuads + 10,
747 10 * sizeof(RGBQUAD));
748 color = rgbQuads + 10;
749 for(r = 0; r <= 5; r++) /* FIXME */
750 for(g = 0; g <= 5; g++)
751 for(b = 0; b <= 5; b++) {
752 color->rgbRed = (r * 0xff) / 5;
753 color->rgbGreen = (g * 0xff) / 5;
754 color->rgbBlue = (b * 0xff) / 5;
755 color->rgbReserved = 0;
756 color++;
765 if (bits && lines)
767 /* If the bitmap object already have a dib section that contains image data, get the bits from it */
768 if(bmp->dib && bmp->dib->dsBm.bmBitsPixel >= 15 && bpp >= 15)
770 /*FIXME: Only RGB dibs supported for now */
771 unsigned int srcwidth = bmp->dib->dsBm.bmWidth, srcwidthb = bmp->dib->dsBm.bmWidthBytes;
772 unsigned int dstwidth = width;
773 int dstwidthb = DIB_GetDIBWidthBytes( width, bpp );
774 LPBYTE dbits = bits, sbits = (LPBYTE) bmp->dib->dsBm.bmBits + (startscan * srcwidthb);
775 unsigned int x, y, width, widthb;
777 if ((height < 0) ^ (bmp->dib->dsBmih.biHeight < 0))
779 dbits = (LPBYTE)bits + (dstwidthb * (lines-1));
780 dstwidthb = -dstwidthb;
783 switch( bpp ) {
785 case 15:
786 case 16: /* 16 bpp dstDIB */
788 LPWORD dstbits = (LPWORD)dbits;
789 WORD rmask = 0x7c00, gmask= 0x03e0, bmask = 0x001f;
791 /* FIXME: BI_BITFIELDS not supported yet */
793 switch(bmp->dib->dsBm.bmBitsPixel) {
795 case 16: /* 16 bpp srcDIB -> 16 bpp dstDIB */
797 widthb = min(srcwidthb, abs(dstwidthb));
798 /* FIXME: BI_BITFIELDS not supported yet */
799 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
800 memcpy(dbits, sbits, widthb);
802 break;
804 case 24: /* 24 bpp srcDIB -> 16 bpp dstDIB */
806 LPBYTE srcbits = sbits;
808 width = min(srcwidth, dstwidth);
809 for( y = 0; y < lines; y++) {
810 for( x = 0; x < width; x++, srcbits += 3)
811 *dstbits++ = ((srcbits[0] >> 3) & bmask) |
812 (((WORD)srcbits[1] << 2) & gmask) |
813 (((WORD)srcbits[2] << 7) & rmask);
815 dstbits = (LPWORD)(dbits+=dstwidthb);
816 srcbits = (sbits += srcwidthb);
819 break;
821 case 32: /* 32 bpp srcDIB -> 16 bpp dstDIB */
823 LPDWORD srcbits = (LPDWORD)sbits;
824 DWORD val;
826 width = min(srcwidth, dstwidth);
827 for( y = 0; y < lines; y++) {
828 for( x = 0; x < width; x++ ) {
829 val = *srcbits++;
830 *dstbits++ = (WORD)(((val >> 3) & bmask) | ((val >> 6) & gmask) |
831 ((val >> 9) & rmask));
833 dstbits = (LPWORD)(dbits+=dstwidthb);
834 srcbits = (LPDWORD)(sbits+=srcwidthb);
837 break;
839 default: /* ? bit bmp -> 16 bit DIB */
840 FIXME("15/16 bit DIB %d bit bitmap\n",
841 bmp->bitmap.bmBitsPixel);
842 break;
845 break;
847 case 24: /* 24 bpp dstDIB */
849 LPBYTE dstbits = dbits;
851 switch(bmp->dib->dsBm.bmBitsPixel) {
853 case 16: /* 16 bpp srcDIB -> 24 bpp dstDIB */
855 LPWORD srcbits = (LPWORD)sbits;
856 WORD val;
858 width = min(srcwidth, dstwidth);
859 /* FIXME: BI_BITFIELDS not supported yet */
860 for( y = 0; y < lines; y++) {
861 for( x = 0; x < width; x++ ) {
862 val = *srcbits++;
863 *dstbits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07));
864 *dstbits++ = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07));
865 *dstbits++ = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07));
867 dstbits = dbits+=dstwidthb;
868 srcbits = (LPWORD)(sbits+=srcwidthb);
871 break;
873 case 24: /* 24 bpp srcDIB -> 24 bpp dstDIB */
875 widthb = min(srcwidthb, abs(dstwidthb));
876 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
877 memcpy(dbits, sbits, widthb);
879 break;
881 case 32: /* 32 bpp srcDIB -> 24 bpp dstDIB */
883 LPBYTE srcbits = sbits;
885 width = min(srcwidth, dstwidth);
886 for( y = 0; y < lines; y++) {
887 for( x = 0; x < width; x++, srcbits++ ) {
888 *dstbits++ = *srcbits++;
889 *dstbits++ = *srcbits++;
890 *dstbits++ = *srcbits++;
892 dstbits = dbits+=dstwidthb;
893 srcbits = sbits+=srcwidthb;
896 break;
898 default: /* ? bit bmp -> 24 bit DIB */
899 FIXME("24 bit DIB %d bit bitmap\n",
900 bmp->bitmap.bmBitsPixel);
901 break;
904 break;
906 case 32: /* 32 bpp dstDIB */
908 LPDWORD dstbits = (LPDWORD)dbits;
910 /* FIXME: BI_BITFIELDS not supported yet */
912 switch(bmp->dib->dsBm.bmBitsPixel) {
913 case 16: /* 16 bpp srcDIB -> 32 bpp dstDIB */
915 LPWORD srcbits = (LPWORD)sbits;
916 DWORD val;
918 width = min(srcwidth, dstwidth);
919 /* FIXME: BI_BITFIELDS not supported yet */
920 for( y = 0; y < lines; y++) {
921 for( x = 0; x < width; x++ ) {
922 val = (DWORD)*srcbits++;
923 *dstbits++ = ((val << 3) & 0xf8) | ((val >> 2) & 0x07) |
924 ((val << 6) & 0xf800) | ((val << 1) & 0x0700) |
925 ((val << 9) & 0xf80000) | ((val << 4) & 0x070000);
927 dstbits=(LPDWORD)(dbits+=dstwidthb);
928 srcbits=(LPWORD)(sbits+=srcwidthb);
931 break;
933 case 24: /* 24 bpp srcDIB -> 32 bpp dstDIB */
935 LPBYTE srcbits = sbits;
937 width = min(srcwidth, dstwidth);
938 for( y = 0; y < lines; y++) {
939 for( x = 0; x < width; x++, srcbits+=3 )
940 *dstbits++ = srcbits[0] |
941 (srcbits[1] << 8) |
942 (srcbits[2] << 16);
943 dstbits=(LPDWORD)(dbits+=dstwidthb);
944 srcbits=(sbits+=srcwidthb);
947 break;
949 case 32: /* 32 bpp srcDIB -> 32 bpp dstDIB */
951 widthb = min(srcwidthb, abs(dstwidthb));
952 /* FIXME: BI_BITFIELDS not supported yet */
953 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb) {
954 memcpy(dbits, sbits, widthb);
957 break;
959 default: /* ? bit bmp -> 32 bit DIB */
960 FIXME("32 bit DIB %d bit bitmap\n",
961 bmp->bitmap.bmBitsPixel);
962 break;
965 break;
967 default: /* ? bit DIB */
968 FIXME("Unsupported DIB depth %d\n", info->bmiHeader.biBitCount);
969 break;
972 /* Otherwise, get bits from the XImage */
973 else
975 if (!bmp->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) lines = 0;
976 else
978 if (bmp->funcs && bmp->funcs->pGetDIBits)
979 lines = bmp->funcs->pGetDIBits( dc->physDev, hbitmap, startscan,
980 lines, bits, info, coloruse );
981 else
982 lines = 0; /* FIXME: should copy from bmp->bitmap.bmBits */
986 else
988 /* fill in struct members */
990 if (bpp == 0)
992 if (core_header)
994 BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) info;
995 coreheader->bcWidth = bmp->bitmap.bmWidth;
996 coreheader->bcHeight = bmp->bitmap.bmHeight;
997 coreheader->bcPlanes = 1;
998 coreheader->bcBitCount = bmp->bitmap.bmBitsPixel;
1000 else
1002 info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
1003 info->bmiHeader.biHeight = bmp->bitmap.bmHeight;
1004 info->bmiHeader.biPlanes = 1;
1005 info->bmiHeader.biSizeImage =
1006 DIB_GetDIBImageBytes( bmp->bitmap.bmWidth,
1007 bmp->bitmap.bmHeight,
1008 bmp->bitmap.bmBitsPixel );
1009 switch(bmp->bitmap.bmBitsPixel)
1011 case 15:
1012 info->bmiHeader.biBitCount = 16;
1013 info->bmiHeader.biCompression = BI_RGB;
1014 break;
1016 case 16:
1017 if (bits)
1019 /* Add color only when bits is given, as per MSDN */
1020 ((PDWORD)info->bmiColors)[0] = 0xf800;
1021 ((PDWORD)info->bmiColors)[1] = 0x07e0;
1022 ((PDWORD)info->bmiColors)[2] = 0x001f;
1024 info->bmiHeader.biBitCount = 16;
1025 info->bmiHeader.biCompression = BI_BITFIELDS;
1026 break;
1028 default:
1029 info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
1030 info->bmiHeader.biCompression = BI_RGB;
1031 break;
1033 info->bmiHeader.biXPelsPerMeter = 0;
1034 info->bmiHeader.biYPelsPerMeter = 0;
1035 info->bmiHeader.biClrUsed = 0;
1036 info->bmiHeader.biClrImportant = 0;
1038 /* Windows 2000 doesn't touch the additional struct members if
1039 it's a BITMAPV4HEADER or a BITMAPV5HEADER */
1041 lines = abs(bmp->bitmap.bmHeight);
1043 else
1045 /* The knowledge base article Q81498 ("DIBs and Their Uses") states that
1046 if bits == NULL and bpp != 0, only biSizeImage and the color table are
1047 filled in. */
1048 if (!core_header)
1050 /* FIXME: biSizeImage should be calculated according to the selected
1051 compression algorithm if biCompression != BI_RGB */
1052 info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes( width, height, bpp );
1054 lines = abs(height);
1058 if (!core_header)
1060 TRACE("biSizeImage = %d, ", info->bmiHeader.biSizeImage);
1062 TRACE("biWidth = %d, biHeight = %d\n", width, height);
1064 release_dc_ptr( dc );
1065 GDI_ReleaseObj( hbitmap );
1066 return lines;
1070 /***********************************************************************
1071 * CreateDIBitmap (GDI32.@)
1073 * Creates a DDB (device dependent bitmap) from a DIB.
1074 * The DDB will have the same color depth as the reference DC.
1076 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
1077 DWORD init, LPCVOID bits, const BITMAPINFO *data,
1078 UINT coloruse )
1080 HBITMAP handle;
1081 LONG width;
1082 LONG height;
1083 WORD planes, bpp;
1084 DWORD compr, size;
1085 DC *dc;
1087 if (DIB_GetBitmapInfo( header, &width, &height, &planes, &bpp, &compr, &size ) == -1) return 0;
1089 if (width < 0)
1091 TRACE("Bitmap has a negative width\n");
1092 return 0;
1095 /* Top-down DIBs have a negative height */
1096 if (height < 0) height = -height;
1098 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1099 hdc, header, init, bits, data, coloruse, width, height, bpp, compr);
1101 if (hdc == NULL)
1102 handle = CreateBitmap( width, height, 1, 1, NULL );
1103 else
1104 handle = CreateCompatibleBitmap( hdc, width, height );
1106 if (handle)
1108 if (init == CBM_INIT) SetDIBits( hdc, handle, 0, height, bits, data, coloruse );
1110 else if (hdc && ((dc = get_dc_ptr( hdc )) != NULL) )
1112 if (!BITMAP_SetOwnerDC( handle, dc ))
1114 DeleteObject( handle );
1115 handle = 0;
1117 release_dc_ptr( dc );
1121 return handle;
1124 /***********************************************************************
1125 * CreateDIBSection (GDI.489)
1127 HBITMAP16 WINAPI CreateDIBSection16 (HDC16 hdc, const BITMAPINFO *bmi, UINT16 usage,
1128 SEGPTR *bits16, HANDLE section, DWORD offset)
1130 LPVOID bits32;
1131 HBITMAP hbitmap;
1133 hbitmap = CreateDIBSection( HDC_32(hdc), bmi, usage, &bits32, section, offset );
1134 if (hbitmap)
1136 BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr(hbitmap, BITMAP_MAGIC);
1137 if (bmp && bmp->dib && bits32)
1139 const BITMAPINFOHEADER *bi = &bmi->bmiHeader;
1140 LONG width, height;
1141 WORD planes, bpp;
1142 DWORD compr, size;
1143 INT width_bytes;
1144 WORD count, sel;
1145 int i;
1147 DIB_GetBitmapInfo(bi, &width, &height, &planes, &bpp, &compr, &size);
1149 height = height >= 0 ? height : -height;
1150 width_bytes = DIB_GetDIBWidthBytes(width, bpp);
1152 if (!size || (compr != BI_RLE4 && compr != BI_RLE8)) size = width_bytes * height;
1154 /* calculate number of sel's needed for size with 64K steps */
1155 count = (size + 0xffff) / 0x10000;
1156 sel = AllocSelectorArray16(count);
1158 for (i = 0; i < count; i++)
1160 SetSelectorBase(sel + (i << __AHSHIFT), (DWORD)bits32 + i * 0x10000);
1161 SetSelectorLimit16(sel + (i << __AHSHIFT), size - 1); /* yep, limit is correct */
1162 size -= 0x10000;
1164 bmp->segptr_bits = MAKESEGPTR( sel, 0 );
1165 if (bits16) *bits16 = bmp->segptr_bits;
1167 if (bmp) GDI_ReleaseObj( hbitmap );
1169 return HBITMAP_16(hbitmap);
1172 /* Copy/synthesize RGB palette from BITMAPINFO. Ripped from dlls/winex11.drv/dib.c */
1173 static void DIB_CopyColorTable( DC *dc, BITMAPOBJ *bmp, WORD coloruse, const BITMAPINFO *info )
1175 RGBQUAD *colorTable;
1176 unsigned int colors;
1177 int i;
1178 BOOL core_info = info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER);
1180 if (core_info)
1182 colors = 1 << ((const BITMAPCOREINFO*) info)->bmciHeader.bcBitCount;
1184 else
1186 colors = info->bmiHeader.biClrUsed;
1187 if (!colors) colors = 1 << info->bmiHeader.biBitCount;
1190 if (colors > 256) {
1191 ERR("called with >256 colors!\n");
1192 return;
1195 if (!(colorTable = HeapAlloc(GetProcessHeap(), 0, colors * sizeof(RGBQUAD) ))) return;
1197 if(coloruse == DIB_RGB_COLORS)
1199 if (core_info)
1201 /* Convert RGBTRIPLEs to RGBQUADs */
1202 for (i=0; i < colors; i++)
1204 colorTable[i].rgbRed = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtRed;
1205 colorTable[i].rgbGreen = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtGreen;
1206 colorTable[i].rgbBlue = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtBlue;
1207 colorTable[i].rgbReserved = 0;
1210 else
1212 memcpy(colorTable, (const BYTE*) info + (WORD) info->bmiHeader.biSize, colors * sizeof(RGBQUAD));
1215 else
1217 PALETTEENTRY entries[256];
1218 const WORD *index = (const WORD*) ((const BYTE*) info + (WORD) info->bmiHeader.biSize);
1219 UINT count = GetPaletteEntries( dc->hPalette, 0, colors, entries );
1221 for (i = 0; i < colors; i++, index++)
1223 PALETTEENTRY *entry = &entries[*index % count];
1224 colorTable[i].rgbRed = entry->peRed;
1225 colorTable[i].rgbGreen = entry->peGreen;
1226 colorTable[i].rgbBlue = entry->peBlue;
1227 colorTable[i].rgbReserved = 0;
1230 bmp->color_table = colorTable;
1231 bmp->nb_colors = colors;
1234 /***********************************************************************
1235 * CreateDIBSection (GDI32.@)
1237 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
1238 VOID **bits, HANDLE section, DWORD offset)
1240 HBITMAP ret = 0;
1241 DC *dc;
1242 BOOL bDesktopDC = FALSE;
1243 DIBSECTION *dib;
1244 BITMAPOBJ *bmp;
1245 int bitmap_type;
1246 LONG width, height;
1247 WORD planes, bpp;
1248 DWORD compression, sizeImage;
1249 void *mapBits = NULL;
1251 if (((bitmap_type = DIB_GetBitmapInfo( &bmi->bmiHeader, &width, &height,
1252 &planes, &bpp, &compression, &sizeImage )) == -1))
1253 return 0;
1255 if (compression != BI_RGB && compression != BI_BITFIELDS)
1257 TRACE("can't create a compressed (%u) dibsection\n", compression);
1258 return 0;
1261 if (!(dib = HeapAlloc( GetProcessHeap(), 0, sizeof(*dib) ))) return 0;
1263 TRACE("format (%d,%d), planes %d, bpp %d, size %d, %s\n",
1264 width, height, planes, bpp, sizeImage, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1266 dib->dsBm.bmType = 0;
1267 dib->dsBm.bmWidth = width;
1268 dib->dsBm.bmHeight = height >= 0 ? height : -height;
1269 dib->dsBm.bmWidthBytes = DIB_GetDIBWidthBytes(width, bpp);
1270 dib->dsBm.bmPlanes = planes;
1271 dib->dsBm.bmBitsPixel = bpp;
1272 dib->dsBm.bmBits = NULL;
1274 if (!bitmap_type) /* core header */
1276 /* convert the BITMAPCOREHEADER to a BITMAPINFOHEADER */
1277 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1278 dib->dsBmih.biWidth = width;
1279 dib->dsBmih.biHeight = height;
1280 dib->dsBmih.biPlanes = planes;
1281 dib->dsBmih.biBitCount = bpp;
1282 dib->dsBmih.biCompression = compression;
1283 dib->dsBmih.biXPelsPerMeter = 0;
1284 dib->dsBmih.biYPelsPerMeter = 0;
1285 dib->dsBmih.biClrUsed = 0;
1286 dib->dsBmih.biClrImportant = 0;
1288 else
1290 /* truncate extended bitmap headers (BITMAPV4HEADER etc.) */
1291 dib->dsBmih = bmi->bmiHeader;
1292 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1295 /* set number of entries in bmi.bmiColors table */
1296 if( bpp <= 8 )
1297 dib->dsBmih.biClrUsed = 1 << bpp;
1299 dib->dsBmih.biSizeImage = dib->dsBm.bmWidthBytes * dib->dsBm.bmHeight;
1301 /* set dsBitfields values */
1302 if (usage == DIB_PAL_COLORS || bpp <= 8)
1304 dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
1306 else switch( bpp )
1308 case 15:
1309 case 16:
1310 dib->dsBitfields[0] = (compression == BI_BITFIELDS) ? *(const DWORD *)bmi->bmiColors : 0x7c00;
1311 dib->dsBitfields[1] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 1) : 0x03e0;
1312 dib->dsBitfields[2] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 2) : 0x001f;
1313 break;
1314 case 24:
1315 case 32:
1316 dib->dsBitfields[0] = (compression == BI_BITFIELDS) ? *(const DWORD *)bmi->bmiColors : 0xff0000;
1317 dib->dsBitfields[1] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 1) : 0x00ff00;
1318 dib->dsBitfields[2] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 2) : 0x0000ff;
1319 break;
1322 /* get storage location for DIB bits */
1324 if (section)
1326 SYSTEM_INFO SystemInfo;
1327 DWORD mapOffset;
1328 INT mapSize;
1330 GetSystemInfo( &SystemInfo );
1331 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
1332 mapSize = dib->dsBmih.biSizeImage + (offset - mapOffset);
1333 mapBits = MapViewOfFile( section, FILE_MAP_ALL_ACCESS, 0, mapOffset, mapSize );
1334 if (mapBits) dib->dsBm.bmBits = (char *)mapBits + (offset - mapOffset);
1336 else
1338 offset = 0;
1339 dib->dsBm.bmBits = VirtualAlloc( NULL, dib->dsBmih.biSizeImage,
1340 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
1342 dib->dshSection = section;
1343 dib->dsOffset = offset;
1345 if (!dib->dsBm.bmBits)
1347 HeapFree( GetProcessHeap(), 0, dib );
1348 return 0;
1351 /* If the reference hdc is null, take the desktop dc */
1352 if (hdc == 0)
1354 hdc = CreateCompatibleDC(0);
1355 bDesktopDC = TRUE;
1358 if (!(dc = get_dc_ptr( hdc ))) goto error;
1360 /* create Device Dependent Bitmap and add DIB pointer */
1361 ret = CreateBitmap( dib->dsBm.bmWidth, dib->dsBm.bmHeight, 1,
1362 (bpp == 1) ? 1 : GetDeviceCaps(hdc, BITSPIXEL), NULL );
1364 if (ret && ((bmp = GDI_GetObjPtr(ret, BITMAP_MAGIC))))
1366 bmp->dib = dib;
1367 bmp->funcs = dc->funcs;
1368 /* create local copy of DIB palette */
1369 if (bpp <= 8) DIB_CopyColorTable( dc, bmp, usage, bmi );
1370 GDI_ReleaseObj( ret );
1372 if (dc->funcs->pCreateDIBSection)
1374 if (!dc->funcs->pCreateDIBSection(dc->physDev, ret, bmi, usage))
1376 DeleteObject( ret );
1377 ret = 0;
1382 release_dc_ptr( dc );
1383 if (bDesktopDC) DeleteDC( hdc );
1384 if (ret && bits) *bits = dib->dsBm.bmBits;
1385 return ret;
1387 error:
1388 if (bDesktopDC) DeleteDC( hdc );
1389 if (section) UnmapViewOfFile( mapBits );
1390 else if (!offset) VirtualFree( dib->dsBm.bmBits, 0, MEM_RELEASE );
1391 HeapFree( GetProcessHeap(), 0, dib );
1392 return 0;