kernel32/tests: Fix a signed/unsigned int mismatch.
[wine/wine-kai.git] / dlls / gdi32 / dib.c
blob86e13080e132044da42a3c1a6ee3180d284c73df
1 /*
2 * GDI device-independent bitmaps
4 * Copyright 1993,1994 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 Important information:
24 * Current Windows versions support two different DIB structures:
26 - BITMAPCOREINFO / BITMAPCOREHEADER (legacy structures; used in OS/2)
27 - BITMAPINFO / BITMAPINFOHEADER
29 Most Windows API functions taking a BITMAPINFO* / BITMAPINFOHEADER* also
30 accept the old "core" structures, and so must WINE.
31 You can distinguish them by looking at the first member (bcSize/biSize),
32 or use the internal function DIB_GetBitmapInfo.
35 * The palettes are stored in different formats:
37 - BITMAPCOREINFO: Array of RGBTRIPLE
38 - BITMAPINFO: Array of RGBQUAD
41 * There are even more DIB headers, but they all extend BITMAPINFOHEADER:
43 - BITMAPV4HEADER: Introduced in Windows 95 / NT 4.0
44 - BITMAPV5HEADER: Introduced in Windows 98 / 2000
46 If biCompression is BI_BITFIELDS, the color masks are at the same position
47 in all the headers (they start at bmiColors of BITMAPINFOHEADER), because
48 the new headers have structure members for the masks.
51 * You should never access the color table using the bmiColors member,
52 because the passed structure may have one of the extended headers
53 mentioned above. Use this to calculate the location:
55 BITMAPINFO* info;
56 void* colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
59 * More information:
60 Search for "Bitmap Structures" in MSDN
63 #include <stdarg.h>
64 #include <stdlib.h>
65 #include <string.h>
67 #include "windef.h"
68 #include "winbase.h"
69 #include "wownt32.h"
70 #include "gdi_private.h"
71 #include "wine/debug.h"
73 WINE_DEFAULT_DEBUG_CHANNEL(bitmap);
77 Some of the following helper functions are duplicated in
78 dlls/x11drv/dib.c
81 /***********************************************************************
82 * DIB_GetDIBWidthBytes
84 * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
85 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/bitmaps_87eb.asp
87 int DIB_GetDIBWidthBytes( int width, int depth )
89 int words;
91 switch(depth)
93 case 1: words = (width + 31) / 32; break;
94 case 4: words = (width + 7) / 8; break;
95 case 8: words = (width + 3) / 4; break;
96 case 15:
97 case 16: words = (width + 1) / 2; break;
98 case 24: words = (width * 3 + 3)/4; break;
100 default:
101 WARN("(%d): Unsupported depth\n", depth );
102 /* fall through */
103 case 32:
104 words = width;
106 return 4 * words;
109 /***********************************************************************
110 * DIB_GetDIBImageBytes
112 * Return the number of bytes used to hold the image in a DIB bitmap.
114 int DIB_GetDIBImageBytes( int width, int height, int depth )
116 return DIB_GetDIBWidthBytes( width, depth ) * abs( height );
120 /***********************************************************************
121 * DIB_BitmapInfoSize
123 * Return the size of the bitmap info structure including color table.
125 int DIB_BitmapInfoSize( const BITMAPINFO * info, WORD coloruse )
127 int colors;
129 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
131 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
132 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
133 return sizeof(BITMAPCOREHEADER) + colors *
134 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
136 else /* assume BITMAPINFOHEADER */
138 colors = info->bmiHeader.biClrUsed;
139 if (colors > 256) colors = 256;
140 if (!colors && (info->bmiHeader.biBitCount <= 8))
141 colors = 1 << info->bmiHeader.biBitCount;
142 return sizeof(BITMAPINFOHEADER) + colors *
143 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
148 /***********************************************************************
149 * DIB_GetBitmapInfo
151 * Get the info from a bitmap header.
152 * Return 1 for INFOHEADER, 0 for COREHEADER,
153 * 4 for V4HEADER, 5 for V5HEADER, -1 for error.
155 static int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
156 LONG *height, WORD *planes, WORD *bpp, DWORD *compr, DWORD *size )
158 if (header->biSize == sizeof(BITMAPINFOHEADER))
160 *width = header->biWidth;
161 *height = header->biHeight;
162 *planes = header->biPlanes;
163 *bpp = header->biBitCount;
164 *compr = header->biCompression;
165 *size = header->biSizeImage;
166 return 1;
168 if (header->biSize == sizeof(BITMAPCOREHEADER))
170 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)header;
171 *width = core->bcWidth;
172 *height = core->bcHeight;
173 *planes = core->bcPlanes;
174 *bpp = core->bcBitCount;
175 *compr = 0;
176 *size = 0;
177 return 0;
179 if (header->biSize == sizeof(BITMAPV4HEADER))
181 const BITMAPV4HEADER *v4hdr = (const BITMAPV4HEADER *)header;
182 *width = v4hdr->bV4Width;
183 *height = v4hdr->bV4Height;
184 *planes = v4hdr->bV4Planes;
185 *bpp = v4hdr->bV4BitCount;
186 *compr = v4hdr->bV4V4Compression;
187 *size = v4hdr->bV4SizeImage;
188 return 4;
190 if (header->biSize == sizeof(BITMAPV5HEADER))
192 const BITMAPV5HEADER *v5hdr = (const BITMAPV5HEADER *)header;
193 *width = v5hdr->bV5Width;
194 *height = v5hdr->bV5Height;
195 *planes = v5hdr->bV5Planes;
196 *bpp = v5hdr->bV5BitCount;
197 *compr = v5hdr->bV5Compression;
198 *size = v5hdr->bV5SizeImage;
199 return 5;
201 ERR("(%d): unknown/wrong size for header\n", header->biSize );
202 return -1;
206 /***********************************************************************
207 * StretchDIBits (GDI32.@)
209 INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst,
210 INT heightDst, INT xSrc, INT ySrc, INT widthSrc,
211 INT heightSrc, const void *bits,
212 const BITMAPINFO *info, UINT wUsage, DWORD dwRop )
214 DC *dc;
216 if (!bits || !info)
217 return 0;
219 dc = DC_GetDCUpdate( hdc );
220 if(!dc) return FALSE;
222 if(dc->funcs->pStretchDIBits)
224 heightSrc = dc->funcs->pStretchDIBits(dc->physDev, xDst, yDst, widthDst,
225 heightDst, xSrc, ySrc, widthSrc,
226 heightSrc, bits, info, wUsage, dwRop);
227 GDI_ReleaseObj( hdc );
229 else /* use StretchBlt */
231 HBITMAP hBitmap, hOldBitmap;
232 HPALETTE hpal = NULL;
233 HDC hdcMem;
234 LONG height;
235 LONG width;
236 WORD planes, bpp;
237 DWORD compr, size;
239 GDI_ReleaseObj( hdc );
241 if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size ) == -1)
243 ERR("Invalid bitmap\n");
244 return 0;
247 if (width < 0)
249 ERR("Bitmap has a negative width\n");
250 return 0;
253 hdcMem = CreateCompatibleDC( hdc );
254 hBitmap = CreateCompatibleBitmap(hdc, width, height);
255 hOldBitmap = SelectObject( hdcMem, hBitmap );
256 if(wUsage == DIB_PAL_COLORS)
258 hpal = GetCurrentObject(hdc, OBJ_PAL);
259 hpal = SelectPalette(hdcMem, hpal, FALSE);
262 if (info->bmiHeader.biCompression == BI_RLE4 ||
263 info->bmiHeader.biCompression == BI_RLE8) {
265 /* when RLE compression is used, there may be some gaps (ie the DIB doesn't
266 * contain all the rectangle described in bmiHeader, but only part of it.
267 * This mean that those undescribed pixels must be left untouched.
268 * So, we first copy on a memory bitmap the current content of the
269 * destination rectangle, blit the DIB bits on top of it - hence leaving
270 * the gaps untouched -, and blitting the rectangle back.
271 * This insure that gaps are untouched on the destination rectangle
272 * Not doing so leads to trashed images (the gaps contain what was on the
273 * memory bitmap => generally black or garbage)
274 * Unfortunately, RLE DIBs without gaps will be slowed down. But this is
275 * another speed vs correctness issue. Anyway, if speed is needed, then the
276 * pStretchDIBits function shall be implemented.
277 * ericP (2000/09/09)
280 /* copy existing bitmap from destination dc */
281 StretchBlt( hdcMem, xSrc, abs(height) - heightSrc - ySrc,
282 widthSrc, heightSrc, hdc, xDst, yDst, widthDst, heightDst,
283 dwRop );
286 SetDIBits(hdcMem, hBitmap, 0, height, bits, info, wUsage);
288 /* Origin for DIBitmap may be bottom left (positive biHeight) or top
289 left (negative biHeight) */
290 StretchBlt( hdc, xDst, yDst, widthDst, heightDst,
291 hdcMem, xSrc, abs(height) - heightSrc - ySrc,
292 widthSrc, heightSrc, dwRop );
293 if(hpal)
294 SelectPalette(hdcMem, hpal, FALSE);
295 SelectObject( hdcMem, hOldBitmap );
296 DeleteDC( hdcMem );
297 DeleteObject( hBitmap );
299 return heightSrc;
303 /******************************************************************************
304 * SetDIBits [GDI32.@]
306 * Sets pixels in a bitmap using colors from DIB.
308 * PARAMS
309 * hdc [I] Handle to device context
310 * hbitmap [I] Handle to bitmap
311 * startscan [I] Starting scan line
312 * lines [I] Number of scan lines
313 * bits [I] Array of bitmap bits
314 * info [I] Address of structure with data
315 * coloruse [I] Type of color indexes to use
317 * RETURNS
318 * Success: Number of scan lines copied
319 * Failure: 0
321 INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
322 UINT lines, LPCVOID bits, const BITMAPINFO *info,
323 UINT coloruse )
325 DC *dc;
326 BITMAPOBJ *bitmap;
327 INT result = 0;
329 if (!(dc = DC_GetDCUpdate( hdc )))
331 if (coloruse == DIB_RGB_COLORS) FIXME( "shouldn't require a DC for DIB_RGB_COLORS\n" );
332 return 0;
335 if (!(bitmap = GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
337 GDI_ReleaseObj( hdc );
338 return 0;
341 if (!bitmap->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) goto done;
343 if (bitmap->funcs && bitmap->funcs->pSetDIBits)
344 result = bitmap->funcs->pSetDIBits( dc->physDev, hbitmap, startscan, lines,
345 bits, info, coloruse );
346 else
347 result = lines;
349 done:
350 GDI_ReleaseObj( hbitmap );
351 GDI_ReleaseObj( hdc );
352 return result;
356 /***********************************************************************
357 * SetDIBitsToDevice (GDI32.@)
359 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
360 DWORD cy, INT xSrc, INT ySrc, UINT startscan,
361 UINT lines, LPCVOID bits, const BITMAPINFO *info,
362 UINT coloruse )
364 INT ret;
365 DC *dc;
367 if (!bits) return 0;
369 if (!(dc = DC_GetDCUpdate( hdc ))) return 0;
371 if(dc->funcs->pSetDIBitsToDevice)
372 ret = dc->funcs->pSetDIBitsToDevice( dc->physDev, xDest, yDest, cx, cy, xSrc,
373 ySrc, startscan, lines, bits,
374 info, coloruse );
375 else {
376 FIXME("unimplemented on hdc %p\n", hdc);
377 ret = 0;
380 GDI_ReleaseObj( hdc );
381 return ret;
384 /***********************************************************************
385 * SetDIBColorTable (GDI32.@)
387 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, CONST RGBQUAD *colors )
389 DC * dc;
390 UINT result = 0;
391 BITMAPOBJ * bitmap;
393 if (!(dc = DC_GetDCPtr( hdc ))) return 0;
395 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, BITMAP_MAGIC )))
397 /* Check if currently selected bitmap is a DIB */
398 if (bitmap->color_table)
400 if (startpos < bitmap->nb_colors)
402 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
403 memcpy(bitmap->color_table + startpos, colors, entries * sizeof(RGBQUAD));
404 result = entries;
407 GDI_ReleaseObj( dc->hBitmap );
410 if (dc->funcs->pSetDIBColorTable)
411 dc->funcs->pSetDIBColorTable(dc->physDev, startpos, entries, colors);
413 GDI_ReleaseObj( hdc );
414 return result;
418 /***********************************************************************
419 * GetDIBColorTable (GDI32.@)
421 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
423 DC * dc;
424 UINT result = 0;
426 if (!(dc = DC_GetDCPtr( hdc ))) return 0;
428 if (dc->funcs->pGetDIBColorTable)
429 result = dc->funcs->pGetDIBColorTable(dc->physDev, startpos, entries, colors);
430 else
432 BITMAPOBJ *bitmap = GDI_GetObjPtr( dc->hBitmap, BITMAP_MAGIC );
433 if (bitmap)
435 /* Check if currently selected bitmap is a DIB */
436 if (bitmap->color_table)
438 if (startpos < bitmap->nb_colors)
440 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
441 memcpy(colors, bitmap->color_table + startpos, entries * sizeof(RGBQUAD));
442 result = entries;
445 GDI_ReleaseObj( dc->hBitmap );
448 GDI_ReleaseObj( hdc );
449 return result;
452 /* FIXME the following two structs should be combined with __sysPalTemplate in
453 objects/color.c - this should happen after de-X11-ing both of these
454 files.
455 NB. RGBQUAD and PALETTEENTRY have different orderings of red, green
456 and blue - sigh */
458 static const RGBQUAD EGAColorsQuads[16] = {
459 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
460 { 0x00, 0x00, 0x00, 0x00 },
461 { 0x00, 0x00, 0x80, 0x00 },
462 { 0x00, 0x80, 0x00, 0x00 },
463 { 0x00, 0x80, 0x80, 0x00 },
464 { 0x80, 0x00, 0x00, 0x00 },
465 { 0x80, 0x00, 0x80, 0x00 },
466 { 0x80, 0x80, 0x00, 0x00 },
467 { 0x80, 0x80, 0x80, 0x00 },
468 { 0xc0, 0xc0, 0xc0, 0x00 },
469 { 0x00, 0x00, 0xff, 0x00 },
470 { 0x00, 0xff, 0x00, 0x00 },
471 { 0x00, 0xff, 0xff, 0x00 },
472 { 0xff, 0x00, 0x00, 0x00 },
473 { 0xff, 0x00, 0xff, 0x00 },
474 { 0xff, 0xff, 0x00, 0x00 },
475 { 0xff, 0xff, 0xff, 0x00 }
478 static const RGBTRIPLE EGAColorsTriples[16] = {
479 /* rgbBlue, rgbGreen, rgbRed */
480 { 0x00, 0x00, 0x00 },
481 { 0x00, 0x00, 0x80 },
482 { 0x00, 0x80, 0x00 },
483 { 0x00, 0x80, 0x80 },
484 { 0x80, 0x00, 0x00 },
485 { 0x80, 0x00, 0x80 },
486 { 0x80, 0x80, 0x00 },
487 { 0x80, 0x80, 0x80 },
488 { 0xc0, 0xc0, 0xc0 },
489 { 0x00, 0x00, 0xff },
490 { 0x00, 0xff, 0x00 },
491 { 0x00, 0xff, 0xff },
492 { 0xff, 0x00, 0x00 } ,
493 { 0xff, 0x00, 0xff },
494 { 0xff, 0xff, 0x00 },
495 { 0xff, 0xff, 0xff }
498 static const RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
499 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
500 { 0x00, 0x00, 0x00, 0x00 },
501 { 0x00, 0x00, 0x80, 0x00 },
502 { 0x00, 0x80, 0x00, 0x00 },
503 { 0x00, 0x80, 0x80, 0x00 },
504 { 0x80, 0x00, 0x00, 0x00 },
505 { 0x80, 0x00, 0x80, 0x00 },
506 { 0x80, 0x80, 0x00, 0x00 },
507 { 0xc0, 0xc0, 0xc0, 0x00 },
508 { 0xc0, 0xdc, 0xc0, 0x00 },
509 { 0xf0, 0xca, 0xa6, 0x00 },
510 { 0xf0, 0xfb, 0xff, 0x00 },
511 { 0xa4, 0xa0, 0xa0, 0x00 },
512 { 0x80, 0x80, 0x80, 0x00 },
513 { 0x00, 0x00, 0xf0, 0x00 },
514 { 0x00, 0xff, 0x00, 0x00 },
515 { 0x00, 0xff, 0xff, 0x00 },
516 { 0xff, 0x00, 0x00, 0x00 },
517 { 0xff, 0x00, 0xff, 0x00 },
518 { 0xff, 0xff, 0x00, 0x00 },
519 { 0xff, 0xff, 0xff, 0x00 }
522 static const RGBTRIPLE DefLogPaletteTriples[20] = { /* Copy of Default Logical Palette */
523 /* rgbBlue, rgbGreen, rgbRed */
524 { 0x00, 0x00, 0x00 },
525 { 0x00, 0x00, 0x80 },
526 { 0x00, 0x80, 0x00 },
527 { 0x00, 0x80, 0x80 },
528 { 0x80, 0x00, 0x00 },
529 { 0x80, 0x00, 0x80 },
530 { 0x80, 0x80, 0x00 },
531 { 0xc0, 0xc0, 0xc0 },
532 { 0xc0, 0xdc, 0xc0 },
533 { 0xf0, 0xca, 0xa6 },
534 { 0xf0, 0xfb, 0xff },
535 { 0xa4, 0xa0, 0xa0 },
536 { 0x80, 0x80, 0x80 },
537 { 0x00, 0x00, 0xf0 },
538 { 0x00, 0xff, 0x00 },
539 { 0x00, 0xff, 0xff },
540 { 0xff, 0x00, 0x00 },
541 { 0xff, 0x00, 0xff },
542 { 0xff, 0xff, 0x00 },
543 { 0xff, 0xff, 0xff}
547 /******************************************************************************
548 * GetDIBits [GDI32.@]
550 * Retrieves bits of bitmap and copies to buffer.
552 * RETURNS
553 * Success: Number of scan lines copied from bitmap
554 * Failure: 0
556 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/bitmaps_87eb.asp
558 INT WINAPI GetDIBits(
559 HDC hdc, /* [in] Handle to device context */
560 HBITMAP hbitmap, /* [in] Handle to bitmap */
561 UINT startscan, /* [in] First scan line to set in dest bitmap */
562 UINT lines, /* [in] Number of scan lines to copy */
563 LPVOID bits, /* [out] Address of array for bitmap bits */
564 BITMAPINFO * info, /* [out] Address of structure with bitmap data */
565 UINT coloruse) /* [in] RGB or palette index */
567 DC * dc;
568 BITMAPOBJ * bmp;
569 int i;
570 int bitmap_type;
571 BOOL core_header;
572 LONG width;
573 LONG height;
574 WORD planes, bpp;
575 DWORD compr, size;
576 void* colorPtr;
577 RGBTRIPLE* rgbTriples;
578 RGBQUAD* rgbQuads;
580 if (!info) return 0;
582 bitmap_type = DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size);
583 if (bitmap_type == -1)
585 ERR("Invalid bitmap format\n");
586 return 0;
588 core_header = (bitmap_type == 0);
589 if (!(dc = DC_GetDCUpdate( hdc )))
591 SetLastError( ERROR_INVALID_PARAMETER );
592 return 0;
594 if (!(bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
596 GDI_ReleaseObj( hdc );
597 return 0;
600 colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
601 rgbTriples = (RGBTRIPLE *) colorPtr;
602 rgbQuads = (RGBQUAD *) colorPtr;
604 /* Transfer color info */
606 if (bpp <= 8 && bpp > 0)
608 if (!core_header) info->bmiHeader.biClrUsed = 0;
610 /* If the bitmap object already has a dib section at the
611 same color depth then get the color map from it */
612 if (bmp->dib && bmp->dib->dsBm.bmBitsPixel == bpp) {
613 if(coloruse == DIB_RGB_COLORS) {
614 unsigned int colors = min( bmp->nb_colors, 1 << bpp );
616 if (core_header)
618 /* Convert the color table (RGBQUAD to RGBTRIPLE) */
619 RGBTRIPLE* index = rgbTriples;
621 for (i=0; i < colors; i++, index++)
623 index->rgbtRed = bmp->color_table[i].rgbRed;
624 index->rgbtGreen = bmp->color_table[i].rgbGreen;
625 index->rgbtBlue = bmp->color_table[i].rgbBlue;
628 else
630 if (colors != 1 << bpp) info->bmiHeader.biClrUsed = colors;
631 memcpy(colorPtr, bmp->color_table, colors * sizeof(RGBQUAD));
634 else {
635 WORD *index = colorPtr;
636 for(i = 0; i < 1 << info->bmiHeader.biBitCount; i++, index++)
637 *index = i;
640 else {
641 if(bpp >= bmp->bitmap.bmBitsPixel) {
642 /* Generate the color map from the selected palette */
643 PALETTEENTRY palEntry[256];
645 memset( palEntry, 0, sizeof(palEntry) );
646 if (!GetPaletteEntries( dc->hPalette, 0, 1 << bmp->bitmap.bmBitsPixel, palEntry ))
648 GDI_ReleaseObj( hdc );
649 GDI_ReleaseObj( hbitmap );
650 return 0;
652 for (i = 0; i < (1 << bmp->bitmap.bmBitsPixel); i++) {
653 if (coloruse == DIB_RGB_COLORS) {
654 if (core_header)
656 rgbTriples[i].rgbtRed = palEntry[i].peRed;
657 rgbTriples[i].rgbtGreen = palEntry[i].peGreen;
658 rgbTriples[i].rgbtBlue = palEntry[i].peBlue;
660 else
662 rgbQuads[i].rgbRed = palEntry[i].peRed;
663 rgbQuads[i].rgbGreen = palEntry[i].peGreen;
664 rgbQuads[i].rgbBlue = palEntry[i].peBlue;
665 rgbQuads[i].rgbReserved = 0;
668 else ((WORD *)colorPtr)[i] = (WORD)i;
670 } else {
671 switch (bpp) {
672 case 1:
673 if (core_header)
675 rgbTriples[0].rgbtRed = rgbTriples[0].rgbtGreen =
676 rgbTriples[0].rgbtBlue = 0;
677 rgbTriples[1].rgbtRed = rgbTriples[1].rgbtGreen =
678 rgbTriples[1].rgbtBlue = 0xff;
680 else
682 rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen =
683 rgbQuads[0].rgbBlue = 0;
684 rgbQuads[0].rgbReserved = 0;
685 rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen =
686 rgbQuads[1].rgbBlue = 0xff;
687 rgbQuads[1].rgbReserved = 0;
689 break;
691 case 4:
692 if (core_header)
693 memcpy(colorPtr, EGAColorsTriples, sizeof(EGAColorsTriples));
694 else
695 memcpy(colorPtr, EGAColorsQuads, sizeof(EGAColorsQuads));
697 break;
699 case 8:
701 if (core_header)
703 INT r, g, b;
704 RGBTRIPLE *color;
706 memcpy(rgbTriples, DefLogPaletteTriples,
707 10 * sizeof(RGBTRIPLE));
708 memcpy(rgbTriples + 246, DefLogPaletteTriples + 10,
709 10 * sizeof(RGBTRIPLE));
710 color = rgbTriples + 10;
711 for(r = 0; r <= 5; r++) /* FIXME */
712 for(g = 0; g <= 5; g++)
713 for(b = 0; b <= 5; b++) {
714 color->rgbtRed = (r * 0xff) / 5;
715 color->rgbtGreen = (g * 0xff) / 5;
716 color->rgbtBlue = (b * 0xff) / 5;
717 color++;
720 else
722 INT r, g, b;
723 RGBQUAD *color;
725 memcpy(rgbQuads, DefLogPaletteQuads,
726 10 * sizeof(RGBQUAD));
727 memcpy(rgbQuads + 246, DefLogPaletteQuads + 10,
728 10 * sizeof(RGBQUAD));
729 color = rgbQuads + 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->rgbRed = (r * 0xff) / 5;
734 color->rgbGreen = (g * 0xff) / 5;
735 color->rgbBlue = (b * 0xff) / 5;
736 color->rgbReserved = 0;
737 color++;
746 if (bits && lines)
748 /* If the bitmap object already have a dib section that contains image data, get the bits from it */
749 if(bmp->dib && bmp->dib->dsBm.bmBitsPixel >= 15 && bpp >= 15)
751 /*FIXME: Only RGB dibs supported for now */
752 unsigned int srcwidth = bmp->dib->dsBm.bmWidth, srcwidthb = bmp->dib->dsBm.bmWidthBytes;
753 unsigned int dstwidth = width;
754 int dstwidthb = DIB_GetDIBWidthBytes( width, bpp );
755 LPBYTE dbits = bits, sbits = (LPBYTE) bmp->dib->dsBm.bmBits + (startscan * srcwidthb);
756 unsigned int x, y, width, widthb;
758 if ((height < 0) ^ (bmp->dib->dsBmih.biHeight < 0))
760 dbits = (LPBYTE)bits + (dstwidthb * (lines-1));
761 dstwidthb = -dstwidthb;
764 switch( bpp ) {
766 case 15:
767 case 16: /* 16 bpp dstDIB */
769 LPWORD dstbits = (LPWORD)dbits;
770 WORD rmask = 0x7c00, gmask= 0x03e0, bmask = 0x001f;
772 /* FIXME: BI_BITFIELDS not supported yet */
774 switch(bmp->dib->dsBm.bmBitsPixel) {
776 case 16: /* 16 bpp srcDIB -> 16 bpp dstDIB */
778 widthb = min(srcwidthb, abs(dstwidthb));
779 /* FIXME: BI_BITFIELDS not supported yet */
780 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
781 memcpy(dbits, sbits, widthb);
783 break;
785 case 24: /* 24 bpp srcDIB -> 16 bpp dstDIB */
787 LPBYTE srcbits = sbits;
789 width = min(srcwidth, dstwidth);
790 for( y = 0; y < lines; y++) {
791 for( x = 0; x < width; x++, srcbits += 3)
792 *dstbits++ = ((srcbits[0] >> 3) & bmask) |
793 (((WORD)srcbits[1] << 2) & gmask) |
794 (((WORD)srcbits[2] << 7) & rmask);
796 dstbits = (LPWORD)(dbits+=dstwidthb);
797 srcbits = (sbits += srcwidthb);
800 break;
802 case 32: /* 32 bpp srcDIB -> 16 bpp dstDIB */
804 LPDWORD srcbits = (LPDWORD)sbits;
805 DWORD val;
807 width = min(srcwidth, dstwidth);
808 for( y = 0; y < lines; y++) {
809 for( x = 0; x < width; x++ ) {
810 val = *srcbits++;
811 *dstbits++ = (WORD)(((val >> 3) & bmask) | ((val >> 6) & gmask) |
812 ((val >> 9) & rmask));
814 dstbits = (LPWORD)(dbits+=dstwidthb);
815 srcbits = (LPDWORD)(sbits+=srcwidthb);
818 break;
820 default: /* ? bit bmp -> 16 bit DIB */
821 FIXME("15/16 bit DIB %d bit bitmap\n",
822 bmp->bitmap.bmBitsPixel);
823 break;
826 break;
828 case 24: /* 24 bpp dstDIB */
830 LPBYTE dstbits = dbits;
832 switch(bmp->dib->dsBm.bmBitsPixel) {
834 case 16: /* 16 bpp srcDIB -> 24 bpp dstDIB */
836 LPWORD srcbits = (LPWORD)sbits;
837 WORD val;
839 width = min(srcwidth, dstwidth);
840 /* FIXME: BI_BITFIELDS not supported yet */
841 for( y = 0; y < lines; y++) {
842 for( x = 0; x < width; x++ ) {
843 val = *srcbits++;
844 *dstbits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07));
845 *dstbits++ = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07));
846 *dstbits++ = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07));
848 dstbits = (LPBYTE)(dbits+=dstwidthb);
849 srcbits = (LPWORD)(sbits+=srcwidthb);
852 break;
854 case 24: /* 24 bpp srcDIB -> 24 bpp dstDIB */
856 widthb = min(srcwidthb, abs(dstwidthb));
857 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
858 memcpy(dbits, sbits, widthb);
860 break;
862 case 32: /* 32 bpp srcDIB -> 24 bpp dstDIB */
864 LPBYTE srcbits = (LPBYTE)sbits;
866 width = min(srcwidth, dstwidth);
867 for( y = 0; y < lines; y++) {
868 for( x = 0; x < width; x++, srcbits++ ) {
869 *dstbits++ = *srcbits++;
870 *dstbits++ = *srcbits++;
871 *dstbits++ = *srcbits++;
873 dstbits=(LPBYTE)(dbits+=dstwidthb);
874 srcbits = (LPBYTE)(sbits+=srcwidthb);
877 break;
879 default: /* ? bit bmp -> 24 bit DIB */
880 FIXME("24 bit DIB %d bit bitmap\n",
881 bmp->bitmap.bmBitsPixel);
882 break;
885 break;
887 case 32: /* 32 bpp dstDIB */
889 LPDWORD dstbits = (LPDWORD)dbits;
891 /* FIXME: BI_BITFIELDS not supported yet */
893 switch(bmp->dib->dsBm.bmBitsPixel) {
894 case 16: /* 16 bpp srcDIB -> 32 bpp dstDIB */
896 LPWORD srcbits = (LPWORD)sbits;
897 DWORD val;
899 width = min(srcwidth, dstwidth);
900 /* FIXME: BI_BITFIELDS not supported yet */
901 for( y = 0; y < lines; y++) {
902 for( x = 0; x < width; x++ ) {
903 val = (DWORD)*srcbits++;
904 *dstbits++ = ((val << 3) & 0xf8) | ((val >> 2) & 0x07) |
905 ((val << 6) & 0xf800) | ((val << 1) & 0x0700) |
906 ((val << 9) & 0xf80000) | ((val << 4) & 0x070000);
908 dstbits=(LPDWORD)(dbits+=dstwidthb);
909 srcbits=(LPWORD)(sbits+=srcwidthb);
912 break;
914 case 24: /* 24 bpp srcDIB -> 32 bpp dstDIB */
916 LPBYTE srcbits = sbits;
918 width = min(srcwidth, dstwidth);
919 for( y = 0; y < lines; y++) {
920 for( x = 0; x < width; x++, srcbits+=3 )
921 *dstbits++ = srcbits[0] |
922 (srcbits[1] << 8) |
923 (srcbits[2] << 16);
924 dstbits=(LPDWORD)(dbits+=dstwidthb);
925 srcbits=(sbits+=srcwidthb);
928 break;
930 case 32: /* 32 bpp srcDIB -> 32 bpp dstDIB */
932 widthb = min(srcwidthb, abs(dstwidthb));
933 /* FIXME: BI_BITFIELDS not supported yet */
934 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb) {
935 memcpy(dbits, sbits, widthb);
938 break;
940 default: /* ? bit bmp -> 32 bit DIB */
941 FIXME("32 bit DIB %d bit bitmap\n",
942 bmp->bitmap.bmBitsPixel);
943 break;
946 break;
948 default: /* ? bit DIB */
949 FIXME("Unsupported DIB depth %d\n", info->bmiHeader.biBitCount);
950 break;
953 /* Otherwise, get bits from the XImage */
954 else
956 if (!bmp->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) lines = 0;
957 else
959 if (bmp->funcs && bmp->funcs->pGetDIBits)
960 lines = bmp->funcs->pGetDIBits( dc->physDev, hbitmap, startscan,
961 lines, bits, info, coloruse );
962 else
963 lines = 0; /* FIXME: should copy from bmp->bitmap.bmBits */
967 else
969 /* fill in struct members */
971 if (bpp == 0)
973 if (core_header)
975 BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) info;
976 coreheader->bcWidth = bmp->bitmap.bmWidth;
977 coreheader->bcHeight = bmp->bitmap.bmHeight;
978 coreheader->bcPlanes = 1;
979 coreheader->bcBitCount = bmp->bitmap.bmBitsPixel;
981 else
983 info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
984 info->bmiHeader.biHeight = bmp->bitmap.bmHeight;
985 info->bmiHeader.biPlanes = 1;
986 info->bmiHeader.biSizeImage =
987 DIB_GetDIBImageBytes( bmp->bitmap.bmWidth,
988 bmp->bitmap.bmHeight,
989 bmp->bitmap.bmBitsPixel );
990 switch(bmp->bitmap.bmBitsPixel)
992 case 15:
993 info->bmiHeader.biBitCount = 16;
994 info->bmiHeader.biCompression = BI_RGB;
995 break;
997 case 16:
998 info->bmiHeader.biBitCount = 16;
999 info->bmiHeader.biCompression = BI_BITFIELDS;
1000 ((PDWORD)info->bmiColors)[0] = 0xf800;
1001 ((PDWORD)info->bmiColors)[1] = 0x07e0;
1002 ((PDWORD)info->bmiColors)[2] = 0x001f;
1003 break;
1005 default:
1006 info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
1007 info->bmiHeader.biCompression = BI_RGB;
1008 break;
1010 info->bmiHeader.biXPelsPerMeter = 0;
1011 info->bmiHeader.biYPelsPerMeter = 0;
1012 info->bmiHeader.biClrUsed = 0;
1013 info->bmiHeader.biClrImportant = 0;
1015 /* Windows 2000 doesn't touch the additional struct members if
1016 it's a BITMAPV4HEADER or a BITMAPV5HEADER */
1018 lines = abs(bmp->bitmap.bmHeight);
1020 else
1022 /* The knowledge base article Q81498 ("DIBs and Their Uses") states that
1023 if bits == NULL and bpp != 0, only biSizeImage and the color table are
1024 filled in. */
1025 if (!core_header)
1027 /* FIXME: biSizeImage should be calculated according to the selected
1028 compression algorithm if biCompression != BI_RGB */
1029 info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes( width, height, bpp );
1031 lines = abs(height);
1035 if (!core_header)
1037 TRACE("biSizeImage = %d, ", info->bmiHeader.biSizeImage);
1039 TRACE("biWidth = %d, biHeight = %d\n", width, height);
1041 GDI_ReleaseObj( hdc );
1042 GDI_ReleaseObj( hbitmap );
1043 return lines;
1047 /***********************************************************************
1048 * CreateDIBitmap (GDI32.@)
1050 * Creates a DDB (device dependent bitmap) from a DIB.
1051 * The DDB will have the same color depth as the reference DC.
1053 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
1054 DWORD init, LPCVOID bits, const BITMAPINFO *data,
1055 UINT coloruse )
1057 HBITMAP handle;
1058 LONG width;
1059 LONG height;
1060 WORD planes, bpp;
1061 DWORD compr, size;
1062 DC *dc;
1064 if (DIB_GetBitmapInfo( header, &width, &height, &planes, &bpp, &compr, &size ) == -1) return 0;
1066 if (width < 0)
1068 TRACE("Bitmap has a negative width\n");
1069 return 0;
1072 /* Top-down DIBs have a negative height */
1073 if (height < 0) height = -height;
1075 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1076 hdc, header, init, bits, data, coloruse, width, height, bpp, compr);
1078 if (hdc == NULL)
1079 handle = CreateBitmap( width, height, 1, 1, NULL );
1080 else
1081 handle = CreateCompatibleBitmap( hdc, width, height );
1083 if (handle)
1085 if (init == CBM_INIT) SetDIBits( hdc, handle, 0, height, bits, data, coloruse );
1087 else if (hdc && ((dc = DC_GetDCPtr( hdc )) != NULL) )
1089 if (!BITMAP_SetOwnerDC( handle, dc ))
1091 DeleteObject( handle );
1092 handle = 0;
1094 GDI_ReleaseObj( hdc );
1098 return handle;
1101 /***********************************************************************
1102 * CreateDIBSection (GDI.489)
1104 HBITMAP16 WINAPI CreateDIBSection16 (HDC16 hdc, const BITMAPINFO *bmi, UINT16 usage,
1105 SEGPTR *bits16, HANDLE section, DWORD offset)
1107 LPVOID bits32;
1108 HBITMAP hbitmap;
1110 hbitmap = CreateDIBSection( HDC_32(hdc), bmi, usage, &bits32, section, offset );
1111 if (hbitmap)
1113 BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr(hbitmap, BITMAP_MAGIC);
1114 if (bmp && bmp->dib && bits32)
1116 const BITMAPINFOHEADER *bi = &bmi->bmiHeader;
1117 LONG width, height;
1118 WORD planes, bpp;
1119 DWORD compr, size;
1120 INT width_bytes;
1121 WORD count, sel;
1122 int i;
1124 DIB_GetBitmapInfo(bi, &width, &height, &planes, &bpp, &compr, &size);
1126 height = height >= 0 ? height : -height;
1127 width_bytes = DIB_GetDIBWidthBytes(width, bpp);
1129 if (!size || (compr != BI_RLE4 && compr != BI_RLE8)) size = width_bytes * height;
1131 /* calculate number of sel's needed for size with 64K steps */
1132 count = (size + 0xffff) / 0x10000;
1133 sel = AllocSelectorArray16(count);
1135 for (i = 0; i < count; i++)
1137 SetSelectorBase(sel + (i << __AHSHIFT), (DWORD)bits32 + i * 0x10000);
1138 SetSelectorLimit16(sel + (i << __AHSHIFT), size - 1); /* yep, limit is correct */
1139 size -= 0x10000;
1141 bmp->segptr_bits = MAKESEGPTR( sel, 0 );
1142 if (bits16) *bits16 = bmp->segptr_bits;
1144 if (bmp) GDI_ReleaseObj( hbitmap );
1146 return HBITMAP_16(hbitmap);
1149 /* Copy/synthetize RGB palette from BITMAPINFO. Ripped from dlls/winex11.drv/dib.c */
1150 static void DIB_CopyColorTable( DC *dc, BITMAPOBJ *bmp, WORD coloruse, const BITMAPINFO *info )
1152 RGBQUAD *colorTable;
1153 unsigned int colors;
1154 int i;
1155 BOOL core_info = info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER);
1157 if (core_info)
1159 colors = 1 << ((const BITMAPCOREINFO*) info)->bmciHeader.bcBitCount;
1161 else
1163 colors = info->bmiHeader.biClrUsed;
1164 if (!colors) colors = 1 << info->bmiHeader.biBitCount;
1167 if (colors > 256) {
1168 ERR("called with >256 colors!\n");
1169 return;
1172 if (!(colorTable = HeapAlloc(GetProcessHeap(), 0, colors * sizeof(RGBQUAD) ))) return;
1174 if(coloruse == DIB_RGB_COLORS)
1176 if (core_info)
1178 /* Convert RGBTRIPLEs to RGBQUADs */
1179 for (i=0; i < colors; i++)
1181 colorTable[i].rgbRed = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtRed;
1182 colorTable[i].rgbGreen = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtGreen;
1183 colorTable[i].rgbBlue = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtBlue;
1184 colorTable[i].rgbReserved = 0;
1187 else
1189 memcpy(colorTable, (const BYTE*) info + (WORD) info->bmiHeader.biSize, colors * sizeof(RGBQUAD));
1192 else
1194 PALETTEENTRY entries[256];
1195 const WORD *index = (const WORD*) ((const BYTE*) info + (WORD) info->bmiHeader.biSize);
1196 UINT count = GetPaletteEntries( dc->hPalette, 0, colors, entries );
1198 for (i = 0; i < colors; i++, index++)
1200 PALETTEENTRY *entry = &entries[*index % count];
1201 colorTable[i].rgbRed = entry->peRed;
1202 colorTable[i].rgbGreen = entry->peGreen;
1203 colorTable[i].rgbBlue = entry->peBlue;
1204 colorTable[i].rgbReserved = 0;
1207 bmp->color_table = colorTable;
1208 bmp->nb_colors = colors;
1211 /***********************************************************************
1212 * CreateDIBSection (GDI32.@)
1214 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
1215 VOID **bits, HANDLE section, DWORD offset)
1217 HBITMAP ret = 0;
1218 DC *dc;
1219 BOOL bDesktopDC = FALSE;
1220 DIBSECTION *dib;
1221 BITMAPOBJ *bmp;
1222 int bitmap_type;
1223 LONG width, height;
1224 WORD planes, bpp;
1225 DWORD compression, sizeImage;
1226 void *mapBits = NULL;
1228 if (((bitmap_type = DIB_GetBitmapInfo( &bmi->bmiHeader, &width, &height,
1229 &planes, &bpp, &compression, &sizeImage )) == -1))
1230 return 0;
1232 if (compression != BI_RGB && compression != BI_BITFIELDS)
1234 TRACE("can't create a compressed (%u) dibsection\n", compression);
1235 return 0;
1238 if (!(dib = HeapAlloc( GetProcessHeap(), 0, sizeof(*dib) ))) return 0;
1240 TRACE("format (%d,%d), planes %d, bpp %d, size %d, %s\n",
1241 width, height, planes, bpp, sizeImage, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1243 dib->dsBm.bmType = 0;
1244 dib->dsBm.bmWidth = width;
1245 dib->dsBm.bmHeight = height >= 0 ? height : -height;
1246 dib->dsBm.bmWidthBytes = DIB_GetDIBWidthBytes(width, bpp);
1247 dib->dsBm.bmPlanes = planes;
1248 dib->dsBm.bmBitsPixel = bpp;
1249 dib->dsBm.bmBits = NULL;
1251 if (!bitmap_type) /* core header */
1253 /* convert the BITMAPCOREHEADER to a BITMAPINFOHEADER */
1254 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1255 dib->dsBmih.biWidth = width;
1256 dib->dsBmih.biHeight = height;
1257 dib->dsBmih.biPlanes = planes;
1258 dib->dsBmih.biBitCount = bpp;
1259 dib->dsBmih.biCompression = compression;
1260 dib->dsBmih.biXPelsPerMeter = 0;
1261 dib->dsBmih.biYPelsPerMeter = 0;
1262 dib->dsBmih.biClrUsed = 0;
1263 dib->dsBmih.biClrImportant = 0;
1265 else
1267 /* truncate extended bitmap headers (BITMAPV4HEADER etc.) */
1268 dib->dsBmih = bmi->bmiHeader;
1269 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1272 /* set number of entries in bmi.bmiColors table */
1273 if( bpp <= 8 )
1274 dib->dsBmih.biClrUsed = 1 << bpp;
1276 dib->dsBmih.biSizeImage = dib->dsBm.bmWidthBytes * dib->dsBm.bmHeight;
1278 /* set dsBitfields values */
1279 if (usage == DIB_PAL_COLORS || bpp <= 8)
1281 dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
1283 else switch( bpp )
1285 case 15:
1286 case 16:
1287 dib->dsBitfields[0] = (compression == BI_BITFIELDS) ? *(const DWORD *)bmi->bmiColors : 0x7c00;
1288 dib->dsBitfields[1] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 1) : 0x03e0;
1289 dib->dsBitfields[2] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 2) : 0x001f;
1290 break;
1291 case 24:
1292 case 32:
1293 dib->dsBitfields[0] = (compression == BI_BITFIELDS) ? *(const DWORD *)bmi->bmiColors : 0xff0000;
1294 dib->dsBitfields[1] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 1) : 0x00ff00;
1295 dib->dsBitfields[2] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 2) : 0x0000ff;
1296 break;
1299 /* get storage location for DIB bits */
1301 if (section)
1303 SYSTEM_INFO SystemInfo;
1304 DWORD mapOffset;
1305 INT mapSize;
1307 GetSystemInfo( &SystemInfo );
1308 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
1309 mapSize = dib->dsBmih.biSizeImage + (offset - mapOffset);
1310 mapBits = MapViewOfFile( section, FILE_MAP_ALL_ACCESS, 0, mapOffset, mapSize );
1311 if (mapBits) dib->dsBm.bmBits = (char *)mapBits + (offset - mapOffset);
1313 else
1315 offset = 0;
1316 dib->dsBm.bmBits = VirtualAlloc( NULL, dib->dsBmih.biSizeImage,
1317 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
1319 dib->dshSection = section;
1320 dib->dsOffset = offset;
1322 if (!dib->dsBm.bmBits)
1324 HeapFree( GetProcessHeap(), 0, dib );
1325 return 0;
1328 /* If the reference hdc is null, take the desktop dc */
1329 if (hdc == 0)
1331 hdc = CreateCompatibleDC(0);
1332 bDesktopDC = TRUE;
1335 if (!(dc = DC_GetDCPtr( hdc ))) goto error;
1337 /* create Device Dependent Bitmap and add DIB pointer */
1338 ret = CreateBitmap( dib->dsBm.bmWidth, dib->dsBm.bmHeight, 1,
1339 (bpp == 1) ? 1 : GetDeviceCaps(hdc, BITSPIXEL), NULL );
1341 if (ret && ((bmp = GDI_GetObjPtr(ret, BITMAP_MAGIC))))
1343 bmp->dib = dib;
1344 bmp->funcs = dc->funcs;
1345 /* create local copy of DIB palette */
1346 if (bpp <= 8) DIB_CopyColorTable( dc, bmp, usage, bmi );
1347 GDI_ReleaseObj( ret );
1349 if (dc->funcs->pCreateDIBSection)
1351 if (!dc->funcs->pCreateDIBSection(dc->physDev, ret, bmi, usage))
1353 DeleteObject( ret );
1354 ret = 0;
1359 GDI_ReleaseObj(hdc);
1360 if (bDesktopDC) DeleteDC( hdc );
1361 if (ret && bits) *bits = dib->dsBm.bmBits;
1362 return ret;
1364 error:
1365 if (bDesktopDC) DeleteDC( hdc );
1366 if (section) UnmapViewOfFile( mapBits );
1367 else if (!offset) VirtualFree( dib->dsBm.bmBits, 0, MEM_RELEASE );
1368 HeapFree( GetProcessHeap(), 0, dib );
1369 return 0;