shell32: Fix a comment typo.
[wine/wine-gecko.git] / dlls / gdi32 / dib.c
blobce5ab8b989e445cf4b62795d79cbaaa7b8acb0f9
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 * bitmap_info_size
122 * Return the size of the bitmap info structure including color table.
124 int bitmap_info_size( const BITMAPINFO * info, WORD coloruse )
126 unsigned int colors, size, masks = 0;
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 if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3;
142 size = max( info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD) );
143 return size + colors * ((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 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;
192 INT ret;
194 if (!bits || !info)
195 return 0;
197 if (!(dc = get_dc_ptr( hdc ))) return 0;
199 if(dc->funcs->pStretchDIBits)
201 update_dc( dc );
202 ret = dc->funcs->pStretchDIBits(dc->physDev, xDst, yDst, widthDst,
203 heightDst, xSrc, ySrc, widthSrc,
204 heightSrc, bits, info, wUsage, dwRop);
205 release_dc_ptr( dc );
207 else /* use StretchBlt */
209 LONG height;
210 LONG width;
211 WORD planes, bpp;
212 DWORD compr, size;
213 HBITMAP hBitmap;
214 BOOL fastpath = FALSE;
216 release_dc_ptr( dc );
218 if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size ) == -1)
220 ERR("Invalid bitmap\n");
221 return 0;
224 if (width < 0)
226 ERR("Bitmap has a negative width\n");
227 return 0;
230 hBitmap = GetCurrentObject(hdc, OBJ_BITMAP);
232 if (xDst == 0 && yDst == 0 && xSrc == 0 && ySrc == 0 &&
233 widthDst == widthSrc && heightDst == heightSrc &&
234 info->bmiHeader.biCompression == BI_RGB &&
235 dwRop == SRCCOPY)
237 BITMAPOBJ *bmp;
238 if ((bmp = GDI_GetObjPtr( hBitmap, OBJ_BITMAP )))
240 if (bmp->bitmap.bmBitsPixel == bpp &&
241 bmp->bitmap.bmWidth == widthSrc &&
242 bmp->bitmap.bmHeight == heightSrc &&
243 bmp->bitmap.bmPlanes == planes)
244 fastpath = TRUE;
245 GDI_ReleaseObj( hBitmap );
249 if (fastpath)
251 /* fast path */
252 TRACE("using fast path\n");
253 ret = SetDIBits( hdc, hBitmap, 0, height, bits, info, wUsage);
255 else
257 /* slow path - need to use StretchBlt */
258 HBITMAP hOldBitmap;
259 HPALETTE hpal = NULL;
260 HDC hdcMem;
262 hdcMem = CreateCompatibleDC( hdc );
263 hBitmap = CreateCompatibleBitmap(hdc, width, height);
264 hOldBitmap = SelectObject( hdcMem, hBitmap );
265 if(wUsage == DIB_PAL_COLORS)
267 hpal = GetCurrentObject(hdc, OBJ_PAL);
268 hpal = SelectPalette(hdcMem, hpal, FALSE);
271 if (info->bmiHeader.biCompression == BI_RLE4 ||
272 info->bmiHeader.biCompression == BI_RLE8) {
274 /* when RLE compression is used, there may be some gaps (ie the DIB doesn't
275 * contain all the rectangle described in bmiHeader, but only part of it.
276 * This mean that those undescribed pixels must be left untouched.
277 * So, we first copy on a memory bitmap the current content of the
278 * destination rectangle, blit the DIB bits on top of it - hence leaving
279 * the gaps untouched -, and blitting the rectangle back.
280 * This insure that gaps are untouched on the destination rectangle
281 * Not doing so leads to trashed images (the gaps contain what was on the
282 * memory bitmap => generally black or garbage)
283 * Unfortunately, RLE DIBs without gaps will be slowed down. But this is
284 * another speed vs correctness issue. Anyway, if speed is needed, then the
285 * pStretchDIBits function shall be implemented.
286 * ericP (2000/09/09)
289 /* copy existing bitmap from destination dc */
290 StretchBlt( hdcMem, xSrc, abs(height) - heightSrc - ySrc,
291 widthSrc, heightSrc, hdc, xDst, yDst, widthDst, heightDst,
292 dwRop );
295 ret = SetDIBits(hdcMem, hBitmap, 0, height, bits, info, wUsage);
297 /* Origin for DIBitmap may be bottom left (positive biHeight) or top
298 left (negative biHeight) */
299 if (ret) StretchBlt( hdc, xDst, yDst, widthDst, heightDst,
300 hdcMem, xSrc, abs(height) - heightSrc - ySrc,
301 widthSrc, heightSrc, dwRop );
302 if(hpal)
303 SelectPalette(hdcMem, hpal, FALSE);
304 SelectObject( hdcMem, hOldBitmap );
305 DeleteDC( hdcMem );
306 DeleteObject( hBitmap );
309 return ret;
313 /******************************************************************************
314 * SetDIBits [GDI32.@]
316 * Sets pixels in a bitmap using colors from DIB.
318 * PARAMS
319 * hdc [I] Handle to device context
320 * hbitmap [I] Handle to bitmap
321 * startscan [I] Starting scan line
322 * lines [I] Number of scan lines
323 * bits [I] Array of bitmap bits
324 * info [I] Address of structure with data
325 * coloruse [I] Type of color indexes to use
327 * RETURNS
328 * Success: Number of scan lines copied
329 * Failure: 0
331 INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
332 UINT lines, LPCVOID bits, const BITMAPINFO *info,
333 UINT coloruse )
335 DC *dc = get_dc_ptr( hdc );
336 BOOL delete_hdc = FALSE;
337 BITMAPOBJ *bitmap;
338 INT result = 0;
340 if (coloruse == DIB_RGB_COLORS && !dc)
342 hdc = CreateCompatibleDC(0);
343 dc = get_dc_ptr( hdc );
344 delete_hdc = TRUE;
347 if (!dc) return 0;
349 update_dc( dc );
351 if (!(bitmap = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
353 release_dc_ptr( dc );
354 if (delete_hdc) DeleteDC(hdc);
355 return 0;
358 if (!bitmap->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) goto done;
360 result = lines;
361 if (bitmap->funcs)
363 if (bitmap->funcs != dc->funcs)
364 ERR( "not supported: DDB bitmap %p not belonging to device %p\n", hbitmap, hdc );
365 else if (dc->funcs->pSetDIBits)
366 result = dc->funcs->pSetDIBits( dc->physDev, hbitmap, startscan, lines,
367 bits, info, coloruse );
370 done:
371 GDI_ReleaseObj( hbitmap );
372 release_dc_ptr( dc );
373 if (delete_hdc) DeleteDC(hdc);
374 return result;
378 /***********************************************************************
379 * SetDIBitsToDevice (GDI32.@)
381 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
382 DWORD cy, INT xSrc, INT ySrc, UINT startscan,
383 UINT lines, LPCVOID bits, const BITMAPINFO *info,
384 UINT coloruse )
386 INT ret;
387 DC *dc;
389 if (!bits) return 0;
391 if (!(dc = get_dc_ptr( hdc ))) return 0;
393 if(dc->funcs->pSetDIBitsToDevice)
395 update_dc( dc );
396 ret = dc->funcs->pSetDIBitsToDevice( dc->physDev, xDest, yDest, cx, cy, xSrc,
397 ySrc, startscan, lines, bits,
398 info, coloruse );
400 else {
401 FIXME("unimplemented on hdc %p\n", hdc);
402 ret = 0;
405 release_dc_ptr( dc );
406 return ret;
409 /***********************************************************************
410 * SetDIBColorTable (GDI32.@)
412 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, CONST RGBQUAD *colors )
414 DC * dc;
415 UINT result = 0;
416 BITMAPOBJ * bitmap;
418 if (!(dc = get_dc_ptr( hdc ))) return 0;
420 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
422 /* Check if currently selected bitmap is a DIB */
423 if (bitmap->color_table)
425 if (startpos < bitmap->nb_colors)
427 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
428 memcpy(bitmap->color_table + startpos, colors, entries * sizeof(RGBQUAD));
429 result = entries;
432 GDI_ReleaseObj( dc->hBitmap );
435 if (dc->funcs->pSetDIBColorTable)
436 dc->funcs->pSetDIBColorTable(dc->physDev, startpos, entries, colors);
438 release_dc_ptr( dc );
439 return result;
443 /***********************************************************************
444 * GetDIBColorTable (GDI32.@)
446 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
448 DC * dc;
449 UINT result = 0;
451 if (!(dc = get_dc_ptr( hdc ))) return 0;
453 if (dc->funcs->pGetDIBColorTable)
454 result = dc->funcs->pGetDIBColorTable(dc->physDev, startpos, entries, colors);
455 else
457 BITMAPOBJ *bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP );
458 if (bitmap)
460 /* Check if currently selected bitmap is a DIB */
461 if (bitmap->color_table)
463 if (startpos < bitmap->nb_colors)
465 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
466 memcpy(colors, bitmap->color_table + startpos, entries * sizeof(RGBQUAD));
467 result = entries;
470 GDI_ReleaseObj( dc->hBitmap );
473 release_dc_ptr( dc );
474 return result;
477 /* FIXME the following two structs should be combined with __sysPalTemplate in
478 objects/color.c - this should happen after de-X11-ing both of these
479 files.
480 NB. RGBQUAD and PALETTEENTRY have different orderings of red, green
481 and blue - sigh */
483 static const RGBQUAD EGAColorsQuads[16] = {
484 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
485 { 0x00, 0x00, 0x00, 0x00 },
486 { 0x00, 0x00, 0x80, 0x00 },
487 { 0x00, 0x80, 0x00, 0x00 },
488 { 0x00, 0x80, 0x80, 0x00 },
489 { 0x80, 0x00, 0x00, 0x00 },
490 { 0x80, 0x00, 0x80, 0x00 },
491 { 0x80, 0x80, 0x00, 0x00 },
492 { 0x80, 0x80, 0x80, 0x00 },
493 { 0xc0, 0xc0, 0xc0, 0x00 },
494 { 0x00, 0x00, 0xff, 0x00 },
495 { 0x00, 0xff, 0x00, 0x00 },
496 { 0x00, 0xff, 0xff, 0x00 },
497 { 0xff, 0x00, 0x00, 0x00 },
498 { 0xff, 0x00, 0xff, 0x00 },
499 { 0xff, 0xff, 0x00, 0x00 },
500 { 0xff, 0xff, 0xff, 0x00 }
503 static const RGBTRIPLE EGAColorsTriples[16] = {
504 /* rgbBlue, rgbGreen, rgbRed */
505 { 0x00, 0x00, 0x00 },
506 { 0x00, 0x00, 0x80 },
507 { 0x00, 0x80, 0x00 },
508 { 0x00, 0x80, 0x80 },
509 { 0x80, 0x00, 0x00 },
510 { 0x80, 0x00, 0x80 },
511 { 0x80, 0x80, 0x00 },
512 { 0x80, 0x80, 0x80 },
513 { 0xc0, 0xc0, 0xc0 },
514 { 0x00, 0x00, 0xff },
515 { 0x00, 0xff, 0x00 },
516 { 0x00, 0xff, 0xff },
517 { 0xff, 0x00, 0x00 } ,
518 { 0xff, 0x00, 0xff },
519 { 0xff, 0xff, 0x00 },
520 { 0xff, 0xff, 0xff }
523 static const RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
524 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
525 { 0x00, 0x00, 0x00, 0x00 },
526 { 0x00, 0x00, 0x80, 0x00 },
527 { 0x00, 0x80, 0x00, 0x00 },
528 { 0x00, 0x80, 0x80, 0x00 },
529 { 0x80, 0x00, 0x00, 0x00 },
530 { 0x80, 0x00, 0x80, 0x00 },
531 { 0x80, 0x80, 0x00, 0x00 },
532 { 0xc0, 0xc0, 0xc0, 0x00 },
533 { 0xc0, 0xdc, 0xc0, 0x00 },
534 { 0xf0, 0xca, 0xa6, 0x00 },
535 { 0xf0, 0xfb, 0xff, 0x00 },
536 { 0xa4, 0xa0, 0xa0, 0x00 },
537 { 0x80, 0x80, 0x80, 0x00 },
538 { 0x00, 0x00, 0xf0, 0x00 },
539 { 0x00, 0xff, 0x00, 0x00 },
540 { 0x00, 0xff, 0xff, 0x00 },
541 { 0xff, 0x00, 0x00, 0x00 },
542 { 0xff, 0x00, 0xff, 0x00 },
543 { 0xff, 0xff, 0x00, 0x00 },
544 { 0xff, 0xff, 0xff, 0x00 }
547 static const RGBTRIPLE DefLogPaletteTriples[20] = { /* Copy of Default Logical Palette */
548 /* rgbBlue, rgbGreen, rgbRed */
549 { 0x00, 0x00, 0x00 },
550 { 0x00, 0x00, 0x80 },
551 { 0x00, 0x80, 0x00 },
552 { 0x00, 0x80, 0x80 },
553 { 0x80, 0x00, 0x00 },
554 { 0x80, 0x00, 0x80 },
555 { 0x80, 0x80, 0x00 },
556 { 0xc0, 0xc0, 0xc0 },
557 { 0xc0, 0xdc, 0xc0 },
558 { 0xf0, 0xca, 0xa6 },
559 { 0xf0, 0xfb, 0xff },
560 { 0xa4, 0xa0, 0xa0 },
561 { 0x80, 0x80, 0x80 },
562 { 0x00, 0x00, 0xf0 },
563 { 0x00, 0xff, 0x00 },
564 { 0x00, 0xff, 0xff },
565 { 0xff, 0x00, 0x00 },
566 { 0xff, 0x00, 0xff },
567 { 0xff, 0xff, 0x00 },
568 { 0xff, 0xff, 0xff}
572 /******************************************************************************
573 * GetDIBits [GDI32.@]
575 * Retrieves bits of bitmap and copies to buffer.
577 * RETURNS
578 * Success: Number of scan lines copied from bitmap
579 * Failure: 0
581 INT WINAPI GetDIBits(
582 HDC hdc, /* [in] Handle to device context */
583 HBITMAP hbitmap, /* [in] Handle to bitmap */
584 UINT startscan, /* [in] First scan line to set in dest bitmap */
585 UINT lines, /* [in] Number of scan lines to copy */
586 LPVOID bits, /* [out] Address of array for bitmap bits */
587 BITMAPINFO * info, /* [out] Address of structure with bitmap data */
588 UINT coloruse) /* [in] RGB or palette index */
590 DC * dc;
591 BITMAPOBJ * bmp;
592 int i;
593 int bitmap_type;
594 BOOL core_header;
595 LONG width;
596 LONG height;
597 WORD planes, bpp;
598 DWORD compr, size;
599 void* colorPtr;
600 RGBTRIPLE* rgbTriples;
601 RGBQUAD* rgbQuads;
603 if (!info) return 0;
605 bitmap_type = DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size);
606 if (bitmap_type == -1)
608 ERR("Invalid bitmap format\n");
609 return 0;
611 core_header = (bitmap_type == 0);
612 if (!(dc = get_dc_ptr( hdc )))
614 SetLastError( ERROR_INVALID_PARAMETER );
615 return 0;
617 update_dc( dc );
618 if (!(bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
620 release_dc_ptr( dc );
621 return 0;
624 colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
625 rgbTriples = colorPtr;
626 rgbQuads = colorPtr;
628 /* Transfer color info */
630 switch (bpp)
632 case 0: /* query bitmap info only */
633 if (core_header)
635 BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) info;
636 coreheader->bcWidth = bmp->bitmap.bmWidth;
637 coreheader->bcHeight = bmp->bitmap.bmHeight;
638 coreheader->bcPlanes = 1;
639 coreheader->bcBitCount = bmp->bitmap.bmBitsPixel;
641 else
643 info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
644 info->bmiHeader.biHeight = bmp->bitmap.bmHeight;
645 info->bmiHeader.biPlanes = 1;
646 info->bmiHeader.biSizeImage =
647 DIB_GetDIBImageBytes( bmp->bitmap.bmWidth,
648 bmp->bitmap.bmHeight,
649 bmp->bitmap.bmBitsPixel );
650 if (bmp->dib)
652 info->bmiHeader.biBitCount = bmp->dib->dsBm.bmBitsPixel;
653 switch (bmp->dib->dsBm.bmBitsPixel)
655 case 16:
656 case 32:
657 info->bmiHeader.biCompression = BI_BITFIELDS;
658 break;
659 default:
660 info->bmiHeader.biCompression = BI_RGB;
661 break;
664 else
666 info->bmiHeader.biCompression = (bmp->bitmap.bmBitsPixel > 8) ? BI_BITFIELDS : BI_RGB;
667 info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
669 info->bmiHeader.biXPelsPerMeter = 0;
670 info->bmiHeader.biYPelsPerMeter = 0;
671 info->bmiHeader.biClrUsed = 0;
672 info->bmiHeader.biClrImportant = 0;
674 /* Windows 2000 doesn't touch the additional struct members if
675 it's a BITMAPV4HEADER or a BITMAPV5HEADER */
677 lines = abs(bmp->bitmap.bmHeight);
678 goto done;
680 case 1:
681 case 4:
682 case 8:
683 if (!core_header) info->bmiHeader.biClrUsed = 0;
685 /* If the bitmap object already has a dib section at the
686 same color depth then get the color map from it */
687 if (bmp->dib && bmp->dib->dsBm.bmBitsPixel == bpp) {
688 if(coloruse == DIB_RGB_COLORS) {
689 unsigned int colors = min( bmp->nb_colors, 1 << bpp );
691 if (core_header)
693 /* Convert the color table (RGBQUAD to RGBTRIPLE) */
694 RGBTRIPLE* index = rgbTriples;
696 for (i=0; i < colors; i++, index++)
698 index->rgbtRed = bmp->color_table[i].rgbRed;
699 index->rgbtGreen = bmp->color_table[i].rgbGreen;
700 index->rgbtBlue = bmp->color_table[i].rgbBlue;
703 else
705 if (colors != 1 << bpp) info->bmiHeader.biClrUsed = colors;
706 memcpy(colorPtr, bmp->color_table, colors * sizeof(RGBQUAD));
709 else {
710 WORD *index = colorPtr;
711 for(i = 0; i < 1 << info->bmiHeader.biBitCount; i++, index++)
712 *index = i;
715 else {
716 if (coloruse == DIB_PAL_COLORS) {
717 for (i = 0; i < (1 << bpp); i++)
718 ((WORD *)colorPtr)[i] = (WORD)i;
720 else if(bpp > 1 && bpp == bmp->bitmap.bmBitsPixel) {
721 /* For color DDBs in native depth (mono DDBs always have
722 a black/white palette):
723 Generate the color map from the selected palette */
724 PALETTEENTRY palEntry[256];
726 memset( palEntry, 0, sizeof(palEntry) );
727 if (!GetPaletteEntries( dc->hPalette, 0, 1 << bmp->bitmap.bmBitsPixel, palEntry ))
729 release_dc_ptr( dc );
730 GDI_ReleaseObj( hbitmap );
731 return 0;
733 for (i = 0; i < (1 << bmp->bitmap.bmBitsPixel); i++) {
734 if (core_header)
736 rgbTriples[i].rgbtRed = palEntry[i].peRed;
737 rgbTriples[i].rgbtGreen = palEntry[i].peGreen;
738 rgbTriples[i].rgbtBlue = palEntry[i].peBlue;
740 else
742 rgbQuads[i].rgbRed = palEntry[i].peRed;
743 rgbQuads[i].rgbGreen = palEntry[i].peGreen;
744 rgbQuads[i].rgbBlue = palEntry[i].peBlue;
745 rgbQuads[i].rgbReserved = 0;
748 } else {
749 switch (bpp) {
750 case 1:
751 if (core_header)
753 rgbTriples[0].rgbtRed = rgbTriples[0].rgbtGreen =
754 rgbTriples[0].rgbtBlue = 0;
755 rgbTriples[1].rgbtRed = rgbTriples[1].rgbtGreen =
756 rgbTriples[1].rgbtBlue = 0xff;
758 else
760 rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen =
761 rgbQuads[0].rgbBlue = 0;
762 rgbQuads[0].rgbReserved = 0;
763 rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen =
764 rgbQuads[1].rgbBlue = 0xff;
765 rgbQuads[1].rgbReserved = 0;
767 break;
769 case 4:
770 if (core_header)
771 memcpy(colorPtr, EGAColorsTriples, sizeof(EGAColorsTriples));
772 else
773 memcpy(colorPtr, EGAColorsQuads, sizeof(EGAColorsQuads));
775 break;
777 case 8:
779 if (core_header)
781 INT r, g, b;
782 RGBTRIPLE *color;
784 memcpy(rgbTriples, DefLogPaletteTriples,
785 10 * sizeof(RGBTRIPLE));
786 memcpy(rgbTriples + 246, DefLogPaletteTriples + 10,
787 10 * sizeof(RGBTRIPLE));
788 color = rgbTriples + 10;
789 for(r = 0; r <= 5; r++) /* FIXME */
790 for(g = 0; g <= 5; g++)
791 for(b = 0; b <= 5; b++) {
792 color->rgbtRed = (r * 0xff) / 5;
793 color->rgbtGreen = (g * 0xff) / 5;
794 color->rgbtBlue = (b * 0xff) / 5;
795 color++;
798 else
800 INT r, g, b;
801 RGBQUAD *color;
803 memcpy(rgbQuads, DefLogPaletteQuads,
804 10 * sizeof(RGBQUAD));
805 memcpy(rgbQuads + 246, DefLogPaletteQuads + 10,
806 10 * sizeof(RGBQUAD));
807 color = rgbQuads + 10;
808 for(r = 0; r <= 5; r++) /* FIXME */
809 for(g = 0; g <= 5; g++)
810 for(b = 0; b <= 5; b++) {
811 color->rgbRed = (r * 0xff) / 5;
812 color->rgbGreen = (g * 0xff) / 5;
813 color->rgbBlue = (b * 0xff) / 5;
814 color->rgbReserved = 0;
815 color++;
822 break;
824 case 15:
825 if (info->bmiHeader.biCompression == BI_BITFIELDS)
827 ((PDWORD)info->bmiColors)[0] = 0x7c00;
828 ((PDWORD)info->bmiColors)[1] = 0x03e0;
829 ((PDWORD)info->bmiColors)[2] = 0x001f;
831 break;
833 case 16:
834 if (info->bmiHeader.biCompression == BI_BITFIELDS)
836 if (bmp->dib) memcpy( info->bmiColors, bmp->dib->dsBitfields, 3 * sizeof(DWORD) );
837 else
839 ((PDWORD)info->bmiColors)[0] = 0xf800;
840 ((PDWORD)info->bmiColors)[1] = 0x07e0;
841 ((PDWORD)info->bmiColors)[2] = 0x001f;
844 break;
846 case 24:
847 case 32:
848 if (info->bmiHeader.biCompression == BI_BITFIELDS)
850 if (bmp->dib) memcpy( info->bmiColors, bmp->dib->dsBitfields, 3 * sizeof(DWORD) );
851 else
853 ((PDWORD)info->bmiColors)[0] = 0xff0000;
854 ((PDWORD)info->bmiColors)[1] = 0x00ff00;
855 ((PDWORD)info->bmiColors)[2] = 0x0000ff;
858 break;
861 if (bits && lines)
863 /* If the bitmap object already have a dib section that contains image data, get the bits from it */
864 if(bmp->dib && bmp->dib->dsBm.bmBitsPixel >= 15 && bpp >= 15)
866 /*FIXME: Only RGB dibs supported for now */
867 unsigned int srcwidth = bmp->dib->dsBm.bmWidth, srcwidthb = bmp->dib->dsBm.bmWidthBytes;
868 unsigned int dstwidth = width;
869 int dstwidthb = DIB_GetDIBWidthBytes( width, bpp );
870 LPBYTE dbits = bits, sbits = (LPBYTE) bmp->dib->dsBm.bmBits + (startscan * srcwidthb);
871 unsigned int x, y, width, widthb;
873 if ((height < 0) ^ (bmp->dib->dsBmih.biHeight < 0))
875 dbits = (LPBYTE)bits + (dstwidthb * (lines-1));
876 dstwidthb = -dstwidthb;
879 switch( bpp ) {
881 case 15:
882 case 16: /* 16 bpp dstDIB */
884 LPWORD dstbits = (LPWORD)dbits;
885 WORD rmask = 0x7c00, gmask= 0x03e0, bmask = 0x001f;
887 /* FIXME: BI_BITFIELDS not supported yet */
889 switch(bmp->dib->dsBm.bmBitsPixel) {
891 case 16: /* 16 bpp srcDIB -> 16 bpp dstDIB */
893 widthb = min(srcwidthb, abs(dstwidthb));
894 /* FIXME: BI_BITFIELDS not supported yet */
895 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
896 memcpy(dbits, sbits, widthb);
898 break;
900 case 24: /* 24 bpp srcDIB -> 16 bpp dstDIB */
902 LPBYTE srcbits = sbits;
904 width = min(srcwidth, dstwidth);
905 for( y = 0; y < lines; y++) {
906 for( x = 0; x < width; x++, srcbits += 3)
907 *dstbits++ = ((srcbits[0] >> 3) & bmask) |
908 (((WORD)srcbits[1] << 2) & gmask) |
909 (((WORD)srcbits[2] << 7) & rmask);
911 dstbits = (LPWORD)(dbits+=dstwidthb);
912 srcbits = (sbits += srcwidthb);
915 break;
917 case 32: /* 32 bpp srcDIB -> 16 bpp dstDIB */
919 LPDWORD srcbits = (LPDWORD)sbits;
920 DWORD val;
922 width = min(srcwidth, dstwidth);
923 for( y = 0; y < lines; y++) {
924 for( x = 0; x < width; x++ ) {
925 val = *srcbits++;
926 *dstbits++ = (WORD)(((val >> 3) & bmask) | ((val >> 6) & gmask) |
927 ((val >> 9) & rmask));
929 dstbits = (LPWORD)(dbits+=dstwidthb);
930 srcbits = (LPDWORD)(sbits+=srcwidthb);
933 break;
935 default: /* ? bit bmp -> 16 bit DIB */
936 FIXME("15/16 bit DIB %d bit bitmap\n",
937 bmp->bitmap.bmBitsPixel);
938 break;
941 break;
943 case 24: /* 24 bpp dstDIB */
945 LPBYTE dstbits = dbits;
947 switch(bmp->dib->dsBm.bmBitsPixel) {
949 case 16: /* 16 bpp srcDIB -> 24 bpp dstDIB */
951 LPWORD srcbits = (LPWORD)sbits;
952 WORD val;
954 width = min(srcwidth, dstwidth);
955 /* FIXME: BI_BITFIELDS not supported yet */
956 for( y = 0; y < lines; y++) {
957 for( x = 0; x < width; x++ ) {
958 val = *srcbits++;
959 *dstbits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07));
960 *dstbits++ = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07));
961 *dstbits++ = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07));
963 dstbits = dbits+=dstwidthb;
964 srcbits = (LPWORD)(sbits+=srcwidthb);
967 break;
969 case 24: /* 24 bpp srcDIB -> 24 bpp dstDIB */
971 widthb = min(srcwidthb, abs(dstwidthb));
972 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
973 memcpy(dbits, sbits, widthb);
975 break;
977 case 32: /* 32 bpp srcDIB -> 24 bpp dstDIB */
979 LPBYTE srcbits = sbits;
981 width = min(srcwidth, dstwidth);
982 for( y = 0; y < lines; y++) {
983 for( x = 0; x < width; x++, srcbits++ ) {
984 *dstbits++ = *srcbits++;
985 *dstbits++ = *srcbits++;
986 *dstbits++ = *srcbits++;
988 dstbits = dbits+=dstwidthb;
989 srcbits = sbits+=srcwidthb;
992 break;
994 default: /* ? bit bmp -> 24 bit DIB */
995 FIXME("24 bit DIB %d bit bitmap\n",
996 bmp->bitmap.bmBitsPixel);
997 break;
1000 break;
1002 case 32: /* 32 bpp dstDIB */
1004 LPDWORD dstbits = (LPDWORD)dbits;
1006 /* FIXME: BI_BITFIELDS not supported yet */
1008 switch(bmp->dib->dsBm.bmBitsPixel) {
1009 case 16: /* 16 bpp srcDIB -> 32 bpp dstDIB */
1011 LPWORD srcbits = (LPWORD)sbits;
1012 DWORD val;
1014 width = min(srcwidth, dstwidth);
1015 /* FIXME: BI_BITFIELDS not supported yet */
1016 for( y = 0; y < lines; y++) {
1017 for( x = 0; x < width; x++ ) {
1018 val = (DWORD)*srcbits++;
1019 *dstbits++ = ((val << 3) & 0xf8) | ((val >> 2) & 0x07) |
1020 ((val << 6) & 0xf800) | ((val << 1) & 0x0700) |
1021 ((val << 9) & 0xf80000) | ((val << 4) & 0x070000);
1023 dstbits=(LPDWORD)(dbits+=dstwidthb);
1024 srcbits=(LPWORD)(sbits+=srcwidthb);
1027 break;
1029 case 24: /* 24 bpp srcDIB -> 32 bpp dstDIB */
1031 LPBYTE srcbits = sbits;
1033 width = min(srcwidth, dstwidth);
1034 for( y = 0; y < lines; y++) {
1035 for( x = 0; x < width; x++, srcbits+=3 )
1036 *dstbits++ = srcbits[0] |
1037 (srcbits[1] << 8) |
1038 (srcbits[2] << 16);
1039 dstbits=(LPDWORD)(dbits+=dstwidthb);
1040 srcbits=(sbits+=srcwidthb);
1043 break;
1045 case 32: /* 32 bpp srcDIB -> 32 bpp dstDIB */
1047 widthb = min(srcwidthb, abs(dstwidthb));
1048 /* FIXME: BI_BITFIELDS not supported yet */
1049 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb) {
1050 memcpy(dbits, sbits, widthb);
1053 break;
1055 default: /* ? bit bmp -> 32 bit DIB */
1056 FIXME("32 bit DIB %d bit bitmap\n",
1057 bmp->bitmap.bmBitsPixel);
1058 break;
1061 break;
1063 default: /* ? bit DIB */
1064 FIXME("Unsupported DIB depth %d\n", info->bmiHeader.biBitCount);
1065 break;
1068 /* Otherwise, get bits from the XImage */
1069 else
1071 if (!bmp->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) lines = 0;
1072 else
1074 if (bmp->funcs && bmp->funcs->pGetDIBits)
1075 lines = bmp->funcs->pGetDIBits( dc->physDev, hbitmap, startscan,
1076 lines, bits, info, coloruse );
1077 else
1078 lines = 0; /* FIXME: should copy from bmp->bitmap.bmBits */
1082 else lines = abs(height);
1084 /* The knowledge base article Q81498 ("DIBs and Their Uses") states that
1085 if bits == NULL and bpp != 0, only biSizeImage and the color table are
1086 filled in. */
1087 if (!core_header)
1089 /* FIXME: biSizeImage should be calculated according to the selected
1090 compression algorithm if biCompression != BI_RGB */
1091 info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes( width, height, bpp );
1092 TRACE("biSizeImage = %d, ", info->bmiHeader.biSizeImage);
1094 TRACE("biWidth = %d, biHeight = %d\n", width, height);
1096 done:
1097 release_dc_ptr( dc );
1098 GDI_ReleaseObj( hbitmap );
1099 return lines;
1103 /***********************************************************************
1104 * CreateDIBitmap (GDI32.@)
1106 * Creates a DDB (device dependent bitmap) from a DIB.
1107 * The DDB will have the same color depth as the reference DC.
1109 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
1110 DWORD init, LPCVOID bits, const BITMAPINFO *data,
1111 UINT coloruse )
1113 HBITMAP handle;
1114 LONG width;
1115 LONG height;
1116 WORD planes, bpp;
1117 DWORD compr, size;
1118 DC *dc;
1120 if (!header) return 0;
1122 if (DIB_GetBitmapInfo( header, &width, &height, &planes, &bpp, &compr, &size ) == -1) return 0;
1124 if (width < 0)
1126 TRACE("Bitmap has a negative width\n");
1127 return 0;
1130 /* Top-down DIBs have a negative height */
1131 if (height < 0) height = -height;
1133 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1134 hdc, header, init, bits, data, coloruse, width, height, bpp, compr);
1136 if (hdc == NULL)
1137 handle = CreateBitmap( width, height, 1, 1, NULL );
1138 else
1139 handle = CreateCompatibleBitmap( hdc, width, height );
1141 if (handle)
1143 if (init & CBM_INIT)
1145 if (SetDIBits( hdc, handle, 0, height, bits, data, coloruse ) == 0)
1147 DeleteObject( handle );
1148 handle = 0;
1152 else if (hdc && ((dc = get_dc_ptr( hdc )) != NULL) )
1154 if (!BITMAP_SetOwnerDC( handle, dc ))
1156 DeleteObject( handle );
1157 handle = 0;
1159 release_dc_ptr( dc );
1163 return handle;
1166 /* Copy/synthesize RGB palette from BITMAPINFO. Ripped from dlls/winex11.drv/dib.c */
1167 static void DIB_CopyColorTable( DC *dc, BITMAPOBJ *bmp, WORD coloruse, const BITMAPINFO *info )
1169 RGBQUAD *colorTable;
1170 unsigned int colors, i;
1171 BOOL core_info = info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER);
1173 if (core_info)
1175 colors = 1 << ((const BITMAPCOREINFO*) info)->bmciHeader.bcBitCount;
1177 else
1179 colors = info->bmiHeader.biClrUsed;
1180 if (!colors) colors = 1 << info->bmiHeader.biBitCount;
1183 if (colors > 256) {
1184 ERR("called with >256 colors!\n");
1185 return;
1188 if (!(colorTable = HeapAlloc(GetProcessHeap(), 0, colors * sizeof(RGBQUAD) ))) return;
1190 if(coloruse == DIB_RGB_COLORS)
1192 if (core_info)
1194 /* Convert RGBTRIPLEs to RGBQUADs */
1195 for (i=0; i < colors; i++)
1197 colorTable[i].rgbRed = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtRed;
1198 colorTable[i].rgbGreen = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtGreen;
1199 colorTable[i].rgbBlue = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtBlue;
1200 colorTable[i].rgbReserved = 0;
1203 else
1205 memcpy(colorTable, (const BYTE*) info + (WORD) info->bmiHeader.biSize, colors * sizeof(RGBQUAD));
1208 else
1210 PALETTEENTRY entries[256];
1211 const WORD *index = (const WORD*) ((const BYTE*) info + (WORD) info->bmiHeader.biSize);
1212 UINT count = GetPaletteEntries( dc->hPalette, 0, colors, entries );
1214 for (i = 0; i < colors; i++, index++)
1216 PALETTEENTRY *entry = &entries[*index % count];
1217 colorTable[i].rgbRed = entry->peRed;
1218 colorTable[i].rgbGreen = entry->peGreen;
1219 colorTable[i].rgbBlue = entry->peBlue;
1220 colorTable[i].rgbReserved = 0;
1223 bmp->color_table = colorTable;
1224 bmp->nb_colors = colors;
1227 /***********************************************************************
1228 * CreateDIBSection (GDI32.@)
1230 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
1231 VOID **bits, HANDLE section, DWORD offset)
1233 HBITMAP ret = 0;
1234 DC *dc;
1235 BOOL bDesktopDC = FALSE;
1236 DIBSECTION *dib;
1237 BITMAPOBJ *bmp;
1238 int bitmap_type;
1239 LONG width, height;
1240 WORD planes, bpp;
1241 DWORD compression, sizeImage;
1242 void *mapBits = NULL;
1244 if(!bmi){
1245 if(bits) *bits = NULL;
1246 return NULL;
1249 if (((bitmap_type = DIB_GetBitmapInfo( &bmi->bmiHeader, &width, &height,
1250 &planes, &bpp, &compression, &sizeImage )) == -1))
1251 return 0;
1253 switch (bpp)
1255 case 16:
1256 case 32:
1257 if (compression == BI_BITFIELDS) break;
1258 /* fall through */
1259 case 1:
1260 case 4:
1261 case 8:
1262 case 24:
1263 if (compression == BI_RGB) break;
1264 WARN( "invalid %u bpp compression %u\n", bpp, compression );
1265 return 0;
1266 default:
1267 FIXME( "should fail %u bpp compression %u\n", bpp, compression );
1268 break;
1271 if (!(dib = HeapAlloc( GetProcessHeap(), 0, sizeof(*dib) ))) return 0;
1273 TRACE("format (%d,%d), planes %d, bpp %d, size %d, %s\n",
1274 width, height, planes, bpp, sizeImage, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1276 dib->dsBm.bmType = 0;
1277 dib->dsBm.bmWidth = width;
1278 dib->dsBm.bmHeight = height >= 0 ? height : -height;
1279 dib->dsBm.bmWidthBytes = DIB_GetDIBWidthBytes(width, bpp);
1280 dib->dsBm.bmPlanes = planes;
1281 dib->dsBm.bmBitsPixel = bpp;
1282 dib->dsBm.bmBits = NULL;
1284 if (!bitmap_type) /* core header */
1286 /* convert the BITMAPCOREHEADER to a BITMAPINFOHEADER */
1287 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1288 dib->dsBmih.biWidth = width;
1289 dib->dsBmih.biHeight = height;
1290 dib->dsBmih.biPlanes = planes;
1291 dib->dsBmih.biBitCount = bpp;
1292 dib->dsBmih.biCompression = compression;
1293 dib->dsBmih.biXPelsPerMeter = 0;
1294 dib->dsBmih.biYPelsPerMeter = 0;
1295 dib->dsBmih.biClrUsed = 0;
1296 dib->dsBmih.biClrImportant = 0;
1298 else
1300 /* truncate extended bitmap headers (BITMAPV4HEADER etc.) */
1301 dib->dsBmih = bmi->bmiHeader;
1302 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1305 /* set number of entries in bmi.bmiColors table */
1306 if( bpp <= 8 )
1307 dib->dsBmih.biClrUsed = 1 << bpp;
1309 dib->dsBmih.biSizeImage = dib->dsBm.bmWidthBytes * dib->dsBm.bmHeight;
1311 /* set dsBitfields values */
1312 if (usage == DIB_PAL_COLORS || bpp <= 8)
1314 dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
1316 else switch( bpp )
1318 case 15:
1319 case 16:
1320 dib->dsBitfields[0] = (compression == BI_BITFIELDS) ? *(const DWORD *)bmi->bmiColors : 0x7c00;
1321 dib->dsBitfields[1] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 1) : 0x03e0;
1322 dib->dsBitfields[2] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 2) : 0x001f;
1323 break;
1324 case 24:
1325 case 32:
1326 dib->dsBitfields[0] = (compression == BI_BITFIELDS) ? *(const DWORD *)bmi->bmiColors : 0xff0000;
1327 dib->dsBitfields[1] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 1) : 0x00ff00;
1328 dib->dsBitfields[2] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 2) : 0x0000ff;
1329 break;
1332 /* get storage location for DIB bits */
1334 if (section)
1336 SYSTEM_INFO SystemInfo;
1337 DWORD mapOffset;
1338 INT mapSize;
1340 GetSystemInfo( &SystemInfo );
1341 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
1342 mapSize = dib->dsBmih.biSizeImage + (offset - mapOffset);
1343 mapBits = MapViewOfFile( section, FILE_MAP_ALL_ACCESS, 0, mapOffset, mapSize );
1344 if (mapBits) dib->dsBm.bmBits = (char *)mapBits + (offset - mapOffset);
1346 else
1348 offset = 0;
1349 dib->dsBm.bmBits = VirtualAlloc( NULL, dib->dsBmih.biSizeImage,
1350 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
1352 dib->dshSection = section;
1353 dib->dsOffset = offset;
1355 if (!dib->dsBm.bmBits)
1357 HeapFree( GetProcessHeap(), 0, dib );
1358 return 0;
1361 /* If the reference hdc is null, take the desktop dc */
1362 if (hdc == 0)
1364 hdc = CreateCompatibleDC(0);
1365 bDesktopDC = TRUE;
1368 if (!(dc = get_dc_ptr( hdc ))) goto error;
1370 /* create Device Dependent Bitmap and add DIB pointer */
1371 ret = CreateBitmap( dib->dsBm.bmWidth, dib->dsBm.bmHeight, 1,
1372 (bpp == 1) ? 1 : GetDeviceCaps(hdc, BITSPIXEL), NULL );
1374 if (ret && ((bmp = GDI_GetObjPtr(ret, OBJ_BITMAP))))
1376 bmp->dib = dib;
1377 bmp->funcs = dc->funcs;
1378 /* create local copy of DIB palette */
1379 if (bpp <= 8) DIB_CopyColorTable( dc, bmp, usage, bmi );
1380 GDI_ReleaseObj( ret );
1382 if (dc->funcs->pCreateDIBSection)
1384 if (!dc->funcs->pCreateDIBSection(dc->physDev, ret, bmi, usage))
1386 DeleteObject( ret );
1387 ret = 0;
1392 release_dc_ptr( dc );
1393 if (bDesktopDC) DeleteDC( hdc );
1394 if (ret && bits) *bits = dib->dsBm.bmBits;
1395 return ret;
1397 error:
1398 if (bDesktopDC) DeleteDC( hdc );
1399 if (section) UnmapViewOfFile( mapBits );
1400 else if (!offset) VirtualFree( dib->dsBm.bmBits, 0, MEM_RELEASE );
1401 HeapFree( GetProcessHeap(), 0, dib );
1402 return 0;