push 6fe5edf8439c19d3885814583531c2f2b1495177
[wine/hacks.git] / dlls / gdi32 / dib.c
blobcaf3e6ca9abb91bb752396bbd949458dc492d442
1 /*
2 * GDI device-independent bitmaps
4 * Copyright 1993,1994 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 Important information:
24 * Current Windows versions support two different DIB structures:
26 - BITMAPCOREINFO / BITMAPCOREHEADER (legacy structures; used in OS/2)
27 - BITMAPINFO / BITMAPINFOHEADER
29 Most Windows API functions taking a BITMAPINFO* / BITMAPINFOHEADER* also
30 accept the old "core" structures, and so must WINE.
31 You can distinguish them by looking at the first member (bcSize/biSize),
32 or use the internal function DIB_GetBitmapInfo.
35 * The palettes are stored in different formats:
37 - BITMAPCOREINFO: Array of RGBTRIPLE
38 - BITMAPINFO: Array of RGBQUAD
41 * There are even more DIB headers, but they all extend BITMAPINFOHEADER:
43 - BITMAPV4HEADER: Introduced in Windows 95 / NT 4.0
44 - BITMAPV5HEADER: Introduced in Windows 98 / 2000
46 If biCompression is BI_BITFIELDS, the color masks are at the same position
47 in all the headers (they start at bmiColors of BITMAPINFOHEADER), because
48 the new headers have structure members for the masks.
51 * You should never access the color table using the bmiColors member,
52 because the passed structure may have one of the extended headers
53 mentioned above. Use this to calculate the location:
55 BITMAPINFO* info;
56 void* colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
59 * More information:
60 Search for "Bitmap Structures" in MSDN
63 #include <stdarg.h>
64 #include <stdlib.h>
65 #include <string.h>
67 #include "windef.h"
68 #include "winbase.h"
69 #include "wownt32.h"
70 #include "gdi_private.h"
71 #include "wine/debug.h"
73 WINE_DEFAULT_DEBUG_CHANNEL(bitmap);
77 Some of the following helper functions are duplicated in
78 dlls/x11drv/dib.c
81 /***********************************************************************
82 * DIB_GetDIBWidthBytes
84 * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
86 int DIB_GetDIBWidthBytes( int width, int depth )
88 int words;
90 switch(depth)
92 case 1: words = (width + 31) / 32; break;
93 case 4: words = (width + 7) / 8; break;
94 case 8: words = (width + 3) / 4; break;
95 case 15:
96 case 16: words = (width + 1) / 2; break;
97 case 24: words = (width * 3 + 3)/4; break;
99 default:
100 WARN("(%d): Unsupported depth\n", depth );
101 /* fall through */
102 case 32:
103 words = width;
105 return 4 * words;
108 /***********************************************************************
109 * DIB_GetDIBImageBytes
111 * Return the number of bytes used to hold the image in a DIB bitmap.
113 int DIB_GetDIBImageBytes( int width, int height, int depth )
115 return DIB_GetDIBWidthBytes( width, depth ) * abs( height );
119 /***********************************************************************
120 * DIB_BitmapInfoSize
122 * Return the size of the bitmap info structure including color table.
124 int DIB_BitmapInfoSize( const BITMAPINFO * info, WORD coloruse )
126 int colors;
128 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
130 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
131 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
132 return sizeof(BITMAPCOREHEADER) + colors *
133 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
135 else /* assume BITMAPINFOHEADER */
137 colors = info->bmiHeader.biClrUsed;
138 if (colors > 256) colors = 256;
139 if (!colors && (info->bmiHeader.biBitCount <= 8))
140 colors = 1 << info->bmiHeader.biBitCount;
141 return sizeof(BITMAPINFOHEADER) + colors *
142 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
147 /***********************************************************************
148 * DIB_GetBitmapInfo
150 * Get the info from a bitmap header.
151 * Return 0 for COREHEADER, 1 for INFOHEADER, -1 for error.
153 static int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
154 LONG *height, WORD *planes, WORD *bpp, DWORD *compr, DWORD *size )
156 if (header->biSize == sizeof(BITMAPCOREHEADER))
158 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)header;
159 *width = core->bcWidth;
160 *height = core->bcHeight;
161 *planes = core->bcPlanes;
162 *bpp = core->bcBitCount;
163 *compr = 0;
164 *size = 0;
165 return 0;
167 if (header->biSize >= sizeof(BITMAPINFOHEADER)) /* assume BITMAPINFOHEADER */
169 *width = header->biWidth;
170 *height = header->biHeight;
171 *planes = header->biPlanes;
172 *bpp = header->biBitCount;
173 *compr = header->biCompression;
174 *size = header->biSizeImage;
175 return 1;
177 ERR("(%d): unknown/wrong size for header\n", header->biSize );
178 return -1;
182 /***********************************************************************
183 * StretchDIBits (GDI32.@)
185 INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst,
186 INT heightDst, INT xSrc, INT ySrc, INT widthSrc,
187 INT heightSrc, const void *bits,
188 const BITMAPINFO *info, UINT wUsage, DWORD dwRop )
190 DC *dc;
191 INT ret;
193 if (!bits || !info)
194 return 0;
196 if (!(dc = get_dc_ptr( hdc ))) return 0;
198 if(dc->funcs->pStretchDIBits)
200 update_dc( dc );
201 ret = dc->funcs->pStretchDIBits(dc->physDev, xDst, yDst, widthDst,
202 heightDst, xSrc, ySrc, widthSrc,
203 heightSrc, bits, info, wUsage, dwRop);
204 release_dc_ptr( dc );
206 else /* use StretchBlt */
208 LONG height;
209 LONG width;
210 WORD planes, bpp;
211 DWORD compr, size;
212 HBITMAP hBitmap;
213 BOOL fastpath = FALSE;
215 release_dc_ptr( dc );
217 if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size ) == -1)
219 ERR("Invalid bitmap\n");
220 return 0;
223 if (width < 0)
225 ERR("Bitmap has a negative width\n");
226 return 0;
229 hBitmap = GetCurrentObject(hdc, OBJ_BITMAP);
231 if (xDst == 0 && yDst == 0 && xSrc == 0 && ySrc == 0 &&
232 widthDst == widthSrc && heightDst == heightSrc &&
233 info->bmiHeader.biCompression == BI_RGB &&
234 dwRop == SRCCOPY)
236 BITMAPOBJ *bmp;
237 if ((bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBitmap, BITMAP_MAGIC )))
239 if (bmp->bitmap.bmBitsPixel == bpp &&
240 bmp->bitmap.bmWidth == widthSrc &&
241 bmp->bitmap.bmHeight == heightSrc &&
242 bmp->bitmap.bmPlanes == planes)
243 fastpath = TRUE;
244 GDI_ReleaseObj( hBitmap );
248 if (fastpath)
250 /* fast path */
251 TRACE("using fast path\n");
252 ret = SetDIBits( hdc, hBitmap, 0, height, bits, info, wUsage);
254 else
256 /* slow path - need to use StretchBlt */
257 HBITMAP hOldBitmap;
258 HPALETTE hpal = NULL;
259 HDC hdcMem;
261 hdcMem = CreateCompatibleDC( hdc );
262 hBitmap = CreateCompatibleBitmap(hdc, width, height);
263 hOldBitmap = SelectObject( hdcMem, hBitmap );
264 if(wUsage == DIB_PAL_COLORS)
266 hpal = GetCurrentObject(hdc, OBJ_PAL);
267 hpal = SelectPalette(hdcMem, hpal, FALSE);
270 if (info->bmiHeader.biCompression == BI_RLE4 ||
271 info->bmiHeader.biCompression == BI_RLE8) {
273 /* when RLE compression is used, there may be some gaps (ie the DIB doesn't
274 * contain all the rectangle described in bmiHeader, but only part of it.
275 * This mean that those undescribed pixels must be left untouched.
276 * So, we first copy on a memory bitmap the current content of the
277 * destination rectangle, blit the DIB bits on top of it - hence leaving
278 * the gaps untouched -, and blitting the rectangle back.
279 * This insure that gaps are untouched on the destination rectangle
280 * Not doing so leads to trashed images (the gaps contain what was on the
281 * memory bitmap => generally black or garbage)
282 * Unfortunately, RLE DIBs without gaps will be slowed down. But this is
283 * another speed vs correctness issue. Anyway, if speed is needed, then the
284 * pStretchDIBits function shall be implemented.
285 * ericP (2000/09/09)
288 /* copy existing bitmap from destination dc */
289 StretchBlt( hdcMem, xSrc, abs(height) - heightSrc - ySrc,
290 widthSrc, heightSrc, hdc, xDst, yDst, widthDst, heightDst,
291 dwRop );
294 ret = SetDIBits(hdcMem, hBitmap, 0, height, bits, info, wUsage);
296 /* Origin for DIBitmap may be bottom left (positive biHeight) or top
297 left (negative biHeight) */
298 if (ret) StretchBlt( hdc, xDst, yDst, widthDst, heightDst,
299 hdcMem, xSrc, abs(height) - heightSrc - ySrc,
300 widthSrc, heightSrc, dwRop );
301 if(hpal)
302 SelectPalette(hdcMem, hpal, FALSE);
303 SelectObject( hdcMem, hOldBitmap );
304 DeleteDC( hdcMem );
305 DeleteObject( hBitmap );
308 return ret;
312 /******************************************************************************
313 * SetDIBits [GDI32.@]
315 * Sets pixels in a bitmap using colors from DIB.
317 * PARAMS
318 * hdc [I] Handle to device context
319 * hbitmap [I] Handle to bitmap
320 * startscan [I] Starting scan line
321 * lines [I] Number of scan lines
322 * bits [I] Array of bitmap bits
323 * info [I] Address of structure with data
324 * coloruse [I] Type of color indexes to use
326 * RETURNS
327 * Success: Number of scan lines copied
328 * Failure: 0
330 INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
331 UINT lines, LPCVOID bits, const BITMAPINFO *info,
332 UINT coloruse )
334 DC *dc;
335 BITMAPOBJ *bitmap;
336 INT result = 0;
338 if (!(dc = get_dc_ptr( hdc )))
340 if (coloruse == DIB_RGB_COLORS) FIXME( "shouldn't require a DC for DIB_RGB_COLORS\n" );
341 return 0;
344 update_dc( dc );
346 if (!(bitmap = GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
348 release_dc_ptr( dc );
349 return 0;
352 if (!bitmap->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) goto done;
354 result = lines;
355 if (bitmap->funcs)
357 if (bitmap->funcs != dc->funcs)
358 ERR( "not supported: DDB bitmap %p not belonging to device %p\n", hbitmap, hdc );
359 else if (dc->funcs->pSetDIBits)
360 result = dc->funcs->pSetDIBits( dc->physDev, hbitmap, startscan, lines,
361 bits, info, coloruse );
364 done:
365 GDI_ReleaseObj( hbitmap );
366 release_dc_ptr( dc );
367 return result;
371 /***********************************************************************
372 * SetDIBitsToDevice (GDI32.@)
374 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
375 DWORD cy, INT xSrc, INT ySrc, UINT startscan,
376 UINT lines, LPCVOID bits, const BITMAPINFO *info,
377 UINT coloruse )
379 INT ret;
380 DC *dc;
382 if (!bits) return 0;
384 if (!(dc = get_dc_ptr( hdc ))) return 0;
386 if(dc->funcs->pSetDIBitsToDevice)
388 update_dc( dc );
389 ret = dc->funcs->pSetDIBitsToDevice( dc->physDev, xDest, yDest, cx, cy, xSrc,
390 ySrc, startscan, lines, bits,
391 info, coloruse );
393 else {
394 FIXME("unimplemented on hdc %p\n", hdc);
395 ret = 0;
398 release_dc_ptr( dc );
399 return ret;
402 /***********************************************************************
403 * SetDIBColorTable (GDI32.@)
405 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, CONST RGBQUAD *colors )
407 DC * dc;
408 UINT result = 0;
409 BITMAPOBJ * bitmap;
411 if (!(dc = get_dc_ptr( hdc ))) return 0;
413 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, BITMAP_MAGIC )))
415 /* Check if currently selected bitmap is a DIB */
416 if (bitmap->color_table)
418 if (startpos < bitmap->nb_colors)
420 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
421 memcpy(bitmap->color_table + startpos, colors, entries * sizeof(RGBQUAD));
422 result = entries;
425 GDI_ReleaseObj( dc->hBitmap );
428 if (dc->funcs->pSetDIBColorTable)
429 dc->funcs->pSetDIBColorTable(dc->physDev, startpos, entries, colors);
431 release_dc_ptr( dc );
432 return result;
436 /***********************************************************************
437 * GetDIBColorTable (GDI32.@)
439 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
441 DC * dc;
442 UINT result = 0;
444 if (!(dc = get_dc_ptr( hdc ))) return 0;
446 if (dc->funcs->pGetDIBColorTable)
447 result = dc->funcs->pGetDIBColorTable(dc->physDev, startpos, entries, colors);
448 else
450 BITMAPOBJ *bitmap = GDI_GetObjPtr( dc->hBitmap, BITMAP_MAGIC );
451 if (bitmap)
453 /* Check if currently selected bitmap is a DIB */
454 if (bitmap->color_table)
456 if (startpos < bitmap->nb_colors)
458 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
459 memcpy(colors, bitmap->color_table + startpos, entries * sizeof(RGBQUAD));
460 result = entries;
463 GDI_ReleaseObj( dc->hBitmap );
466 release_dc_ptr( dc );
467 return result;
470 /* FIXME the following two structs should be combined with __sysPalTemplate in
471 objects/color.c - this should happen after de-X11-ing both of these
472 files.
473 NB. RGBQUAD and PALETTEENTRY have different orderings of red, green
474 and blue - sigh */
476 static const RGBQUAD EGAColorsQuads[16] = {
477 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
478 { 0x00, 0x00, 0x00, 0x00 },
479 { 0x00, 0x00, 0x80, 0x00 },
480 { 0x00, 0x80, 0x00, 0x00 },
481 { 0x00, 0x80, 0x80, 0x00 },
482 { 0x80, 0x00, 0x00, 0x00 },
483 { 0x80, 0x00, 0x80, 0x00 },
484 { 0x80, 0x80, 0x00, 0x00 },
485 { 0x80, 0x80, 0x80, 0x00 },
486 { 0xc0, 0xc0, 0xc0, 0x00 },
487 { 0x00, 0x00, 0xff, 0x00 },
488 { 0x00, 0xff, 0x00, 0x00 },
489 { 0x00, 0xff, 0xff, 0x00 },
490 { 0xff, 0x00, 0x00, 0x00 },
491 { 0xff, 0x00, 0xff, 0x00 },
492 { 0xff, 0xff, 0x00, 0x00 },
493 { 0xff, 0xff, 0xff, 0x00 }
496 static const RGBTRIPLE EGAColorsTriples[16] = {
497 /* rgbBlue, rgbGreen, rgbRed */
498 { 0x00, 0x00, 0x00 },
499 { 0x00, 0x00, 0x80 },
500 { 0x00, 0x80, 0x00 },
501 { 0x00, 0x80, 0x80 },
502 { 0x80, 0x00, 0x00 },
503 { 0x80, 0x00, 0x80 },
504 { 0x80, 0x80, 0x00 },
505 { 0x80, 0x80, 0x80 },
506 { 0xc0, 0xc0, 0xc0 },
507 { 0x00, 0x00, 0xff },
508 { 0x00, 0xff, 0x00 },
509 { 0x00, 0xff, 0xff },
510 { 0xff, 0x00, 0x00 } ,
511 { 0xff, 0x00, 0xff },
512 { 0xff, 0xff, 0x00 },
513 { 0xff, 0xff, 0xff }
516 static const RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
517 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
518 { 0x00, 0x00, 0x00, 0x00 },
519 { 0x00, 0x00, 0x80, 0x00 },
520 { 0x00, 0x80, 0x00, 0x00 },
521 { 0x00, 0x80, 0x80, 0x00 },
522 { 0x80, 0x00, 0x00, 0x00 },
523 { 0x80, 0x00, 0x80, 0x00 },
524 { 0x80, 0x80, 0x00, 0x00 },
525 { 0xc0, 0xc0, 0xc0, 0x00 },
526 { 0xc0, 0xdc, 0xc0, 0x00 },
527 { 0xf0, 0xca, 0xa6, 0x00 },
528 { 0xf0, 0xfb, 0xff, 0x00 },
529 { 0xa4, 0xa0, 0xa0, 0x00 },
530 { 0x80, 0x80, 0x80, 0x00 },
531 { 0x00, 0x00, 0xf0, 0x00 },
532 { 0x00, 0xff, 0x00, 0x00 },
533 { 0x00, 0xff, 0xff, 0x00 },
534 { 0xff, 0x00, 0x00, 0x00 },
535 { 0xff, 0x00, 0xff, 0x00 },
536 { 0xff, 0xff, 0x00, 0x00 },
537 { 0xff, 0xff, 0xff, 0x00 }
540 static const RGBTRIPLE DefLogPaletteTriples[20] = { /* Copy of Default Logical Palette */
541 /* rgbBlue, rgbGreen, rgbRed */
542 { 0x00, 0x00, 0x00 },
543 { 0x00, 0x00, 0x80 },
544 { 0x00, 0x80, 0x00 },
545 { 0x00, 0x80, 0x80 },
546 { 0x80, 0x00, 0x00 },
547 { 0x80, 0x00, 0x80 },
548 { 0x80, 0x80, 0x00 },
549 { 0xc0, 0xc0, 0xc0 },
550 { 0xc0, 0xdc, 0xc0 },
551 { 0xf0, 0xca, 0xa6 },
552 { 0xf0, 0xfb, 0xff },
553 { 0xa4, 0xa0, 0xa0 },
554 { 0x80, 0x80, 0x80 },
555 { 0x00, 0x00, 0xf0 },
556 { 0x00, 0xff, 0x00 },
557 { 0x00, 0xff, 0xff },
558 { 0xff, 0x00, 0x00 },
559 { 0xff, 0x00, 0xff },
560 { 0xff, 0xff, 0x00 },
561 { 0xff, 0xff, 0xff}
565 /******************************************************************************
566 * GetDIBits [GDI32.@]
568 * Retrieves bits of bitmap and copies to buffer.
570 * RETURNS
571 * Success: Number of scan lines copied from bitmap
572 * Failure: 0
574 INT WINAPI GetDIBits(
575 HDC hdc, /* [in] Handle to device context */
576 HBITMAP hbitmap, /* [in] Handle to bitmap */
577 UINT startscan, /* [in] First scan line to set in dest bitmap */
578 UINT lines, /* [in] Number of scan lines to copy */
579 LPVOID bits, /* [out] Address of array for bitmap bits */
580 BITMAPINFO * info, /* [out] Address of structure with bitmap data */
581 UINT coloruse) /* [in] RGB or palette index */
583 DC * dc;
584 BITMAPOBJ * bmp;
585 int i;
586 int bitmap_type;
587 BOOL core_header;
588 LONG width;
589 LONG height;
590 WORD planes, bpp;
591 DWORD compr, size;
592 void* colorPtr;
593 RGBTRIPLE* rgbTriples;
594 RGBQUAD* rgbQuads;
596 if (!info) return 0;
598 bitmap_type = DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size);
599 if (bitmap_type == -1)
601 ERR("Invalid bitmap format\n");
602 return 0;
604 core_header = (bitmap_type == 0);
605 if (!(dc = get_dc_ptr( hdc )))
607 SetLastError( ERROR_INVALID_PARAMETER );
608 return 0;
610 update_dc( dc );
611 if (!(bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
613 release_dc_ptr( dc );
614 return 0;
617 colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
618 rgbTriples = (RGBTRIPLE *) colorPtr;
619 rgbQuads = (RGBQUAD *) colorPtr;
621 /* Transfer color info */
623 switch (bpp)
625 case 0: /* query bitmap info only */
626 if (core_header)
628 BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) info;
629 coreheader->bcWidth = bmp->bitmap.bmWidth;
630 coreheader->bcHeight = bmp->bitmap.bmHeight;
631 coreheader->bcPlanes = 1;
632 coreheader->bcBitCount = bmp->bitmap.bmBitsPixel;
634 else
636 info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
637 info->bmiHeader.biHeight = bmp->bitmap.bmHeight;
638 info->bmiHeader.biPlanes = 1;
639 info->bmiHeader.biSizeImage =
640 DIB_GetDIBImageBytes( bmp->bitmap.bmWidth,
641 bmp->bitmap.bmHeight,
642 bmp->bitmap.bmBitsPixel );
643 switch(bmp->bitmap.bmBitsPixel)
645 case 15:
646 info->bmiHeader.biBitCount = 16;
647 info->bmiHeader.biCompression = BI_RGB;
648 break;
649 case 16:
650 info->bmiHeader.biBitCount = 16;
651 info->bmiHeader.biCompression = BI_BITFIELDS;
652 break;
653 default:
654 info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
655 info->bmiHeader.biCompression = BI_RGB;
656 break;
658 info->bmiHeader.biXPelsPerMeter = 0;
659 info->bmiHeader.biYPelsPerMeter = 0;
660 info->bmiHeader.biClrUsed = 0;
661 info->bmiHeader.biClrImportant = 0;
663 /* Windows 2000 doesn't touch the additional struct members if
664 it's a BITMAPV4HEADER or a BITMAPV5HEADER */
666 lines = abs(bmp->bitmap.bmHeight);
667 goto done;
669 case 1:
670 case 4:
671 case 8:
672 if (!core_header) info->bmiHeader.biClrUsed = 0;
674 /* If the bitmap object already has a dib section at the
675 same color depth then get the color map from it */
676 if (bmp->dib && bmp->dib->dsBm.bmBitsPixel == bpp) {
677 if(coloruse == DIB_RGB_COLORS) {
678 unsigned int colors = min( bmp->nb_colors, 1 << bpp );
680 if (core_header)
682 /* Convert the color table (RGBQUAD to RGBTRIPLE) */
683 RGBTRIPLE* index = rgbTriples;
685 for (i=0; i < colors; i++, index++)
687 index->rgbtRed = bmp->color_table[i].rgbRed;
688 index->rgbtGreen = bmp->color_table[i].rgbGreen;
689 index->rgbtBlue = bmp->color_table[i].rgbBlue;
692 else
694 if (colors != 1 << bpp) info->bmiHeader.biClrUsed = colors;
695 memcpy(colorPtr, bmp->color_table, colors * sizeof(RGBQUAD));
698 else {
699 WORD *index = colorPtr;
700 for(i = 0; i < 1 << info->bmiHeader.biBitCount; i++, index++)
701 *index = i;
704 else {
705 if(bpp >= bmp->bitmap.bmBitsPixel) {
706 /* Generate the color map from the selected palette */
707 PALETTEENTRY palEntry[256];
709 memset( palEntry, 0, sizeof(palEntry) );
710 if (!GetPaletteEntries( dc->hPalette, 0, 1 << bmp->bitmap.bmBitsPixel, palEntry ))
712 release_dc_ptr( dc );
713 GDI_ReleaseObj( hbitmap );
714 return 0;
716 for (i = 0; i < (1 << bmp->bitmap.bmBitsPixel); i++) {
717 if (coloruse == DIB_RGB_COLORS) {
718 if (core_header)
720 rgbTriples[i].rgbtRed = palEntry[i].peRed;
721 rgbTriples[i].rgbtGreen = palEntry[i].peGreen;
722 rgbTriples[i].rgbtBlue = palEntry[i].peBlue;
724 else
726 rgbQuads[i].rgbRed = palEntry[i].peRed;
727 rgbQuads[i].rgbGreen = palEntry[i].peGreen;
728 rgbQuads[i].rgbBlue = palEntry[i].peBlue;
729 rgbQuads[i].rgbReserved = 0;
732 else ((WORD *)colorPtr)[i] = (WORD)i;
734 } else {
735 switch (bpp) {
736 case 1:
737 if (core_header)
739 rgbTriples[0].rgbtRed = rgbTriples[0].rgbtGreen =
740 rgbTriples[0].rgbtBlue = 0;
741 rgbTriples[1].rgbtRed = rgbTriples[1].rgbtGreen =
742 rgbTriples[1].rgbtBlue = 0xff;
744 else
746 rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen =
747 rgbQuads[0].rgbBlue = 0;
748 rgbQuads[0].rgbReserved = 0;
749 rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen =
750 rgbQuads[1].rgbBlue = 0xff;
751 rgbQuads[1].rgbReserved = 0;
753 break;
755 case 4:
756 if (core_header)
757 memcpy(colorPtr, EGAColorsTriples, sizeof(EGAColorsTriples));
758 else
759 memcpy(colorPtr, EGAColorsQuads, sizeof(EGAColorsQuads));
761 break;
763 case 8:
765 if (core_header)
767 INT r, g, b;
768 RGBTRIPLE *color;
770 memcpy(rgbTriples, DefLogPaletteTriples,
771 10 * sizeof(RGBTRIPLE));
772 memcpy(rgbTriples + 246, DefLogPaletteTriples + 10,
773 10 * sizeof(RGBTRIPLE));
774 color = rgbTriples + 10;
775 for(r = 0; r <= 5; r++) /* FIXME */
776 for(g = 0; g <= 5; g++)
777 for(b = 0; b <= 5; b++) {
778 color->rgbtRed = (r * 0xff) / 5;
779 color->rgbtGreen = (g * 0xff) / 5;
780 color->rgbtBlue = (b * 0xff) / 5;
781 color++;
784 else
786 INT r, g, b;
787 RGBQUAD *color;
789 memcpy(rgbQuads, DefLogPaletteQuads,
790 10 * sizeof(RGBQUAD));
791 memcpy(rgbQuads + 246, DefLogPaletteQuads + 10,
792 10 * sizeof(RGBQUAD));
793 color = rgbQuads + 10;
794 for(r = 0; r <= 5; r++) /* FIXME */
795 for(g = 0; g <= 5; g++)
796 for(b = 0; b <= 5; b++) {
797 color->rgbRed = (r * 0xff) / 5;
798 color->rgbGreen = (g * 0xff) / 5;
799 color->rgbBlue = (b * 0xff) / 5;
800 color->rgbReserved = 0;
801 color++;
808 break;
810 case 15:
811 if (info->bmiHeader.biCompression == BI_BITFIELDS)
813 ((PDWORD)info->bmiColors)[0] = 0x7c00;
814 ((PDWORD)info->bmiColors)[1] = 0x03e0;
815 ((PDWORD)info->bmiColors)[2] = 0x001f;
817 break;
819 case 16:
820 if (info->bmiHeader.biCompression == BI_BITFIELDS)
822 ((PDWORD)info->bmiColors)[0] = 0xf800;
823 ((PDWORD)info->bmiColors)[1] = 0x07e0;
824 ((PDWORD)info->bmiColors)[2] = 0x001f;
826 break;
829 if (bits && lines)
831 /* If the bitmap object already have a dib section that contains image data, get the bits from it */
832 if(bmp->dib && bmp->dib->dsBm.bmBitsPixel >= 15 && bpp >= 15)
834 /*FIXME: Only RGB dibs supported for now */
835 unsigned int srcwidth = bmp->dib->dsBm.bmWidth, srcwidthb = bmp->dib->dsBm.bmWidthBytes;
836 unsigned int dstwidth = width;
837 int dstwidthb = DIB_GetDIBWidthBytes( width, bpp );
838 LPBYTE dbits = bits, sbits = (LPBYTE) bmp->dib->dsBm.bmBits + (startscan * srcwidthb);
839 unsigned int x, y, width, widthb;
841 if ((height < 0) ^ (bmp->dib->dsBmih.biHeight < 0))
843 dbits = (LPBYTE)bits + (dstwidthb * (lines-1));
844 dstwidthb = -dstwidthb;
847 switch( bpp ) {
849 case 15:
850 case 16: /* 16 bpp dstDIB */
852 LPWORD dstbits = (LPWORD)dbits;
853 WORD rmask = 0x7c00, gmask= 0x03e0, bmask = 0x001f;
855 /* FIXME: BI_BITFIELDS not supported yet */
857 switch(bmp->dib->dsBm.bmBitsPixel) {
859 case 16: /* 16 bpp srcDIB -> 16 bpp dstDIB */
861 widthb = min(srcwidthb, abs(dstwidthb));
862 /* FIXME: BI_BITFIELDS not supported yet */
863 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
864 memcpy(dbits, sbits, widthb);
866 break;
868 case 24: /* 24 bpp srcDIB -> 16 bpp dstDIB */
870 LPBYTE srcbits = sbits;
872 width = min(srcwidth, dstwidth);
873 for( y = 0; y < lines; y++) {
874 for( x = 0; x < width; x++, srcbits += 3)
875 *dstbits++ = ((srcbits[0] >> 3) & bmask) |
876 (((WORD)srcbits[1] << 2) & gmask) |
877 (((WORD)srcbits[2] << 7) & rmask);
879 dstbits = (LPWORD)(dbits+=dstwidthb);
880 srcbits = (sbits += srcwidthb);
883 break;
885 case 32: /* 32 bpp srcDIB -> 16 bpp dstDIB */
887 LPDWORD srcbits = (LPDWORD)sbits;
888 DWORD val;
890 width = min(srcwidth, dstwidth);
891 for( y = 0; y < lines; y++) {
892 for( x = 0; x < width; x++ ) {
893 val = *srcbits++;
894 *dstbits++ = (WORD)(((val >> 3) & bmask) | ((val >> 6) & gmask) |
895 ((val >> 9) & rmask));
897 dstbits = (LPWORD)(dbits+=dstwidthb);
898 srcbits = (LPDWORD)(sbits+=srcwidthb);
901 break;
903 default: /* ? bit bmp -> 16 bit DIB */
904 FIXME("15/16 bit DIB %d bit bitmap\n",
905 bmp->bitmap.bmBitsPixel);
906 break;
909 break;
911 case 24: /* 24 bpp dstDIB */
913 LPBYTE dstbits = dbits;
915 switch(bmp->dib->dsBm.bmBitsPixel) {
917 case 16: /* 16 bpp srcDIB -> 24 bpp dstDIB */
919 LPWORD srcbits = (LPWORD)sbits;
920 WORD val;
922 width = min(srcwidth, dstwidth);
923 /* FIXME: BI_BITFIELDS not supported yet */
924 for( y = 0; y < lines; y++) {
925 for( x = 0; x < width; x++ ) {
926 val = *srcbits++;
927 *dstbits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07));
928 *dstbits++ = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07));
929 *dstbits++ = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07));
931 dstbits = dbits+=dstwidthb;
932 srcbits = (LPWORD)(sbits+=srcwidthb);
935 break;
937 case 24: /* 24 bpp srcDIB -> 24 bpp dstDIB */
939 widthb = min(srcwidthb, abs(dstwidthb));
940 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
941 memcpy(dbits, sbits, widthb);
943 break;
945 case 32: /* 32 bpp srcDIB -> 24 bpp dstDIB */
947 LPBYTE srcbits = sbits;
949 width = min(srcwidth, dstwidth);
950 for( y = 0; y < lines; y++) {
951 for( x = 0; x < width; x++, srcbits++ ) {
952 *dstbits++ = *srcbits++;
953 *dstbits++ = *srcbits++;
954 *dstbits++ = *srcbits++;
956 dstbits = dbits+=dstwidthb;
957 srcbits = sbits+=srcwidthb;
960 break;
962 default: /* ? bit bmp -> 24 bit DIB */
963 FIXME("24 bit DIB %d bit bitmap\n",
964 bmp->bitmap.bmBitsPixel);
965 break;
968 break;
970 case 32: /* 32 bpp dstDIB */
972 LPDWORD dstbits = (LPDWORD)dbits;
974 /* FIXME: BI_BITFIELDS not supported yet */
976 switch(bmp->dib->dsBm.bmBitsPixel) {
977 case 16: /* 16 bpp srcDIB -> 32 bpp dstDIB */
979 LPWORD srcbits = (LPWORD)sbits;
980 DWORD val;
982 width = min(srcwidth, dstwidth);
983 /* FIXME: BI_BITFIELDS not supported yet */
984 for( y = 0; y < lines; y++) {
985 for( x = 0; x < width; x++ ) {
986 val = (DWORD)*srcbits++;
987 *dstbits++ = ((val << 3) & 0xf8) | ((val >> 2) & 0x07) |
988 ((val << 6) & 0xf800) | ((val << 1) & 0x0700) |
989 ((val << 9) & 0xf80000) | ((val << 4) & 0x070000);
991 dstbits=(LPDWORD)(dbits+=dstwidthb);
992 srcbits=(LPWORD)(sbits+=srcwidthb);
995 break;
997 case 24: /* 24 bpp srcDIB -> 32 bpp dstDIB */
999 LPBYTE srcbits = sbits;
1001 width = min(srcwidth, dstwidth);
1002 for( y = 0; y < lines; y++) {
1003 for( x = 0; x < width; x++, srcbits+=3 )
1004 *dstbits++ = srcbits[0] |
1005 (srcbits[1] << 8) |
1006 (srcbits[2] << 16);
1007 dstbits=(LPDWORD)(dbits+=dstwidthb);
1008 srcbits=(sbits+=srcwidthb);
1011 break;
1013 case 32: /* 32 bpp srcDIB -> 32 bpp dstDIB */
1015 widthb = min(srcwidthb, abs(dstwidthb));
1016 /* FIXME: BI_BITFIELDS not supported yet */
1017 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb) {
1018 memcpy(dbits, sbits, widthb);
1021 break;
1023 default: /* ? bit bmp -> 32 bit DIB */
1024 FIXME("32 bit DIB %d bit bitmap\n",
1025 bmp->bitmap.bmBitsPixel);
1026 break;
1029 break;
1031 default: /* ? bit DIB */
1032 FIXME("Unsupported DIB depth %d\n", info->bmiHeader.biBitCount);
1033 break;
1036 /* Otherwise, get bits from the XImage */
1037 else
1039 if (!bmp->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) lines = 0;
1040 else
1042 if (bmp->funcs && bmp->funcs->pGetDIBits)
1043 lines = bmp->funcs->pGetDIBits( dc->physDev, hbitmap, startscan,
1044 lines, bits, info, coloruse );
1045 else
1046 lines = 0; /* FIXME: should copy from bmp->bitmap.bmBits */
1050 else lines = abs(height);
1052 /* The knowledge base article Q81498 ("DIBs and Their Uses") states that
1053 if bits == NULL and bpp != 0, only biSizeImage and the color table are
1054 filled in. */
1055 if (!core_header)
1057 /* FIXME: biSizeImage should be calculated according to the selected
1058 compression algorithm if biCompression != BI_RGB */
1059 info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes( width, height, bpp );
1060 TRACE("biSizeImage = %d, ", info->bmiHeader.biSizeImage);
1062 TRACE("biWidth = %d, biHeight = %d\n", width, height);
1064 done:
1065 release_dc_ptr( dc );
1066 GDI_ReleaseObj( hbitmap );
1067 return lines;
1071 /***********************************************************************
1072 * CreateDIBitmap (GDI32.@)
1074 * Creates a DDB (device dependent bitmap) from a DIB.
1075 * The DDB will have the same color depth as the reference DC.
1077 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
1078 DWORD init, LPCVOID bits, const BITMAPINFO *data,
1079 UINT coloruse )
1081 HBITMAP handle;
1082 LONG width;
1083 LONG height;
1084 WORD planes, bpp;
1085 DWORD compr, size;
1086 DC *dc;
1088 if (DIB_GetBitmapInfo( header, &width, &height, &planes, &bpp, &compr, &size ) == -1) return 0;
1090 if (width < 0)
1092 TRACE("Bitmap has a negative width\n");
1093 return 0;
1096 /* Top-down DIBs have a negative height */
1097 if (height < 0) height = -height;
1099 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1100 hdc, header, init, bits, data, coloruse, width, height, bpp, compr);
1102 if (hdc == NULL)
1103 handle = CreateBitmap( width, height, 1, 1, NULL );
1104 else
1105 handle = CreateCompatibleBitmap( hdc, width, height );
1107 if (handle)
1109 if (init == CBM_INIT) SetDIBits( hdc, handle, 0, height, bits, data, coloruse );
1111 else if (hdc && ((dc = get_dc_ptr( hdc )) != NULL) )
1113 if (!BITMAP_SetOwnerDC( handle, dc ))
1115 DeleteObject( handle );
1116 handle = 0;
1118 release_dc_ptr( dc );
1122 return handle;
1125 /***********************************************************************
1126 * CreateDIBSection (GDI.489)
1128 HBITMAP16 WINAPI CreateDIBSection16 (HDC16 hdc, const BITMAPINFO *bmi, UINT16 usage,
1129 SEGPTR *bits16, HANDLE section, DWORD offset)
1131 LPVOID bits32;
1132 HBITMAP hbitmap;
1134 hbitmap = CreateDIBSection( HDC_32(hdc), bmi, usage, &bits32, section, offset );
1135 if (hbitmap)
1137 BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr(hbitmap, BITMAP_MAGIC);
1138 if (bmp && bmp->dib && bits32)
1140 const BITMAPINFOHEADER *bi = &bmi->bmiHeader;
1141 LONG width, height;
1142 WORD planes, bpp;
1143 DWORD compr, size;
1144 INT width_bytes;
1145 WORD count, sel;
1146 int i;
1148 DIB_GetBitmapInfo(bi, &width, &height, &planes, &bpp, &compr, &size);
1150 height = height >= 0 ? height : -height;
1151 width_bytes = DIB_GetDIBWidthBytes(width, bpp);
1153 if (!size || (compr != BI_RLE4 && compr != BI_RLE8)) size = width_bytes * height;
1155 /* calculate number of sel's needed for size with 64K steps */
1156 count = (size + 0xffff) / 0x10000;
1157 sel = AllocSelectorArray16(count);
1159 for (i = 0; i < count; i++)
1161 SetSelectorBase(sel + (i << __AHSHIFT), (DWORD)bits32 + i * 0x10000);
1162 SetSelectorLimit16(sel + (i << __AHSHIFT), size - 1); /* yep, limit is correct */
1163 size -= 0x10000;
1165 bmp->segptr_bits = MAKESEGPTR( sel, 0 );
1166 if (bits16) *bits16 = bmp->segptr_bits;
1168 if (bmp) GDI_ReleaseObj( hbitmap );
1170 return HBITMAP_16(hbitmap);
1173 /* Copy/synthesize RGB palette from BITMAPINFO. Ripped from dlls/winex11.drv/dib.c */
1174 static void DIB_CopyColorTable( DC *dc, BITMAPOBJ *bmp, WORD coloruse, const BITMAPINFO *info )
1176 RGBQUAD *colorTable;
1177 unsigned int colors;
1178 int i;
1179 BOOL core_info = info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER);
1181 if (core_info)
1183 colors = 1 << ((const BITMAPCOREINFO*) info)->bmciHeader.bcBitCount;
1185 else
1187 colors = info->bmiHeader.biClrUsed;
1188 if (!colors) colors = 1 << info->bmiHeader.biBitCount;
1191 if (colors > 256) {
1192 ERR("called with >256 colors!\n");
1193 return;
1196 if (!(colorTable = HeapAlloc(GetProcessHeap(), 0, colors * sizeof(RGBQUAD) ))) return;
1198 if(coloruse == DIB_RGB_COLORS)
1200 if (core_info)
1202 /* Convert RGBTRIPLEs to RGBQUADs */
1203 for (i=0; i < colors; i++)
1205 colorTable[i].rgbRed = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtRed;
1206 colorTable[i].rgbGreen = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtGreen;
1207 colorTable[i].rgbBlue = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtBlue;
1208 colorTable[i].rgbReserved = 0;
1211 else
1213 memcpy(colorTable, (const BYTE*) info + (WORD) info->bmiHeader.biSize, colors * sizeof(RGBQUAD));
1216 else
1218 PALETTEENTRY entries[256];
1219 const WORD *index = (const WORD*) ((const BYTE*) info + (WORD) info->bmiHeader.biSize);
1220 UINT count = GetPaletteEntries( dc->hPalette, 0, colors, entries );
1222 for (i = 0; i < colors; i++, index++)
1224 PALETTEENTRY *entry = &entries[*index % count];
1225 colorTable[i].rgbRed = entry->peRed;
1226 colorTable[i].rgbGreen = entry->peGreen;
1227 colorTable[i].rgbBlue = entry->peBlue;
1228 colorTable[i].rgbReserved = 0;
1231 bmp->color_table = colorTable;
1232 bmp->nb_colors = colors;
1235 /***********************************************************************
1236 * CreateDIBSection (GDI32.@)
1238 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
1239 VOID **bits, HANDLE section, DWORD offset)
1241 HBITMAP ret = 0;
1242 DC *dc;
1243 BOOL bDesktopDC = FALSE;
1244 DIBSECTION *dib;
1245 BITMAPOBJ *bmp;
1246 int bitmap_type;
1247 LONG width, height;
1248 WORD planes, bpp;
1249 DWORD compression, sizeImage;
1250 void *mapBits = NULL;
1252 if (((bitmap_type = DIB_GetBitmapInfo( &bmi->bmiHeader, &width, &height,
1253 &planes, &bpp, &compression, &sizeImage )) == -1))
1254 return 0;
1256 if (compression != BI_RGB && compression != BI_BITFIELDS)
1258 TRACE("can't create a compressed (%u) dibsection\n", compression);
1259 return 0;
1262 if (!(dib = HeapAlloc( GetProcessHeap(), 0, sizeof(*dib) ))) return 0;
1264 TRACE("format (%d,%d), planes %d, bpp %d, size %d, %s\n",
1265 width, height, planes, bpp, sizeImage, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1267 dib->dsBm.bmType = 0;
1268 dib->dsBm.bmWidth = width;
1269 dib->dsBm.bmHeight = height >= 0 ? height : -height;
1270 dib->dsBm.bmWidthBytes = DIB_GetDIBWidthBytes(width, bpp);
1271 dib->dsBm.bmPlanes = planes;
1272 dib->dsBm.bmBitsPixel = bpp;
1273 dib->dsBm.bmBits = NULL;
1275 if (!bitmap_type) /* core header */
1277 /* convert the BITMAPCOREHEADER to a BITMAPINFOHEADER */
1278 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1279 dib->dsBmih.biWidth = width;
1280 dib->dsBmih.biHeight = height;
1281 dib->dsBmih.biPlanes = planes;
1282 dib->dsBmih.biBitCount = bpp;
1283 dib->dsBmih.biCompression = compression;
1284 dib->dsBmih.biXPelsPerMeter = 0;
1285 dib->dsBmih.biYPelsPerMeter = 0;
1286 dib->dsBmih.biClrUsed = 0;
1287 dib->dsBmih.biClrImportant = 0;
1289 else
1291 /* truncate extended bitmap headers (BITMAPV4HEADER etc.) */
1292 dib->dsBmih = bmi->bmiHeader;
1293 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1296 /* set number of entries in bmi.bmiColors table */
1297 if( bpp <= 8 )
1298 dib->dsBmih.biClrUsed = 1 << bpp;
1300 dib->dsBmih.biSizeImage = dib->dsBm.bmWidthBytes * dib->dsBm.bmHeight;
1302 /* set dsBitfields values */
1303 if (usage == DIB_PAL_COLORS || bpp <= 8)
1305 dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
1307 else switch( bpp )
1309 case 15:
1310 case 16:
1311 dib->dsBitfields[0] = (compression == BI_BITFIELDS) ? *(const DWORD *)bmi->bmiColors : 0x7c00;
1312 dib->dsBitfields[1] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 1) : 0x03e0;
1313 dib->dsBitfields[2] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 2) : 0x001f;
1314 break;
1315 case 24:
1316 case 32:
1317 dib->dsBitfields[0] = (compression == BI_BITFIELDS) ? *(const DWORD *)bmi->bmiColors : 0xff0000;
1318 dib->dsBitfields[1] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 1) : 0x00ff00;
1319 dib->dsBitfields[2] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 2) : 0x0000ff;
1320 break;
1323 /* get storage location for DIB bits */
1325 if (section)
1327 SYSTEM_INFO SystemInfo;
1328 DWORD mapOffset;
1329 INT mapSize;
1331 GetSystemInfo( &SystemInfo );
1332 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
1333 mapSize = dib->dsBmih.biSizeImage + (offset - mapOffset);
1334 mapBits = MapViewOfFile( section, FILE_MAP_ALL_ACCESS, 0, mapOffset, mapSize );
1335 if (mapBits) dib->dsBm.bmBits = (char *)mapBits + (offset - mapOffset);
1337 else
1339 offset = 0;
1340 dib->dsBm.bmBits = VirtualAlloc( NULL, dib->dsBmih.biSizeImage,
1341 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
1343 dib->dshSection = section;
1344 dib->dsOffset = offset;
1346 if (!dib->dsBm.bmBits)
1348 HeapFree( GetProcessHeap(), 0, dib );
1349 return 0;
1352 /* If the reference hdc is null, take the desktop dc */
1353 if (hdc == 0)
1355 hdc = CreateCompatibleDC(0);
1356 bDesktopDC = TRUE;
1359 if (!(dc = get_dc_ptr( hdc ))) goto error;
1361 /* create Device Dependent Bitmap and add DIB pointer */
1362 ret = CreateBitmap( dib->dsBm.bmWidth, dib->dsBm.bmHeight, 1,
1363 (bpp == 1) ? 1 : GetDeviceCaps(hdc, BITSPIXEL), NULL );
1365 if (ret && ((bmp = GDI_GetObjPtr(ret, BITMAP_MAGIC))))
1367 bmp->dib = dib;
1368 bmp->funcs = dc->funcs;
1369 /* create local copy of DIB palette */
1370 if (bpp <= 8) DIB_CopyColorTable( dc, bmp, usage, bmi );
1371 GDI_ReleaseObj( ret );
1373 if (dc->funcs->pCreateDIBSection)
1375 if (!dc->funcs->pCreateDIBSection(dc->physDev, ret, bmi, usage))
1377 DeleteObject( ret );
1378 ret = 0;
1383 release_dc_ptr( dc );
1384 if (bDesktopDC) DeleteDC( hdc );
1385 if (ret && bits) *bits = dib->dsBm.bmBits;
1386 return ret;
1388 error:
1389 if (bDesktopDC) DeleteDC( hdc );
1390 if (section) UnmapViewOfFile( mapBits );
1391 else if (!offset) VirtualFree( dib->dsBm.bmBits, 0, MEM_RELEASE );
1392 HeapFree( GetProcessHeap(), 0, dib );
1393 return 0;