gdi32: Return the actual DIB section bitfields instead of default values in GetDIBits.
[wine.git] / dlls / gdi32 / dib.c
blob2725247de4ada1761cc592b4ae7b347b8ae7fc10
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 info->bmiHeader.biCompression = (bmp->bitmap.bmBitsPixel > 8) ? BI_BITFIELDS : BI_RGB;
651 switch(bmp->bitmap.bmBitsPixel)
653 case 15:
654 info->bmiHeader.biBitCount = 16;
655 break;
656 case 24:
657 info->bmiHeader.biBitCount = 32;
658 break;
659 default:
660 info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
661 break;
663 info->bmiHeader.biXPelsPerMeter = 0;
664 info->bmiHeader.biYPelsPerMeter = 0;
665 info->bmiHeader.biClrUsed = 0;
666 info->bmiHeader.biClrImportant = 0;
668 /* Windows 2000 doesn't touch the additional struct members if
669 it's a BITMAPV4HEADER or a BITMAPV5HEADER */
671 lines = abs(bmp->bitmap.bmHeight);
672 goto done;
674 case 1:
675 case 4:
676 case 8:
677 if (!core_header) info->bmiHeader.biClrUsed = 0;
679 /* If the bitmap object already has a dib section at the
680 same color depth then get the color map from it */
681 if (bmp->dib && bmp->dib->dsBm.bmBitsPixel == bpp) {
682 if(coloruse == DIB_RGB_COLORS) {
683 unsigned int colors = min( bmp->nb_colors, 1 << bpp );
685 if (core_header)
687 /* Convert the color table (RGBQUAD to RGBTRIPLE) */
688 RGBTRIPLE* index = rgbTriples;
690 for (i=0; i < colors; i++, index++)
692 index->rgbtRed = bmp->color_table[i].rgbRed;
693 index->rgbtGreen = bmp->color_table[i].rgbGreen;
694 index->rgbtBlue = bmp->color_table[i].rgbBlue;
697 else
699 if (colors != 1 << bpp) info->bmiHeader.biClrUsed = colors;
700 memcpy(colorPtr, bmp->color_table, colors * sizeof(RGBQUAD));
703 else {
704 WORD *index = colorPtr;
705 for(i = 0; i < 1 << info->bmiHeader.biBitCount; i++, index++)
706 *index = i;
709 else {
710 if (coloruse == DIB_PAL_COLORS) {
711 for (i = 0; i < (1 << bpp); i++)
712 ((WORD *)colorPtr)[i] = (WORD)i;
714 else if(bpp > 1 && bpp == bmp->bitmap.bmBitsPixel) {
715 /* For color DDBs in native depth (mono DDBs always have
716 a black/white palette):
717 Generate the color map from the selected palette */
718 PALETTEENTRY palEntry[256];
720 memset( palEntry, 0, sizeof(palEntry) );
721 if (!GetPaletteEntries( dc->hPalette, 0, 1 << bmp->bitmap.bmBitsPixel, palEntry ))
723 release_dc_ptr( dc );
724 GDI_ReleaseObj( hbitmap );
725 return 0;
727 for (i = 0; i < (1 << bmp->bitmap.bmBitsPixel); i++) {
728 if (core_header)
730 rgbTriples[i].rgbtRed = palEntry[i].peRed;
731 rgbTriples[i].rgbtGreen = palEntry[i].peGreen;
732 rgbTriples[i].rgbtBlue = palEntry[i].peBlue;
734 else
736 rgbQuads[i].rgbRed = palEntry[i].peRed;
737 rgbQuads[i].rgbGreen = palEntry[i].peGreen;
738 rgbQuads[i].rgbBlue = palEntry[i].peBlue;
739 rgbQuads[i].rgbReserved = 0;
742 } else {
743 switch (bpp) {
744 case 1:
745 if (core_header)
747 rgbTriples[0].rgbtRed = rgbTriples[0].rgbtGreen =
748 rgbTriples[0].rgbtBlue = 0;
749 rgbTriples[1].rgbtRed = rgbTriples[1].rgbtGreen =
750 rgbTriples[1].rgbtBlue = 0xff;
752 else
754 rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen =
755 rgbQuads[0].rgbBlue = 0;
756 rgbQuads[0].rgbReserved = 0;
757 rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen =
758 rgbQuads[1].rgbBlue = 0xff;
759 rgbQuads[1].rgbReserved = 0;
761 break;
763 case 4:
764 if (core_header)
765 memcpy(colorPtr, EGAColorsTriples, sizeof(EGAColorsTriples));
766 else
767 memcpy(colorPtr, EGAColorsQuads, sizeof(EGAColorsQuads));
769 break;
771 case 8:
773 if (core_header)
775 INT r, g, b;
776 RGBTRIPLE *color;
778 memcpy(rgbTriples, DefLogPaletteTriples,
779 10 * sizeof(RGBTRIPLE));
780 memcpy(rgbTriples + 246, DefLogPaletteTriples + 10,
781 10 * sizeof(RGBTRIPLE));
782 color = rgbTriples + 10;
783 for(r = 0; r <= 5; r++) /* FIXME */
784 for(g = 0; g <= 5; g++)
785 for(b = 0; b <= 5; b++) {
786 color->rgbtRed = (r * 0xff) / 5;
787 color->rgbtGreen = (g * 0xff) / 5;
788 color->rgbtBlue = (b * 0xff) / 5;
789 color++;
792 else
794 INT r, g, b;
795 RGBQUAD *color;
797 memcpy(rgbQuads, DefLogPaletteQuads,
798 10 * sizeof(RGBQUAD));
799 memcpy(rgbQuads + 246, DefLogPaletteQuads + 10,
800 10 * sizeof(RGBQUAD));
801 color = rgbQuads + 10;
802 for(r = 0; r <= 5; r++) /* FIXME */
803 for(g = 0; g <= 5; g++)
804 for(b = 0; b <= 5; b++) {
805 color->rgbRed = (r * 0xff) / 5;
806 color->rgbGreen = (g * 0xff) / 5;
807 color->rgbBlue = (b * 0xff) / 5;
808 color->rgbReserved = 0;
809 color++;
816 break;
818 case 15:
819 if (info->bmiHeader.biCompression == BI_BITFIELDS)
821 ((PDWORD)info->bmiColors)[0] = 0x7c00;
822 ((PDWORD)info->bmiColors)[1] = 0x03e0;
823 ((PDWORD)info->bmiColors)[2] = 0x001f;
825 break;
827 case 16:
828 if (info->bmiHeader.biCompression == BI_BITFIELDS)
830 if (bmp->dib) memcpy( info->bmiColors, bmp->dib->dsBitfields, 3 * sizeof(DWORD) );
831 else
833 ((PDWORD)info->bmiColors)[0] = 0xf800;
834 ((PDWORD)info->bmiColors)[1] = 0x07e0;
835 ((PDWORD)info->bmiColors)[2] = 0x001f;
838 break;
840 case 24:
841 case 32:
842 if (info->bmiHeader.biCompression == BI_BITFIELDS)
844 if (bmp->dib) memcpy( info->bmiColors, bmp->dib->dsBitfields, 3 * sizeof(DWORD) );
845 else
847 ((PDWORD)info->bmiColors)[0] = 0xff0000;
848 ((PDWORD)info->bmiColors)[1] = 0x00ff00;
849 ((PDWORD)info->bmiColors)[2] = 0x0000ff;
852 break;
855 if (bits && lines)
857 /* If the bitmap object already have a dib section that contains image data, get the bits from it */
858 if(bmp->dib && bmp->dib->dsBm.bmBitsPixel >= 15 && bpp >= 15)
860 /*FIXME: Only RGB dibs supported for now */
861 unsigned int srcwidth = bmp->dib->dsBm.bmWidth, srcwidthb = bmp->dib->dsBm.bmWidthBytes;
862 unsigned int dstwidth = width;
863 int dstwidthb = DIB_GetDIBWidthBytes( width, bpp );
864 LPBYTE dbits = bits, sbits = (LPBYTE) bmp->dib->dsBm.bmBits + (startscan * srcwidthb);
865 unsigned int x, y, width, widthb;
867 if ((height < 0) ^ (bmp->dib->dsBmih.biHeight < 0))
869 dbits = (LPBYTE)bits + (dstwidthb * (lines-1));
870 dstwidthb = -dstwidthb;
873 switch( bpp ) {
875 case 15:
876 case 16: /* 16 bpp dstDIB */
878 LPWORD dstbits = (LPWORD)dbits;
879 WORD rmask = 0x7c00, gmask= 0x03e0, bmask = 0x001f;
881 /* FIXME: BI_BITFIELDS not supported yet */
883 switch(bmp->dib->dsBm.bmBitsPixel) {
885 case 16: /* 16 bpp srcDIB -> 16 bpp dstDIB */
887 widthb = min(srcwidthb, abs(dstwidthb));
888 /* FIXME: BI_BITFIELDS not supported yet */
889 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
890 memcpy(dbits, sbits, widthb);
892 break;
894 case 24: /* 24 bpp srcDIB -> 16 bpp dstDIB */
896 LPBYTE srcbits = sbits;
898 width = min(srcwidth, dstwidth);
899 for( y = 0; y < lines; y++) {
900 for( x = 0; x < width; x++, srcbits += 3)
901 *dstbits++ = ((srcbits[0] >> 3) & bmask) |
902 (((WORD)srcbits[1] << 2) & gmask) |
903 (((WORD)srcbits[2] << 7) & rmask);
905 dstbits = (LPWORD)(dbits+=dstwidthb);
906 srcbits = (sbits += srcwidthb);
909 break;
911 case 32: /* 32 bpp srcDIB -> 16 bpp dstDIB */
913 LPDWORD srcbits = (LPDWORD)sbits;
914 DWORD val;
916 width = min(srcwidth, dstwidth);
917 for( y = 0; y < lines; y++) {
918 for( x = 0; x < width; x++ ) {
919 val = *srcbits++;
920 *dstbits++ = (WORD)(((val >> 3) & bmask) | ((val >> 6) & gmask) |
921 ((val >> 9) & rmask));
923 dstbits = (LPWORD)(dbits+=dstwidthb);
924 srcbits = (LPDWORD)(sbits+=srcwidthb);
927 break;
929 default: /* ? bit bmp -> 16 bit DIB */
930 FIXME("15/16 bit DIB %d bit bitmap\n",
931 bmp->bitmap.bmBitsPixel);
932 break;
935 break;
937 case 24: /* 24 bpp dstDIB */
939 LPBYTE dstbits = dbits;
941 switch(bmp->dib->dsBm.bmBitsPixel) {
943 case 16: /* 16 bpp srcDIB -> 24 bpp dstDIB */
945 LPWORD srcbits = (LPWORD)sbits;
946 WORD val;
948 width = min(srcwidth, dstwidth);
949 /* FIXME: BI_BITFIELDS not supported yet */
950 for( y = 0; y < lines; y++) {
951 for( x = 0; x < width; x++ ) {
952 val = *srcbits++;
953 *dstbits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07));
954 *dstbits++ = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07));
955 *dstbits++ = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07));
957 dstbits = dbits+=dstwidthb;
958 srcbits = (LPWORD)(sbits+=srcwidthb);
961 break;
963 case 24: /* 24 bpp srcDIB -> 24 bpp dstDIB */
965 widthb = min(srcwidthb, abs(dstwidthb));
966 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
967 memcpy(dbits, sbits, widthb);
969 break;
971 case 32: /* 32 bpp srcDIB -> 24 bpp dstDIB */
973 LPBYTE srcbits = sbits;
975 width = min(srcwidth, dstwidth);
976 for( y = 0; y < lines; y++) {
977 for( x = 0; x < width; x++, srcbits++ ) {
978 *dstbits++ = *srcbits++;
979 *dstbits++ = *srcbits++;
980 *dstbits++ = *srcbits++;
982 dstbits = dbits+=dstwidthb;
983 srcbits = sbits+=srcwidthb;
986 break;
988 default: /* ? bit bmp -> 24 bit DIB */
989 FIXME("24 bit DIB %d bit bitmap\n",
990 bmp->bitmap.bmBitsPixel);
991 break;
994 break;
996 case 32: /* 32 bpp dstDIB */
998 LPDWORD dstbits = (LPDWORD)dbits;
1000 /* FIXME: BI_BITFIELDS not supported yet */
1002 switch(bmp->dib->dsBm.bmBitsPixel) {
1003 case 16: /* 16 bpp srcDIB -> 32 bpp dstDIB */
1005 LPWORD srcbits = (LPWORD)sbits;
1006 DWORD val;
1008 width = min(srcwidth, dstwidth);
1009 /* FIXME: BI_BITFIELDS not supported yet */
1010 for( y = 0; y < lines; y++) {
1011 for( x = 0; x < width; x++ ) {
1012 val = (DWORD)*srcbits++;
1013 *dstbits++ = ((val << 3) & 0xf8) | ((val >> 2) & 0x07) |
1014 ((val << 6) & 0xf800) | ((val << 1) & 0x0700) |
1015 ((val << 9) & 0xf80000) | ((val << 4) & 0x070000);
1017 dstbits=(LPDWORD)(dbits+=dstwidthb);
1018 srcbits=(LPWORD)(sbits+=srcwidthb);
1021 break;
1023 case 24: /* 24 bpp srcDIB -> 32 bpp dstDIB */
1025 LPBYTE srcbits = sbits;
1027 width = min(srcwidth, dstwidth);
1028 for( y = 0; y < lines; y++) {
1029 for( x = 0; x < width; x++, srcbits+=3 )
1030 *dstbits++ = srcbits[0] |
1031 (srcbits[1] << 8) |
1032 (srcbits[2] << 16);
1033 dstbits=(LPDWORD)(dbits+=dstwidthb);
1034 srcbits=(sbits+=srcwidthb);
1037 break;
1039 case 32: /* 32 bpp srcDIB -> 32 bpp dstDIB */
1041 widthb = min(srcwidthb, abs(dstwidthb));
1042 /* FIXME: BI_BITFIELDS not supported yet */
1043 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb) {
1044 memcpy(dbits, sbits, widthb);
1047 break;
1049 default: /* ? bit bmp -> 32 bit DIB */
1050 FIXME("32 bit DIB %d bit bitmap\n",
1051 bmp->bitmap.bmBitsPixel);
1052 break;
1055 break;
1057 default: /* ? bit DIB */
1058 FIXME("Unsupported DIB depth %d\n", info->bmiHeader.biBitCount);
1059 break;
1062 /* Otherwise, get bits from the XImage */
1063 else
1065 if (!bmp->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) lines = 0;
1066 else
1068 if (bmp->funcs && bmp->funcs->pGetDIBits)
1069 lines = bmp->funcs->pGetDIBits( dc->physDev, hbitmap, startscan,
1070 lines, bits, info, coloruse );
1071 else
1072 lines = 0; /* FIXME: should copy from bmp->bitmap.bmBits */
1076 else lines = abs(height);
1078 /* The knowledge base article Q81498 ("DIBs and Their Uses") states that
1079 if bits == NULL and bpp != 0, only biSizeImage and the color table are
1080 filled in. */
1081 if (!core_header)
1083 /* FIXME: biSizeImage should be calculated according to the selected
1084 compression algorithm if biCompression != BI_RGB */
1085 info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes( width, height, bpp );
1086 TRACE("biSizeImage = %d, ", info->bmiHeader.biSizeImage);
1088 TRACE("biWidth = %d, biHeight = %d\n", width, height);
1090 done:
1091 release_dc_ptr( dc );
1092 GDI_ReleaseObj( hbitmap );
1093 return lines;
1097 /***********************************************************************
1098 * CreateDIBitmap (GDI32.@)
1100 * Creates a DDB (device dependent bitmap) from a DIB.
1101 * The DDB will have the same color depth as the reference DC.
1103 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
1104 DWORD init, LPCVOID bits, const BITMAPINFO *data,
1105 UINT coloruse )
1107 HBITMAP handle;
1108 LONG width;
1109 LONG height;
1110 WORD planes, bpp;
1111 DWORD compr, size;
1112 DC *dc;
1114 if (!header) return 0;
1116 if (DIB_GetBitmapInfo( header, &width, &height, &planes, &bpp, &compr, &size ) == -1) return 0;
1118 if (width < 0)
1120 TRACE("Bitmap has a negative width\n");
1121 return 0;
1124 /* Top-down DIBs have a negative height */
1125 if (height < 0) height = -height;
1127 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1128 hdc, header, init, bits, data, coloruse, width, height, bpp, compr);
1130 if (hdc == NULL)
1131 handle = CreateBitmap( width, height, 1, 1, NULL );
1132 else
1133 handle = CreateCompatibleBitmap( hdc, width, height );
1135 if (handle)
1137 if (init & CBM_INIT)
1139 if (SetDIBits( hdc, handle, 0, height, bits, data, coloruse ) == 0)
1141 DeleteObject( handle );
1142 handle = 0;
1146 else if (hdc && ((dc = get_dc_ptr( hdc )) != NULL) )
1148 if (!BITMAP_SetOwnerDC( handle, dc ))
1150 DeleteObject( handle );
1151 handle = 0;
1153 release_dc_ptr( dc );
1157 return handle;
1160 /* Copy/synthesize RGB palette from BITMAPINFO. Ripped from dlls/winex11.drv/dib.c */
1161 static void DIB_CopyColorTable( DC *dc, BITMAPOBJ *bmp, WORD coloruse, const BITMAPINFO *info )
1163 RGBQUAD *colorTable;
1164 unsigned int colors, i;
1165 BOOL core_info = info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER);
1167 if (core_info)
1169 colors = 1 << ((const BITMAPCOREINFO*) info)->bmciHeader.bcBitCount;
1171 else
1173 colors = info->bmiHeader.biClrUsed;
1174 if (!colors) colors = 1 << info->bmiHeader.biBitCount;
1177 if (colors > 256) {
1178 ERR("called with >256 colors!\n");
1179 return;
1182 if (!(colorTable = HeapAlloc(GetProcessHeap(), 0, colors * sizeof(RGBQUAD) ))) return;
1184 if(coloruse == DIB_RGB_COLORS)
1186 if (core_info)
1188 /* Convert RGBTRIPLEs to RGBQUADs */
1189 for (i=0; i < colors; i++)
1191 colorTable[i].rgbRed = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtRed;
1192 colorTable[i].rgbGreen = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtGreen;
1193 colorTable[i].rgbBlue = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtBlue;
1194 colorTable[i].rgbReserved = 0;
1197 else
1199 memcpy(colorTable, (const BYTE*) info + (WORD) info->bmiHeader.biSize, colors * sizeof(RGBQUAD));
1202 else
1204 PALETTEENTRY entries[256];
1205 const WORD *index = (const WORD*) ((const BYTE*) info + (WORD) info->bmiHeader.biSize);
1206 UINT count = GetPaletteEntries( dc->hPalette, 0, colors, entries );
1208 for (i = 0; i < colors; i++, index++)
1210 PALETTEENTRY *entry = &entries[*index % count];
1211 colorTable[i].rgbRed = entry->peRed;
1212 colorTable[i].rgbGreen = entry->peGreen;
1213 colorTable[i].rgbBlue = entry->peBlue;
1214 colorTable[i].rgbReserved = 0;
1217 bmp->color_table = colorTable;
1218 bmp->nb_colors = colors;
1221 /***********************************************************************
1222 * CreateDIBSection (GDI32.@)
1224 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
1225 VOID **bits, HANDLE section, DWORD offset)
1227 HBITMAP ret = 0;
1228 DC *dc;
1229 BOOL bDesktopDC = FALSE;
1230 DIBSECTION *dib;
1231 BITMAPOBJ *bmp;
1232 int bitmap_type;
1233 LONG width, height;
1234 WORD planes, bpp;
1235 DWORD compression, sizeImage;
1236 void *mapBits = NULL;
1238 if(!bmi){
1239 if(bits) *bits = NULL;
1240 return NULL;
1243 if (((bitmap_type = DIB_GetBitmapInfo( &bmi->bmiHeader, &width, &height,
1244 &planes, &bpp, &compression, &sizeImage )) == -1))
1245 return 0;
1247 if (compression != BI_RGB && compression != BI_BITFIELDS)
1249 TRACE("can't create a compressed (%u) dibsection\n", compression);
1250 return 0;
1253 if (!(dib = HeapAlloc( GetProcessHeap(), 0, sizeof(*dib) ))) return 0;
1255 TRACE("format (%d,%d), planes %d, bpp %d, size %d, %s\n",
1256 width, height, planes, bpp, sizeImage, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1258 dib->dsBm.bmType = 0;
1259 dib->dsBm.bmWidth = width;
1260 dib->dsBm.bmHeight = height >= 0 ? height : -height;
1261 dib->dsBm.bmWidthBytes = DIB_GetDIBWidthBytes(width, bpp);
1262 dib->dsBm.bmPlanes = planes;
1263 dib->dsBm.bmBitsPixel = bpp;
1264 dib->dsBm.bmBits = NULL;
1266 if (!bitmap_type) /* core header */
1268 /* convert the BITMAPCOREHEADER to a BITMAPINFOHEADER */
1269 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1270 dib->dsBmih.biWidth = width;
1271 dib->dsBmih.biHeight = height;
1272 dib->dsBmih.biPlanes = planes;
1273 dib->dsBmih.biBitCount = bpp;
1274 dib->dsBmih.biCompression = compression;
1275 dib->dsBmih.biXPelsPerMeter = 0;
1276 dib->dsBmih.biYPelsPerMeter = 0;
1277 dib->dsBmih.biClrUsed = 0;
1278 dib->dsBmih.biClrImportant = 0;
1280 else
1282 /* truncate extended bitmap headers (BITMAPV4HEADER etc.) */
1283 dib->dsBmih = bmi->bmiHeader;
1284 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1287 /* set number of entries in bmi.bmiColors table */
1288 if( bpp <= 8 )
1289 dib->dsBmih.biClrUsed = 1 << bpp;
1291 dib->dsBmih.biSizeImage = dib->dsBm.bmWidthBytes * dib->dsBm.bmHeight;
1293 /* set dsBitfields values */
1294 if (usage == DIB_PAL_COLORS || bpp <= 8)
1296 dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
1298 else switch( bpp )
1300 case 15:
1301 case 16:
1302 dib->dsBitfields[0] = (compression == BI_BITFIELDS) ? *(const DWORD *)bmi->bmiColors : 0x7c00;
1303 dib->dsBitfields[1] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 1) : 0x03e0;
1304 dib->dsBitfields[2] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 2) : 0x001f;
1305 break;
1306 case 24:
1307 case 32:
1308 dib->dsBitfields[0] = (compression == BI_BITFIELDS) ? *(const DWORD *)bmi->bmiColors : 0xff0000;
1309 dib->dsBitfields[1] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 1) : 0x00ff00;
1310 dib->dsBitfields[2] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 2) : 0x0000ff;
1311 break;
1314 /* get storage location for DIB bits */
1316 if (section)
1318 SYSTEM_INFO SystemInfo;
1319 DWORD mapOffset;
1320 INT mapSize;
1322 GetSystemInfo( &SystemInfo );
1323 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
1324 mapSize = dib->dsBmih.biSizeImage + (offset - mapOffset);
1325 mapBits = MapViewOfFile( section, FILE_MAP_ALL_ACCESS, 0, mapOffset, mapSize );
1326 if (mapBits) dib->dsBm.bmBits = (char *)mapBits + (offset - mapOffset);
1328 else
1330 offset = 0;
1331 dib->dsBm.bmBits = VirtualAlloc( NULL, dib->dsBmih.biSizeImage,
1332 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
1334 dib->dshSection = section;
1335 dib->dsOffset = offset;
1337 if (!dib->dsBm.bmBits)
1339 HeapFree( GetProcessHeap(), 0, dib );
1340 return 0;
1343 /* If the reference hdc is null, take the desktop dc */
1344 if (hdc == 0)
1346 hdc = CreateCompatibleDC(0);
1347 bDesktopDC = TRUE;
1350 if (!(dc = get_dc_ptr( hdc ))) goto error;
1352 /* create Device Dependent Bitmap and add DIB pointer */
1353 ret = CreateBitmap( dib->dsBm.bmWidth, dib->dsBm.bmHeight, 1,
1354 (bpp == 1) ? 1 : GetDeviceCaps(hdc, BITSPIXEL), NULL );
1356 if (ret && ((bmp = GDI_GetObjPtr(ret, OBJ_BITMAP))))
1358 bmp->dib = dib;
1359 bmp->funcs = dc->funcs;
1360 /* create local copy of DIB palette */
1361 if (bpp <= 8) DIB_CopyColorTable( dc, bmp, usage, bmi );
1362 GDI_ReleaseObj( ret );
1364 if (dc->funcs->pCreateDIBSection)
1366 if (!dc->funcs->pCreateDIBSection(dc->physDev, ret, bmi, usage))
1368 DeleteObject( ret );
1369 ret = 0;
1374 release_dc_ptr( dc );
1375 if (bDesktopDC) DeleteDC( hdc );
1376 if (ret && bits) *bits = dib->dsBm.bmBits;
1377 return ret;
1379 error:
1380 if (bDesktopDC) DeleteDC( hdc );
1381 if (section) UnmapViewOfFile( mapBits );
1382 else if (!offset) VirtualFree( dib->dsBm.bmBits, 0, MEM_RELEASE );
1383 HeapFree( GetProcessHeap(), 0, dib );
1384 return 0;