setupapi: Added Hebrew translation.
[wine.git] / dlls / gdi32 / dib.c
blobc799ea3db8701506bd5e0473c74be070db28e53d
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 if (xSrc == 0 && ySrc == 0 && widthDst == widthSrc && heightDst == heightSrc &&
231 info->bmiHeader.biCompression == BI_RGB)
233 /* Windows appears to have a fast case optimization
234 * that uses the wrong origin for top-down DIBs */
235 if (height < 0 && heightSrc < abs(height)) ySrc = abs(height) - heightSrc;
238 hBitmap = GetCurrentObject(hdc, OBJ_BITMAP);
240 if (xDst == 0 && yDst == 0 && xSrc == 0 && ySrc == 0 &&
241 widthDst == widthSrc && heightDst == heightSrc &&
242 info->bmiHeader.biCompression == BI_RGB &&
243 dwRop == SRCCOPY)
245 BITMAPOBJ *bmp;
246 if ((bmp = GDI_GetObjPtr( hBitmap, OBJ_BITMAP )))
248 if (bmp->bitmap.bmBitsPixel == bpp &&
249 bmp->bitmap.bmWidth == widthSrc &&
250 bmp->bitmap.bmHeight == heightSrc &&
251 bmp->bitmap.bmPlanes == planes)
252 fastpath = TRUE;
253 GDI_ReleaseObj( hBitmap );
257 if (fastpath)
259 /* fast path */
260 TRACE("using fast path\n");
261 ret = SetDIBits( hdc, hBitmap, 0, height, bits, info, wUsage);
263 else
265 /* slow path - need to use StretchBlt */
266 HBITMAP hOldBitmap;
267 HPALETTE hpal = NULL;
268 HDC hdcMem;
270 hdcMem = CreateCompatibleDC( hdc );
271 hBitmap = CreateCompatibleBitmap(hdc, width, height);
272 hOldBitmap = SelectObject( hdcMem, hBitmap );
273 if(wUsage == DIB_PAL_COLORS)
275 hpal = GetCurrentObject(hdc, OBJ_PAL);
276 hpal = SelectPalette(hdcMem, hpal, FALSE);
279 if (info->bmiHeader.biCompression == BI_RLE4 ||
280 info->bmiHeader.biCompression == BI_RLE8) {
282 /* when RLE compression is used, there may be some gaps (ie the DIB doesn't
283 * contain all the rectangle described in bmiHeader, but only part of it.
284 * This mean that those undescribed pixels must be left untouched.
285 * So, we first copy on a memory bitmap the current content of the
286 * destination rectangle, blit the DIB bits on top of it - hence leaving
287 * the gaps untouched -, and blitting the rectangle back.
288 * This insure that gaps are untouched on the destination rectangle
289 * Not doing so leads to trashed images (the gaps contain what was on the
290 * memory bitmap => generally black or garbage)
291 * Unfortunately, RLE DIBs without gaps will be slowed down. But this is
292 * another speed vs correctness issue. Anyway, if speed is needed, then the
293 * pStretchDIBits function shall be implemented.
294 * ericP (2000/09/09)
297 /* copy existing bitmap from destination dc */
298 StretchBlt( hdcMem, xSrc, abs(height) - heightSrc - ySrc,
299 widthSrc, heightSrc, hdc, xDst, yDst, widthDst, heightDst,
300 dwRop );
303 ret = SetDIBits(hdcMem, hBitmap, 0, height, bits, info, wUsage);
305 /* Origin for DIBitmap may be bottom left (positive biHeight) or top
306 left (negative biHeight) */
307 if (ret) StretchBlt( hdc, xDst, yDst, widthDst, heightDst,
308 hdcMem, xSrc, abs(height) - heightSrc - ySrc,
309 widthSrc, heightSrc, dwRop );
310 if(hpal)
311 SelectPalette(hdcMem, hpal, FALSE);
312 SelectObject( hdcMem, hOldBitmap );
313 DeleteDC( hdcMem );
314 DeleteObject( hBitmap );
317 return ret;
321 /******************************************************************************
322 * SetDIBits [GDI32.@]
324 * Sets pixels in a bitmap using colors from DIB.
326 * PARAMS
327 * hdc [I] Handle to device context
328 * hbitmap [I] Handle to bitmap
329 * startscan [I] Starting scan line
330 * lines [I] Number of scan lines
331 * bits [I] Array of bitmap bits
332 * info [I] Address of structure with data
333 * coloruse [I] Type of color indexes to use
335 * RETURNS
336 * Success: Number of scan lines copied
337 * Failure: 0
339 INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
340 UINT lines, LPCVOID bits, const BITMAPINFO *info,
341 UINT coloruse )
343 DC *dc = get_dc_ptr( hdc );
344 BOOL delete_hdc = FALSE;
345 BITMAPOBJ *bitmap;
346 INT result = 0;
348 if (coloruse == DIB_RGB_COLORS && !dc)
350 hdc = CreateCompatibleDC(0);
351 dc = get_dc_ptr( hdc );
352 delete_hdc = TRUE;
355 if (!dc) return 0;
357 update_dc( dc );
359 if (!(bitmap = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
361 release_dc_ptr( dc );
362 if (delete_hdc) DeleteDC(hdc);
363 return 0;
366 if (!bitmap->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) goto done;
368 result = lines;
369 if (bitmap->funcs)
371 if (bitmap->funcs != dc->funcs)
372 ERR( "not supported: DDB bitmap %p not belonging to device %p\n", hbitmap, hdc );
373 else if (dc->funcs->pSetDIBits)
374 result = dc->funcs->pSetDIBits( dc->physDev, hbitmap, startscan, lines,
375 bits, info, coloruse );
378 done:
379 GDI_ReleaseObj( hbitmap );
380 release_dc_ptr( dc );
381 if (delete_hdc) DeleteDC(hdc);
382 return result;
386 /***********************************************************************
387 * SetDIBitsToDevice (GDI32.@)
389 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
390 DWORD cy, INT xSrc, INT ySrc, UINT startscan,
391 UINT lines, LPCVOID bits, const BITMAPINFO *info,
392 UINT coloruse )
394 INT ret;
395 DC *dc;
397 if (!bits) return 0;
399 if (!(dc = get_dc_ptr( hdc ))) return 0;
401 if(dc->funcs->pSetDIBitsToDevice)
403 update_dc( dc );
404 ret = dc->funcs->pSetDIBitsToDevice( dc->physDev, xDest, yDest, cx, cy, xSrc,
405 ySrc, startscan, lines, bits,
406 info, coloruse );
408 else {
409 FIXME("unimplemented on hdc %p\n", hdc);
410 ret = 0;
413 release_dc_ptr( dc );
414 return ret;
417 /***********************************************************************
418 * SetDIBColorTable (GDI32.@)
420 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, CONST RGBQUAD *colors )
422 DC * dc;
423 UINT result = 0;
424 BITMAPOBJ * bitmap;
426 if (!(dc = get_dc_ptr( hdc ))) return 0;
428 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
430 /* Check if currently selected bitmap is a DIB */
431 if (bitmap->color_table)
433 if (startpos < bitmap->nb_colors)
435 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
436 memcpy(bitmap->color_table + startpos, colors, entries * sizeof(RGBQUAD));
437 result = entries;
440 GDI_ReleaseObj( dc->hBitmap );
443 if (dc->funcs->pSetDIBColorTable)
444 dc->funcs->pSetDIBColorTable(dc->physDev, startpos, entries, colors);
446 release_dc_ptr( dc );
447 return result;
451 /***********************************************************************
452 * GetDIBColorTable (GDI32.@)
454 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
456 DC * dc;
457 UINT result = 0;
459 if (!(dc = get_dc_ptr( hdc ))) return 0;
461 if (dc->funcs->pGetDIBColorTable)
462 result = dc->funcs->pGetDIBColorTable(dc->physDev, startpos, entries, colors);
463 else
465 BITMAPOBJ *bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP );
466 if (bitmap)
468 /* Check if currently selected bitmap is a DIB */
469 if (bitmap->color_table)
471 if (startpos < bitmap->nb_colors)
473 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
474 memcpy(colors, bitmap->color_table + startpos, entries * sizeof(RGBQUAD));
475 result = entries;
478 GDI_ReleaseObj( dc->hBitmap );
481 release_dc_ptr( dc );
482 return result;
485 /* FIXME the following two structs should be combined with __sysPalTemplate in
486 objects/color.c - this should happen after de-X11-ing both of these
487 files.
488 NB. RGBQUAD and PALETTEENTRY have different orderings of red, green
489 and blue - sigh */
491 static const RGBQUAD EGAColorsQuads[16] = {
492 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
493 { 0x00, 0x00, 0x00, 0x00 },
494 { 0x00, 0x00, 0x80, 0x00 },
495 { 0x00, 0x80, 0x00, 0x00 },
496 { 0x00, 0x80, 0x80, 0x00 },
497 { 0x80, 0x00, 0x00, 0x00 },
498 { 0x80, 0x00, 0x80, 0x00 },
499 { 0x80, 0x80, 0x00, 0x00 },
500 { 0x80, 0x80, 0x80, 0x00 },
501 { 0xc0, 0xc0, 0xc0, 0x00 },
502 { 0x00, 0x00, 0xff, 0x00 },
503 { 0x00, 0xff, 0x00, 0x00 },
504 { 0x00, 0xff, 0xff, 0x00 },
505 { 0xff, 0x00, 0x00, 0x00 },
506 { 0xff, 0x00, 0xff, 0x00 },
507 { 0xff, 0xff, 0x00, 0x00 },
508 { 0xff, 0xff, 0xff, 0x00 }
511 static const RGBTRIPLE EGAColorsTriples[16] = {
512 /* rgbBlue, rgbGreen, rgbRed */
513 { 0x00, 0x00, 0x00 },
514 { 0x00, 0x00, 0x80 },
515 { 0x00, 0x80, 0x00 },
516 { 0x00, 0x80, 0x80 },
517 { 0x80, 0x00, 0x00 },
518 { 0x80, 0x00, 0x80 },
519 { 0x80, 0x80, 0x00 },
520 { 0x80, 0x80, 0x80 },
521 { 0xc0, 0xc0, 0xc0 },
522 { 0x00, 0x00, 0xff },
523 { 0x00, 0xff, 0x00 },
524 { 0x00, 0xff, 0xff },
525 { 0xff, 0x00, 0x00 } ,
526 { 0xff, 0x00, 0xff },
527 { 0xff, 0xff, 0x00 },
528 { 0xff, 0xff, 0xff }
531 static const RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
532 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
533 { 0x00, 0x00, 0x00, 0x00 },
534 { 0x00, 0x00, 0x80, 0x00 },
535 { 0x00, 0x80, 0x00, 0x00 },
536 { 0x00, 0x80, 0x80, 0x00 },
537 { 0x80, 0x00, 0x00, 0x00 },
538 { 0x80, 0x00, 0x80, 0x00 },
539 { 0x80, 0x80, 0x00, 0x00 },
540 { 0xc0, 0xc0, 0xc0, 0x00 },
541 { 0xc0, 0xdc, 0xc0, 0x00 },
542 { 0xf0, 0xca, 0xa6, 0x00 },
543 { 0xf0, 0xfb, 0xff, 0x00 },
544 { 0xa4, 0xa0, 0xa0, 0x00 },
545 { 0x80, 0x80, 0x80, 0x00 },
546 { 0x00, 0x00, 0xf0, 0x00 },
547 { 0x00, 0xff, 0x00, 0x00 },
548 { 0x00, 0xff, 0xff, 0x00 },
549 { 0xff, 0x00, 0x00, 0x00 },
550 { 0xff, 0x00, 0xff, 0x00 },
551 { 0xff, 0xff, 0x00, 0x00 },
552 { 0xff, 0xff, 0xff, 0x00 }
555 static const RGBTRIPLE DefLogPaletteTriples[20] = { /* Copy of Default Logical Palette */
556 /* rgbBlue, rgbGreen, rgbRed */
557 { 0x00, 0x00, 0x00 },
558 { 0x00, 0x00, 0x80 },
559 { 0x00, 0x80, 0x00 },
560 { 0x00, 0x80, 0x80 },
561 { 0x80, 0x00, 0x00 },
562 { 0x80, 0x00, 0x80 },
563 { 0x80, 0x80, 0x00 },
564 { 0xc0, 0xc0, 0xc0 },
565 { 0xc0, 0xdc, 0xc0 },
566 { 0xf0, 0xca, 0xa6 },
567 { 0xf0, 0xfb, 0xff },
568 { 0xa4, 0xa0, 0xa0 },
569 { 0x80, 0x80, 0x80 },
570 { 0x00, 0x00, 0xf0 },
571 { 0x00, 0xff, 0x00 },
572 { 0x00, 0xff, 0xff },
573 { 0xff, 0x00, 0x00 },
574 { 0xff, 0x00, 0xff },
575 { 0xff, 0xff, 0x00 },
576 { 0xff, 0xff, 0xff}
580 /******************************************************************************
581 * GetDIBits [GDI32.@]
583 * Retrieves bits of bitmap and copies to buffer.
585 * RETURNS
586 * Success: Number of scan lines copied from bitmap
587 * Failure: 0
589 INT WINAPI GetDIBits(
590 HDC hdc, /* [in] Handle to device context */
591 HBITMAP hbitmap, /* [in] Handle to bitmap */
592 UINT startscan, /* [in] First scan line to set in dest bitmap */
593 UINT lines, /* [in] Number of scan lines to copy */
594 LPVOID bits, /* [out] Address of array for bitmap bits */
595 BITMAPINFO * info, /* [out] Address of structure with bitmap data */
596 UINT coloruse) /* [in] RGB or palette index */
598 DC * dc;
599 BITMAPOBJ * bmp;
600 int i;
601 int bitmap_type;
602 BOOL core_header;
603 LONG width;
604 LONG height;
605 WORD planes, bpp;
606 DWORD compr, size;
607 void* colorPtr;
608 RGBTRIPLE* rgbTriples;
609 RGBQUAD* rgbQuads;
611 if (!info) return 0;
613 bitmap_type = DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size);
614 if (bitmap_type == -1)
616 ERR("Invalid bitmap format\n");
617 return 0;
619 core_header = (bitmap_type == 0);
620 if (!(dc = get_dc_ptr( hdc )))
622 SetLastError( ERROR_INVALID_PARAMETER );
623 return 0;
625 update_dc( dc );
626 if (!(bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
628 release_dc_ptr( dc );
629 return 0;
632 colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
633 rgbTriples = colorPtr;
634 rgbQuads = colorPtr;
636 /* Transfer color info */
638 switch (bpp)
640 case 0: /* query bitmap info only */
641 if (core_header)
643 BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) info;
644 coreheader->bcWidth = bmp->bitmap.bmWidth;
645 coreheader->bcHeight = bmp->bitmap.bmHeight;
646 coreheader->bcPlanes = 1;
647 coreheader->bcBitCount = bmp->bitmap.bmBitsPixel;
649 else
651 info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
652 info->bmiHeader.biHeight = bmp->bitmap.bmHeight;
653 info->bmiHeader.biPlanes = 1;
654 info->bmiHeader.biSizeImage =
655 DIB_GetDIBImageBytes( bmp->bitmap.bmWidth,
656 bmp->bitmap.bmHeight,
657 bmp->bitmap.bmBitsPixel );
658 if (bmp->dib)
660 info->bmiHeader.biBitCount = bmp->dib->dsBm.bmBitsPixel;
661 switch (bmp->dib->dsBm.bmBitsPixel)
663 case 16:
664 case 32:
665 info->bmiHeader.biCompression = BI_BITFIELDS;
666 break;
667 default:
668 info->bmiHeader.biCompression = BI_RGB;
669 break;
672 else
674 info->bmiHeader.biCompression = (bmp->bitmap.bmBitsPixel > 8) ? BI_BITFIELDS : BI_RGB;
675 info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
677 info->bmiHeader.biXPelsPerMeter = 0;
678 info->bmiHeader.biYPelsPerMeter = 0;
679 info->bmiHeader.biClrUsed = 0;
680 info->bmiHeader.biClrImportant = 0;
682 /* Windows 2000 doesn't touch the additional struct members if
683 it's a BITMAPV4HEADER or a BITMAPV5HEADER */
685 lines = abs(bmp->bitmap.bmHeight);
686 goto done;
688 case 1:
689 case 4:
690 case 8:
691 if (!core_header) info->bmiHeader.biClrUsed = 0;
693 /* If the bitmap object already has a dib section at the
694 same color depth then get the color map from it */
695 if (bmp->dib && bmp->dib->dsBm.bmBitsPixel == bpp) {
696 if(coloruse == DIB_RGB_COLORS) {
697 unsigned int colors = min( bmp->nb_colors, 1 << bpp );
699 if (core_header)
701 /* Convert the color table (RGBQUAD to RGBTRIPLE) */
702 RGBTRIPLE* index = rgbTriples;
704 for (i=0; i < colors; i++, index++)
706 index->rgbtRed = bmp->color_table[i].rgbRed;
707 index->rgbtGreen = bmp->color_table[i].rgbGreen;
708 index->rgbtBlue = bmp->color_table[i].rgbBlue;
711 else
713 if (colors != 1 << bpp) info->bmiHeader.biClrUsed = colors;
714 memcpy(colorPtr, bmp->color_table, colors * sizeof(RGBQUAD));
717 else {
718 WORD *index = colorPtr;
719 for(i = 0; i < 1 << info->bmiHeader.biBitCount; i++, index++)
720 *index = i;
723 else {
724 if (coloruse == DIB_PAL_COLORS) {
725 for (i = 0; i < (1 << bpp); i++)
726 ((WORD *)colorPtr)[i] = (WORD)i;
728 else if(bpp > 1 && bpp == bmp->bitmap.bmBitsPixel) {
729 /* For color DDBs in native depth (mono DDBs always have
730 a black/white palette):
731 Generate the color map from the selected palette */
732 PALETTEENTRY palEntry[256];
734 memset( palEntry, 0, sizeof(palEntry) );
735 if (!GetPaletteEntries( dc->hPalette, 0, 1 << bmp->bitmap.bmBitsPixel, palEntry ))
737 release_dc_ptr( dc );
738 GDI_ReleaseObj( hbitmap );
739 return 0;
741 for (i = 0; i < (1 << bmp->bitmap.bmBitsPixel); i++) {
742 if (core_header)
744 rgbTriples[i].rgbtRed = palEntry[i].peRed;
745 rgbTriples[i].rgbtGreen = palEntry[i].peGreen;
746 rgbTriples[i].rgbtBlue = palEntry[i].peBlue;
748 else
750 rgbQuads[i].rgbRed = palEntry[i].peRed;
751 rgbQuads[i].rgbGreen = palEntry[i].peGreen;
752 rgbQuads[i].rgbBlue = palEntry[i].peBlue;
753 rgbQuads[i].rgbReserved = 0;
756 } else {
757 switch (bpp) {
758 case 1:
759 if (core_header)
761 rgbTriples[0].rgbtRed = rgbTriples[0].rgbtGreen =
762 rgbTriples[0].rgbtBlue = 0;
763 rgbTriples[1].rgbtRed = rgbTriples[1].rgbtGreen =
764 rgbTriples[1].rgbtBlue = 0xff;
766 else
768 rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen =
769 rgbQuads[0].rgbBlue = 0;
770 rgbQuads[0].rgbReserved = 0;
771 rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen =
772 rgbQuads[1].rgbBlue = 0xff;
773 rgbQuads[1].rgbReserved = 0;
775 break;
777 case 4:
778 if (core_header)
779 memcpy(colorPtr, EGAColorsTriples, sizeof(EGAColorsTriples));
780 else
781 memcpy(colorPtr, EGAColorsQuads, sizeof(EGAColorsQuads));
783 break;
785 case 8:
787 if (core_header)
789 INT r, g, b;
790 RGBTRIPLE *color;
792 memcpy(rgbTriples, DefLogPaletteTriples,
793 10 * sizeof(RGBTRIPLE));
794 memcpy(rgbTriples + 246, DefLogPaletteTriples + 10,
795 10 * sizeof(RGBTRIPLE));
796 color = rgbTriples + 10;
797 for(r = 0; r <= 5; r++) /* FIXME */
798 for(g = 0; g <= 5; g++)
799 for(b = 0; b <= 5; b++) {
800 color->rgbtRed = (r * 0xff) / 5;
801 color->rgbtGreen = (g * 0xff) / 5;
802 color->rgbtBlue = (b * 0xff) / 5;
803 color++;
806 else
808 INT r, g, b;
809 RGBQUAD *color;
811 memcpy(rgbQuads, DefLogPaletteQuads,
812 10 * sizeof(RGBQUAD));
813 memcpy(rgbQuads + 246, DefLogPaletteQuads + 10,
814 10 * sizeof(RGBQUAD));
815 color = rgbQuads + 10;
816 for(r = 0; r <= 5; r++) /* FIXME */
817 for(g = 0; g <= 5; g++)
818 for(b = 0; b <= 5; b++) {
819 color->rgbRed = (r * 0xff) / 5;
820 color->rgbGreen = (g * 0xff) / 5;
821 color->rgbBlue = (b * 0xff) / 5;
822 color->rgbReserved = 0;
823 color++;
830 break;
832 case 15:
833 if (info->bmiHeader.biCompression == BI_BITFIELDS)
835 ((PDWORD)info->bmiColors)[0] = 0x7c00;
836 ((PDWORD)info->bmiColors)[1] = 0x03e0;
837 ((PDWORD)info->bmiColors)[2] = 0x001f;
839 break;
841 case 16:
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] = 0xf800;
848 ((PDWORD)info->bmiColors)[1] = 0x07e0;
849 ((PDWORD)info->bmiColors)[2] = 0x001f;
852 break;
854 case 24:
855 case 32:
856 if (info->bmiHeader.biCompression == BI_BITFIELDS)
858 if (bmp->dib) memcpy( info->bmiColors, bmp->dib->dsBitfields, 3 * sizeof(DWORD) );
859 else
861 ((PDWORD)info->bmiColors)[0] = 0xff0000;
862 ((PDWORD)info->bmiColors)[1] = 0x00ff00;
863 ((PDWORD)info->bmiColors)[2] = 0x0000ff;
866 break;
869 if (bits && lines)
871 /* If the bitmap object already have a dib section that contains image data, get the bits from it */
872 if(bmp->dib && bmp->dib->dsBm.bmBitsPixel >= 15 && bpp >= 15)
874 /*FIXME: Only RGB dibs supported for now */
875 unsigned int srcwidth = bmp->dib->dsBm.bmWidth, srcwidthb = bmp->dib->dsBm.bmWidthBytes;
876 unsigned int dstwidth = width;
877 int dstwidthb = DIB_GetDIBWidthBytes( width, bpp );
878 LPBYTE dbits = bits, sbits = (LPBYTE) bmp->dib->dsBm.bmBits + (startscan * srcwidthb);
879 unsigned int x, y, width, widthb;
881 if ((height < 0) ^ (bmp->dib->dsBmih.biHeight < 0))
883 dbits = (LPBYTE)bits + (dstwidthb * (lines-1));
884 dstwidthb = -dstwidthb;
887 switch( bpp ) {
889 case 15:
890 case 16: /* 16 bpp dstDIB */
892 LPWORD dstbits = (LPWORD)dbits;
893 WORD rmask = 0x7c00, gmask= 0x03e0, bmask = 0x001f;
895 /* FIXME: BI_BITFIELDS not supported yet */
897 switch(bmp->dib->dsBm.bmBitsPixel) {
899 case 16: /* 16 bpp srcDIB -> 16 bpp dstDIB */
901 widthb = min(srcwidthb, abs(dstwidthb));
902 /* FIXME: BI_BITFIELDS not supported yet */
903 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
904 memcpy(dbits, sbits, widthb);
906 break;
908 case 24: /* 24 bpp srcDIB -> 16 bpp dstDIB */
910 LPBYTE srcbits = sbits;
912 width = min(srcwidth, dstwidth);
913 for( y = 0; y < lines; y++) {
914 for( x = 0; x < width; x++, srcbits += 3)
915 *dstbits++ = ((srcbits[0] >> 3) & bmask) |
916 (((WORD)srcbits[1] << 2) & gmask) |
917 (((WORD)srcbits[2] << 7) & rmask);
919 dstbits = (LPWORD)(dbits+=dstwidthb);
920 srcbits = (sbits += srcwidthb);
923 break;
925 case 32: /* 32 bpp srcDIB -> 16 bpp dstDIB */
927 LPDWORD srcbits = (LPDWORD)sbits;
928 DWORD val;
930 width = min(srcwidth, dstwidth);
931 for( y = 0; y < lines; y++) {
932 for( x = 0; x < width; x++ ) {
933 val = *srcbits++;
934 *dstbits++ = (WORD)(((val >> 3) & bmask) | ((val >> 6) & gmask) |
935 ((val >> 9) & rmask));
937 dstbits = (LPWORD)(dbits+=dstwidthb);
938 srcbits = (LPDWORD)(sbits+=srcwidthb);
941 break;
943 default: /* ? bit bmp -> 16 bit DIB */
944 FIXME("15/16 bit DIB %d bit bitmap\n",
945 bmp->bitmap.bmBitsPixel);
946 break;
949 break;
951 case 24: /* 24 bpp dstDIB */
953 LPBYTE dstbits = dbits;
955 switch(bmp->dib->dsBm.bmBitsPixel) {
957 case 16: /* 16 bpp srcDIB -> 24 bpp dstDIB */
959 LPWORD srcbits = (LPWORD)sbits;
960 WORD val;
962 width = min(srcwidth, dstwidth);
963 /* FIXME: BI_BITFIELDS not supported yet */
964 for( y = 0; y < lines; y++) {
965 for( x = 0; x < width; x++ ) {
966 val = *srcbits++;
967 *dstbits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07));
968 *dstbits++ = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07));
969 *dstbits++ = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07));
971 dstbits = dbits+=dstwidthb;
972 srcbits = (LPWORD)(sbits+=srcwidthb);
975 break;
977 case 24: /* 24 bpp srcDIB -> 24 bpp dstDIB */
979 widthb = min(srcwidthb, abs(dstwidthb));
980 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
981 memcpy(dbits, sbits, widthb);
983 break;
985 case 32: /* 32 bpp srcDIB -> 24 bpp dstDIB */
987 LPBYTE srcbits = sbits;
989 width = min(srcwidth, dstwidth);
990 for( y = 0; y < lines; y++) {
991 for( x = 0; x < width; x++, srcbits++ ) {
992 *dstbits++ = *srcbits++;
993 *dstbits++ = *srcbits++;
994 *dstbits++ = *srcbits++;
996 dstbits = dbits+=dstwidthb;
997 srcbits = sbits+=srcwidthb;
1000 break;
1002 default: /* ? bit bmp -> 24 bit DIB */
1003 FIXME("24 bit DIB %d bit bitmap\n",
1004 bmp->bitmap.bmBitsPixel);
1005 break;
1008 break;
1010 case 32: /* 32 bpp dstDIB */
1012 LPDWORD dstbits = (LPDWORD)dbits;
1014 /* FIXME: BI_BITFIELDS not supported yet */
1016 switch(bmp->dib->dsBm.bmBitsPixel) {
1017 case 16: /* 16 bpp srcDIB -> 32 bpp dstDIB */
1019 LPWORD srcbits = (LPWORD)sbits;
1020 DWORD val;
1022 width = min(srcwidth, dstwidth);
1023 /* FIXME: BI_BITFIELDS not supported yet */
1024 for( y = 0; y < lines; y++) {
1025 for( x = 0; x < width; x++ ) {
1026 val = (DWORD)*srcbits++;
1027 *dstbits++ = ((val << 3) & 0xf8) | ((val >> 2) & 0x07) |
1028 ((val << 6) & 0xf800) | ((val << 1) & 0x0700) |
1029 ((val << 9) & 0xf80000) | ((val << 4) & 0x070000);
1031 dstbits=(LPDWORD)(dbits+=dstwidthb);
1032 srcbits=(LPWORD)(sbits+=srcwidthb);
1035 break;
1037 case 24: /* 24 bpp srcDIB -> 32 bpp dstDIB */
1039 LPBYTE srcbits = sbits;
1041 width = min(srcwidth, dstwidth);
1042 for( y = 0; y < lines; y++) {
1043 for( x = 0; x < width; x++, srcbits+=3 )
1044 *dstbits++ = srcbits[0] |
1045 (srcbits[1] << 8) |
1046 (srcbits[2] << 16);
1047 dstbits=(LPDWORD)(dbits+=dstwidthb);
1048 srcbits=(sbits+=srcwidthb);
1051 break;
1053 case 32: /* 32 bpp srcDIB -> 32 bpp dstDIB */
1055 widthb = min(srcwidthb, abs(dstwidthb));
1056 /* FIXME: BI_BITFIELDS not supported yet */
1057 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb) {
1058 memcpy(dbits, sbits, widthb);
1061 break;
1063 default: /* ? bit bmp -> 32 bit DIB */
1064 FIXME("32 bit DIB %d bit bitmap\n",
1065 bmp->bitmap.bmBitsPixel);
1066 break;
1069 break;
1071 default: /* ? bit DIB */
1072 FIXME("Unsupported DIB depth %d\n", info->bmiHeader.biBitCount);
1073 break;
1076 /* Otherwise, get bits from the XImage */
1077 else
1079 if (!bmp->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) lines = 0;
1080 else
1082 if (bmp->funcs && bmp->funcs->pGetDIBits)
1083 lines = bmp->funcs->pGetDIBits( dc->physDev, hbitmap, startscan,
1084 lines, bits, info, coloruse );
1085 else
1086 lines = 0; /* FIXME: should copy from bmp->bitmap.bmBits */
1090 else lines = abs(height);
1092 /* The knowledge base article Q81498 ("DIBs and Their Uses") states that
1093 if bits == NULL and bpp != 0, only biSizeImage and the color table are
1094 filled in. */
1095 if (!core_header)
1097 /* FIXME: biSizeImage should be calculated according to the selected
1098 compression algorithm if biCompression != BI_RGB */
1099 info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes( width, height, bpp );
1100 TRACE("biSizeImage = %d, ", info->bmiHeader.biSizeImage);
1102 TRACE("biWidth = %d, biHeight = %d\n", width, height);
1104 done:
1105 release_dc_ptr( dc );
1106 GDI_ReleaseObj( hbitmap );
1107 return lines;
1111 /***********************************************************************
1112 * CreateDIBitmap (GDI32.@)
1114 * Creates a DDB (device dependent bitmap) from a DIB.
1115 * The DDB will have the same color depth as the reference DC.
1117 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
1118 DWORD init, LPCVOID bits, const BITMAPINFO *data,
1119 UINT coloruse )
1121 HBITMAP handle;
1122 LONG width;
1123 LONG height;
1124 WORD planes, bpp;
1125 DWORD compr, size;
1126 DC *dc;
1128 if (!header) return 0;
1130 if (DIB_GetBitmapInfo( header, &width, &height, &planes, &bpp, &compr, &size ) == -1) return 0;
1132 if (width < 0)
1134 TRACE("Bitmap has a negative width\n");
1135 return 0;
1138 /* Top-down DIBs have a negative height */
1139 if (height < 0) height = -height;
1141 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1142 hdc, header, init, bits, data, coloruse, width, height, bpp, compr);
1144 if (hdc == NULL)
1145 handle = CreateBitmap( width, height, 1, 1, NULL );
1146 else
1147 handle = CreateCompatibleBitmap( hdc, width, height );
1149 if (handle)
1151 if (init & CBM_INIT)
1153 if (SetDIBits( hdc, handle, 0, height, bits, data, coloruse ) == 0)
1155 DeleteObject( handle );
1156 handle = 0;
1160 else if (hdc && ((dc = get_dc_ptr( hdc )) != NULL) )
1162 if (!BITMAP_SetOwnerDC( handle, dc ))
1164 DeleteObject( handle );
1165 handle = 0;
1167 release_dc_ptr( dc );
1171 return handle;
1174 /* Copy/synthesize RGB palette from BITMAPINFO. Ripped from dlls/winex11.drv/dib.c */
1175 static void DIB_CopyColorTable( DC *dc, BITMAPOBJ *bmp, WORD coloruse, const BITMAPINFO *info )
1177 RGBQUAD *colorTable;
1178 unsigned int colors, 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(!bmi){
1253 if(bits) *bits = NULL;
1254 return NULL;
1257 if (((bitmap_type = DIB_GetBitmapInfo( &bmi->bmiHeader, &width, &height,
1258 &planes, &bpp, &compression, &sizeImage )) == -1))
1259 return 0;
1261 switch (bpp)
1263 case 16:
1264 case 32:
1265 if (compression == BI_BITFIELDS) break;
1266 /* fall through */
1267 case 1:
1268 case 4:
1269 case 8:
1270 case 24:
1271 if (compression == BI_RGB) break;
1272 /* fall through */
1273 default:
1274 WARN( "invalid %u bpp compression %u\n", bpp, compression );
1275 return 0;
1278 if (!(dib = HeapAlloc( GetProcessHeap(), 0, sizeof(*dib) ))) return 0;
1280 TRACE("format (%d,%d), planes %d, bpp %d, size %d, %s\n",
1281 width, height, planes, bpp, sizeImage, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1283 dib->dsBm.bmType = 0;
1284 dib->dsBm.bmWidth = width;
1285 dib->dsBm.bmHeight = height >= 0 ? height : -height;
1286 dib->dsBm.bmWidthBytes = DIB_GetDIBWidthBytes(width, bpp);
1287 dib->dsBm.bmPlanes = planes;
1288 dib->dsBm.bmBitsPixel = bpp;
1289 dib->dsBm.bmBits = NULL;
1291 if (!bitmap_type) /* core header */
1293 /* convert the BITMAPCOREHEADER to a BITMAPINFOHEADER */
1294 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1295 dib->dsBmih.biWidth = width;
1296 dib->dsBmih.biHeight = height;
1297 dib->dsBmih.biPlanes = planes;
1298 dib->dsBmih.biBitCount = bpp;
1299 dib->dsBmih.biCompression = compression;
1300 dib->dsBmih.biXPelsPerMeter = 0;
1301 dib->dsBmih.biYPelsPerMeter = 0;
1302 dib->dsBmih.biClrUsed = 0;
1303 dib->dsBmih.biClrImportant = 0;
1305 else
1307 /* truncate extended bitmap headers (BITMAPV4HEADER etc.) */
1308 dib->dsBmih = bmi->bmiHeader;
1309 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1312 /* set number of entries in bmi.bmiColors table */
1313 if( bpp <= 8 )
1314 dib->dsBmih.biClrUsed = 1 << bpp;
1316 dib->dsBmih.biSizeImage = dib->dsBm.bmWidthBytes * dib->dsBm.bmHeight;
1318 /* set dsBitfields values */
1319 if (usage == DIB_PAL_COLORS || bpp <= 8)
1321 dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
1323 else switch( bpp )
1325 case 15:
1326 case 16:
1327 dib->dsBitfields[0] = (compression == BI_BITFIELDS) ? *(const DWORD *)bmi->bmiColors : 0x7c00;
1328 dib->dsBitfields[1] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 1) : 0x03e0;
1329 dib->dsBitfields[2] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 2) : 0x001f;
1330 break;
1331 case 24:
1332 case 32:
1333 dib->dsBitfields[0] = (compression == BI_BITFIELDS) ? *(const DWORD *)bmi->bmiColors : 0xff0000;
1334 dib->dsBitfields[1] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 1) : 0x00ff00;
1335 dib->dsBitfields[2] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 2) : 0x0000ff;
1336 break;
1339 /* get storage location for DIB bits */
1341 if (section)
1343 SYSTEM_INFO SystemInfo;
1344 DWORD mapOffset;
1345 INT mapSize;
1347 GetSystemInfo( &SystemInfo );
1348 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
1349 mapSize = dib->dsBmih.biSizeImage + (offset - mapOffset);
1350 mapBits = MapViewOfFile( section, FILE_MAP_ALL_ACCESS, 0, mapOffset, mapSize );
1351 if (mapBits) dib->dsBm.bmBits = (char *)mapBits + (offset - mapOffset);
1353 else
1355 offset = 0;
1356 dib->dsBm.bmBits = VirtualAlloc( NULL, dib->dsBmih.biSizeImage,
1357 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
1359 dib->dshSection = section;
1360 dib->dsOffset = offset;
1362 if (!dib->dsBm.bmBits)
1364 HeapFree( GetProcessHeap(), 0, dib );
1365 return 0;
1368 /* If the reference hdc is null, take the desktop dc */
1369 if (hdc == 0)
1371 hdc = CreateCompatibleDC(0);
1372 bDesktopDC = TRUE;
1375 if (!(dc = get_dc_ptr( hdc ))) goto error;
1377 /* create Device Dependent Bitmap and add DIB pointer */
1378 ret = CreateBitmap( dib->dsBm.bmWidth, dib->dsBm.bmHeight, 1,
1379 (bpp == 1) ? 1 : GetDeviceCaps(hdc, BITSPIXEL), NULL );
1381 if (ret && ((bmp = GDI_GetObjPtr(ret, OBJ_BITMAP))))
1383 bmp->dib = dib;
1384 bmp->funcs = dc->funcs;
1385 /* create local copy of DIB palette */
1386 if (bpp <= 8) DIB_CopyColorTable( dc, bmp, usage, bmi );
1387 GDI_ReleaseObj( ret );
1389 if (dc->funcs->pCreateDIBSection)
1391 if (!dc->funcs->pCreateDIBSection(dc->physDev, ret, bmi, usage))
1393 DeleteObject( ret );
1394 ret = 0;
1399 release_dc_ptr( dc );
1400 if (bDesktopDC) DeleteDC( hdc );
1401 if (ret && bits) *bits = dib->dsBm.bmBits;
1402 return ret;
1404 error:
1405 if (bDesktopDC) DeleteDC( hdc );
1406 if (section) UnmapViewOfFile( mapBits );
1407 else if (!offset) VirtualFree( dib->dsBm.bmBits, 0, MEM_RELEASE );
1408 HeapFree( GetProcessHeap(), 0, dib );
1409 return 0;