push 4bc2235780487bb0501963d375d42d158faac784
[wine/hacks.git] / dlls / gdi32 / dib.c
blobffd6f3131f7fccaed700c0a05a2e7468689eb79d
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 int colors, 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 return sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD) + colors *
143 ((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 static int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
155 LONG *height, WORD *planes, WORD *bpp, DWORD *compr, DWORD *size )
157 if (header->biSize == sizeof(BITMAPCOREHEADER))
159 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)header;
160 *width = core->bcWidth;
161 *height = core->bcHeight;
162 *planes = core->bcPlanes;
163 *bpp = core->bcBitCount;
164 *compr = 0;
165 *size = 0;
166 return 0;
168 if (header->biSize >= sizeof(BITMAPINFOHEADER)) /* assume BITMAPINFOHEADER */
170 *width = header->biWidth;
171 *height = header->biHeight;
172 *planes = header->biPlanes;
173 *bpp = header->biBitCount;
174 *compr = header->biCompression;
175 *size = header->biSizeImage;
176 return 1;
178 ERR("(%d): unknown/wrong size for header\n", header->biSize );
179 return -1;
183 /***********************************************************************
184 * StretchDIBits (GDI32.@)
186 INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst,
187 INT heightDst, INT xSrc, INT ySrc, INT widthSrc,
188 INT heightSrc, const void *bits,
189 const BITMAPINFO *info, UINT wUsage, DWORD dwRop )
191 DC *dc;
192 INT ret;
194 if (!bits || !info)
195 return 0;
197 if (!(dc = get_dc_ptr( hdc ))) return 0;
199 if(dc->funcs->pStretchDIBits)
201 update_dc( dc );
202 ret = dc->funcs->pStretchDIBits(dc->physDev, xDst, yDst, widthDst,
203 heightDst, xSrc, ySrc, widthSrc,
204 heightSrc, bits, info, wUsage, dwRop);
205 release_dc_ptr( dc );
207 else /* use StretchBlt */
209 LONG height;
210 LONG width;
211 WORD planes, bpp;
212 DWORD compr, size;
213 HBITMAP hBitmap;
214 BOOL fastpath = FALSE;
216 release_dc_ptr( dc );
218 if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size ) == -1)
220 ERR("Invalid bitmap\n");
221 return 0;
224 if (width < 0)
226 ERR("Bitmap has a negative width\n");
227 return 0;
230 hBitmap = GetCurrentObject(hdc, OBJ_BITMAP);
232 if (xDst == 0 && yDst == 0 && xSrc == 0 && ySrc == 0 &&
233 widthDst == widthSrc && heightDst == heightSrc &&
234 info->bmiHeader.biCompression == BI_RGB &&
235 dwRop == SRCCOPY)
237 BITMAPOBJ *bmp;
238 if ((bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBitmap, BITMAP_MAGIC )))
240 if (bmp->bitmap.bmBitsPixel == bpp &&
241 bmp->bitmap.bmWidth == widthSrc &&
242 bmp->bitmap.bmHeight == heightSrc &&
243 bmp->bitmap.bmPlanes == planes)
244 fastpath = TRUE;
245 GDI_ReleaseObj( hBitmap );
249 if (fastpath)
251 /* fast path */
252 TRACE("using fast path\n");
253 ret = SetDIBits( hdc, hBitmap, 0, height, bits, info, wUsage);
255 else
257 /* slow path - need to use StretchBlt */
258 HBITMAP hOldBitmap;
259 HPALETTE hpal = NULL;
260 HDC hdcMem;
262 hdcMem = CreateCompatibleDC( hdc );
263 hBitmap = CreateCompatibleBitmap(hdc, width, height);
264 hOldBitmap = SelectObject( hdcMem, hBitmap );
265 if(wUsage == DIB_PAL_COLORS)
267 hpal = GetCurrentObject(hdc, OBJ_PAL);
268 hpal = SelectPalette(hdcMem, hpal, FALSE);
271 if (info->bmiHeader.biCompression == BI_RLE4 ||
272 info->bmiHeader.biCompression == BI_RLE8) {
274 /* when RLE compression is used, there may be some gaps (ie the DIB doesn't
275 * contain all the rectangle described in bmiHeader, but only part of it.
276 * This mean that those undescribed pixels must be left untouched.
277 * So, we first copy on a memory bitmap the current content of the
278 * destination rectangle, blit the DIB bits on top of it - hence leaving
279 * the gaps untouched -, and blitting the rectangle back.
280 * This insure that gaps are untouched on the destination rectangle
281 * Not doing so leads to trashed images (the gaps contain what was on the
282 * memory bitmap => generally black or garbage)
283 * Unfortunately, RLE DIBs without gaps will be slowed down. But this is
284 * another speed vs correctness issue. Anyway, if speed is needed, then the
285 * pStretchDIBits function shall be implemented.
286 * ericP (2000/09/09)
289 /* copy existing bitmap from destination dc */
290 StretchBlt( hdcMem, xSrc, abs(height) - heightSrc - ySrc,
291 widthSrc, heightSrc, hdc, xDst, yDst, widthDst, heightDst,
292 dwRop );
295 ret = SetDIBits(hdcMem, hBitmap, 0, height, bits, info, wUsage);
297 /* Origin for DIBitmap may be bottom left (positive biHeight) or top
298 left (negative biHeight) */
299 if (ret) StretchBlt( hdc, xDst, yDst, widthDst, heightDst,
300 hdcMem, xSrc, abs(height) - heightSrc - ySrc,
301 widthSrc, heightSrc, dwRop );
302 if(hpal)
303 SelectPalette(hdcMem, hpal, FALSE);
304 SelectObject( hdcMem, hOldBitmap );
305 DeleteDC( hdcMem );
306 DeleteObject( hBitmap );
309 return ret;
313 /******************************************************************************
314 * SetDIBits [GDI32.@]
316 * Sets pixels in a bitmap using colors from DIB.
318 * PARAMS
319 * hdc [I] Handle to device context
320 * hbitmap [I] Handle to bitmap
321 * startscan [I] Starting scan line
322 * lines [I] Number of scan lines
323 * bits [I] Array of bitmap bits
324 * info [I] Address of structure with data
325 * coloruse [I] Type of color indexes to use
327 * RETURNS
328 * Success: Number of scan lines copied
329 * Failure: 0
331 INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
332 UINT lines, LPCVOID bits, const BITMAPINFO *info,
333 UINT coloruse )
335 DC *dc;
336 BITMAPOBJ *bitmap;
337 INT result = 0;
339 if (!(dc = get_dc_ptr( hdc )))
341 if (coloruse == DIB_RGB_COLORS) FIXME( "shouldn't require a DC for DIB_RGB_COLORS\n" );
342 return 0;
345 update_dc( dc );
347 if (!(bitmap = GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
349 release_dc_ptr( dc );
350 return 0;
353 if (!bitmap->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) goto done;
355 result = lines;
356 if (bitmap->funcs)
358 if (bitmap->funcs != dc->funcs)
359 ERR( "not supported: DDB bitmap %p not belonging to device %p\n", hbitmap, hdc );
360 else if (dc->funcs->pSetDIBits)
361 result = dc->funcs->pSetDIBits( dc->physDev, hbitmap, startscan, lines,
362 bits, info, coloruse );
365 done:
366 GDI_ReleaseObj( hbitmap );
367 release_dc_ptr( dc );
368 return result;
372 /***********************************************************************
373 * SetDIBitsToDevice (GDI32.@)
375 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
376 DWORD cy, INT xSrc, INT ySrc, UINT startscan,
377 UINT lines, LPCVOID bits, const BITMAPINFO *info,
378 UINT coloruse )
380 INT ret;
381 DC *dc;
383 if (!bits) return 0;
385 if (!(dc = get_dc_ptr( hdc ))) return 0;
387 if(dc->funcs->pSetDIBitsToDevice)
389 update_dc( dc );
390 ret = dc->funcs->pSetDIBitsToDevice( dc->physDev, xDest, yDest, cx, cy, xSrc,
391 ySrc, startscan, lines, bits,
392 info, coloruse );
394 else {
395 FIXME("unimplemented on hdc %p\n", hdc);
396 ret = 0;
399 release_dc_ptr( dc );
400 return ret;
403 /***********************************************************************
404 * SetDIBColorTable (GDI32.@)
406 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, CONST RGBQUAD *colors )
408 DC * dc;
409 UINT result = 0;
410 BITMAPOBJ * bitmap;
412 if (!(dc = get_dc_ptr( hdc ))) return 0;
414 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, BITMAP_MAGIC )))
416 /* Check if currently selected bitmap is a DIB */
417 if (bitmap->color_table)
419 if (startpos < bitmap->nb_colors)
421 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
422 memcpy(bitmap->color_table + startpos, colors, entries * sizeof(RGBQUAD));
423 result = entries;
426 GDI_ReleaseObj( dc->hBitmap );
429 if (dc->funcs->pSetDIBColorTable)
430 dc->funcs->pSetDIBColorTable(dc->physDev, startpos, entries, colors);
432 release_dc_ptr( dc );
433 return result;
437 /***********************************************************************
438 * GetDIBColorTable (GDI32.@)
440 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
442 DC * dc;
443 UINT result = 0;
445 if (!(dc = get_dc_ptr( hdc ))) return 0;
447 if (dc->funcs->pGetDIBColorTable)
448 result = dc->funcs->pGetDIBColorTable(dc->physDev, startpos, entries, colors);
449 else
451 BITMAPOBJ *bitmap = GDI_GetObjPtr( dc->hBitmap, BITMAP_MAGIC );
452 if (bitmap)
454 /* Check if currently selected bitmap is a DIB */
455 if (bitmap->color_table)
457 if (startpos < bitmap->nb_colors)
459 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
460 memcpy(colors, bitmap->color_table + startpos, entries * sizeof(RGBQUAD));
461 result = entries;
464 GDI_ReleaseObj( dc->hBitmap );
467 release_dc_ptr( dc );
468 return result;
471 /* FIXME the following two structs should be combined with __sysPalTemplate in
472 objects/color.c - this should happen after de-X11-ing both of these
473 files.
474 NB. RGBQUAD and PALETTEENTRY have different orderings of red, green
475 and blue - sigh */
477 static const RGBQUAD EGAColorsQuads[16] = {
478 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
479 { 0x00, 0x00, 0x00, 0x00 },
480 { 0x00, 0x00, 0x80, 0x00 },
481 { 0x00, 0x80, 0x00, 0x00 },
482 { 0x00, 0x80, 0x80, 0x00 },
483 { 0x80, 0x00, 0x00, 0x00 },
484 { 0x80, 0x00, 0x80, 0x00 },
485 { 0x80, 0x80, 0x00, 0x00 },
486 { 0x80, 0x80, 0x80, 0x00 },
487 { 0xc0, 0xc0, 0xc0, 0x00 },
488 { 0x00, 0x00, 0xff, 0x00 },
489 { 0x00, 0xff, 0x00, 0x00 },
490 { 0x00, 0xff, 0xff, 0x00 },
491 { 0xff, 0x00, 0x00, 0x00 },
492 { 0xff, 0x00, 0xff, 0x00 },
493 { 0xff, 0xff, 0x00, 0x00 },
494 { 0xff, 0xff, 0xff, 0x00 }
497 static const RGBTRIPLE EGAColorsTriples[16] = {
498 /* rgbBlue, rgbGreen, rgbRed */
499 { 0x00, 0x00, 0x00 },
500 { 0x00, 0x00, 0x80 },
501 { 0x00, 0x80, 0x00 },
502 { 0x00, 0x80, 0x80 },
503 { 0x80, 0x00, 0x00 },
504 { 0x80, 0x00, 0x80 },
505 { 0x80, 0x80, 0x00 },
506 { 0x80, 0x80, 0x80 },
507 { 0xc0, 0xc0, 0xc0 },
508 { 0x00, 0x00, 0xff },
509 { 0x00, 0xff, 0x00 },
510 { 0x00, 0xff, 0xff },
511 { 0xff, 0x00, 0x00 } ,
512 { 0xff, 0x00, 0xff },
513 { 0xff, 0xff, 0x00 },
514 { 0xff, 0xff, 0xff }
517 static const RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
518 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
519 { 0x00, 0x00, 0x00, 0x00 },
520 { 0x00, 0x00, 0x80, 0x00 },
521 { 0x00, 0x80, 0x00, 0x00 },
522 { 0x00, 0x80, 0x80, 0x00 },
523 { 0x80, 0x00, 0x00, 0x00 },
524 { 0x80, 0x00, 0x80, 0x00 },
525 { 0x80, 0x80, 0x00, 0x00 },
526 { 0xc0, 0xc0, 0xc0, 0x00 },
527 { 0xc0, 0xdc, 0xc0, 0x00 },
528 { 0xf0, 0xca, 0xa6, 0x00 },
529 { 0xf0, 0xfb, 0xff, 0x00 },
530 { 0xa4, 0xa0, 0xa0, 0x00 },
531 { 0x80, 0x80, 0x80, 0x00 },
532 { 0x00, 0x00, 0xf0, 0x00 },
533 { 0x00, 0xff, 0x00, 0x00 },
534 { 0x00, 0xff, 0xff, 0x00 },
535 { 0xff, 0x00, 0x00, 0x00 },
536 { 0xff, 0x00, 0xff, 0x00 },
537 { 0xff, 0xff, 0x00, 0x00 },
538 { 0xff, 0xff, 0xff, 0x00 }
541 static const RGBTRIPLE DefLogPaletteTriples[20] = { /* Copy of Default Logical Palette */
542 /* rgbBlue, rgbGreen, rgbRed */
543 { 0x00, 0x00, 0x00 },
544 { 0x00, 0x00, 0x80 },
545 { 0x00, 0x80, 0x00 },
546 { 0x00, 0x80, 0x80 },
547 { 0x80, 0x00, 0x00 },
548 { 0x80, 0x00, 0x80 },
549 { 0x80, 0x80, 0x00 },
550 { 0xc0, 0xc0, 0xc0 },
551 { 0xc0, 0xdc, 0xc0 },
552 { 0xf0, 0xca, 0xa6 },
553 { 0xf0, 0xfb, 0xff },
554 { 0xa4, 0xa0, 0xa0 },
555 { 0x80, 0x80, 0x80 },
556 { 0x00, 0x00, 0xf0 },
557 { 0x00, 0xff, 0x00 },
558 { 0x00, 0xff, 0xff },
559 { 0xff, 0x00, 0x00 },
560 { 0xff, 0x00, 0xff },
561 { 0xff, 0xff, 0x00 },
562 { 0xff, 0xff, 0xff}
566 /******************************************************************************
567 * GetDIBits [GDI32.@]
569 * Retrieves bits of bitmap and copies to buffer.
571 * RETURNS
572 * Success: Number of scan lines copied from bitmap
573 * Failure: 0
575 INT WINAPI GetDIBits(
576 HDC hdc, /* [in] Handle to device context */
577 HBITMAP hbitmap, /* [in] Handle to bitmap */
578 UINT startscan, /* [in] First scan line to set in dest bitmap */
579 UINT lines, /* [in] Number of scan lines to copy */
580 LPVOID bits, /* [out] Address of array for bitmap bits */
581 BITMAPINFO * info, /* [out] Address of structure with bitmap data */
582 UINT coloruse) /* [in] RGB or palette index */
584 DC * dc;
585 BITMAPOBJ * bmp;
586 int i;
587 int bitmap_type;
588 BOOL core_header;
589 LONG width;
590 LONG height;
591 WORD planes, bpp;
592 DWORD compr, size;
593 void* colorPtr;
594 RGBTRIPLE* rgbTriples;
595 RGBQUAD* rgbQuads;
597 if (!info) return 0;
599 bitmap_type = DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size);
600 if (bitmap_type == -1)
602 ERR("Invalid bitmap format\n");
603 return 0;
605 core_header = (bitmap_type == 0);
606 if (!(dc = get_dc_ptr( hdc )))
608 SetLastError( ERROR_INVALID_PARAMETER );
609 return 0;
611 update_dc( dc );
612 if (!(bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
614 release_dc_ptr( dc );
615 return 0;
618 colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
619 rgbTriples = (RGBTRIPLE *) colorPtr;
620 rgbQuads = (RGBQUAD *) colorPtr;
622 /* Transfer color info */
624 switch (bpp)
626 case 0: /* query bitmap info only */
627 if (core_header)
629 BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) info;
630 coreheader->bcWidth = bmp->bitmap.bmWidth;
631 coreheader->bcHeight = bmp->bitmap.bmHeight;
632 coreheader->bcPlanes = 1;
633 coreheader->bcBitCount = bmp->bitmap.bmBitsPixel;
635 else
637 info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
638 info->bmiHeader.biHeight = bmp->bitmap.bmHeight;
639 info->bmiHeader.biPlanes = 1;
640 info->bmiHeader.biSizeImage =
641 DIB_GetDIBImageBytes( bmp->bitmap.bmWidth,
642 bmp->bitmap.bmHeight,
643 bmp->bitmap.bmBitsPixel );
644 info->bmiHeader.biCompression = (bmp->bitmap.bmBitsPixel > 8) ? BI_BITFIELDS : BI_RGB;
645 switch(bmp->bitmap.bmBitsPixel)
647 case 15:
648 info->bmiHeader.biBitCount = 16;
649 break;
650 case 24:
651 info->bmiHeader.biBitCount = 32;
652 break;
653 default:
654 info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
655 break;
657 info->bmiHeader.biXPelsPerMeter = 0;
658 info->bmiHeader.biYPelsPerMeter = 0;
659 info->bmiHeader.biClrUsed = 0;
660 info->bmiHeader.biClrImportant = 0;
662 /* Windows 2000 doesn't touch the additional struct members if
663 it's a BITMAPV4HEADER or a BITMAPV5HEADER */
665 lines = abs(bmp->bitmap.bmHeight);
666 goto done;
668 case 1:
669 case 4:
670 case 8:
671 if (!core_header) info->bmiHeader.biClrUsed = 0;
673 /* If the bitmap object already has a dib section at the
674 same color depth then get the color map from it */
675 if (bmp->dib && bmp->dib->dsBm.bmBitsPixel == bpp) {
676 if(coloruse == DIB_RGB_COLORS) {
677 unsigned int colors = min( bmp->nb_colors, 1 << bpp );
679 if (core_header)
681 /* Convert the color table (RGBQUAD to RGBTRIPLE) */
682 RGBTRIPLE* index = rgbTriples;
684 for (i=0; i < colors; i++, index++)
686 index->rgbtRed = bmp->color_table[i].rgbRed;
687 index->rgbtGreen = bmp->color_table[i].rgbGreen;
688 index->rgbtBlue = bmp->color_table[i].rgbBlue;
691 else
693 if (colors != 1 << bpp) info->bmiHeader.biClrUsed = colors;
694 memcpy(colorPtr, bmp->color_table, colors * sizeof(RGBQUAD));
697 else {
698 WORD *index = colorPtr;
699 for(i = 0; i < 1 << info->bmiHeader.biBitCount; i++, index++)
700 *index = i;
703 else {
704 if(bpp >= bmp->bitmap.bmBitsPixel) {
705 /* Generate the color map from the selected palette */
706 PALETTEENTRY palEntry[256];
708 memset( palEntry, 0, sizeof(palEntry) );
709 if (!GetPaletteEntries( dc->hPalette, 0, 1 << bmp->bitmap.bmBitsPixel, palEntry ))
711 release_dc_ptr( dc );
712 GDI_ReleaseObj( hbitmap );
713 return 0;
715 for (i = 0; i < (1 << bmp->bitmap.bmBitsPixel); i++) {
716 if (coloruse == DIB_RGB_COLORS) {
717 if (core_header)
719 rgbTriples[i].rgbtRed = palEntry[i].peRed;
720 rgbTriples[i].rgbtGreen = palEntry[i].peGreen;
721 rgbTriples[i].rgbtBlue = palEntry[i].peBlue;
723 else
725 rgbQuads[i].rgbRed = palEntry[i].peRed;
726 rgbQuads[i].rgbGreen = palEntry[i].peGreen;
727 rgbQuads[i].rgbBlue = palEntry[i].peBlue;
728 rgbQuads[i].rgbReserved = 0;
731 else ((WORD *)colorPtr)[i] = (WORD)i;
733 } else {
734 switch (bpp) {
735 case 1:
736 if (core_header)
738 rgbTriples[0].rgbtRed = rgbTriples[0].rgbtGreen =
739 rgbTriples[0].rgbtBlue = 0;
740 rgbTriples[1].rgbtRed = rgbTriples[1].rgbtGreen =
741 rgbTriples[1].rgbtBlue = 0xff;
743 else
745 rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen =
746 rgbQuads[0].rgbBlue = 0;
747 rgbQuads[0].rgbReserved = 0;
748 rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen =
749 rgbQuads[1].rgbBlue = 0xff;
750 rgbQuads[1].rgbReserved = 0;
752 break;
754 case 4:
755 if (core_header)
756 memcpy(colorPtr, EGAColorsTriples, sizeof(EGAColorsTriples));
757 else
758 memcpy(colorPtr, EGAColorsQuads, sizeof(EGAColorsQuads));
760 break;
762 case 8:
764 if (core_header)
766 INT r, g, b;
767 RGBTRIPLE *color;
769 memcpy(rgbTriples, DefLogPaletteTriples,
770 10 * sizeof(RGBTRIPLE));
771 memcpy(rgbTriples + 246, DefLogPaletteTriples + 10,
772 10 * sizeof(RGBTRIPLE));
773 color = rgbTriples + 10;
774 for(r = 0; r <= 5; r++) /* FIXME */
775 for(g = 0; g <= 5; g++)
776 for(b = 0; b <= 5; b++) {
777 color->rgbtRed = (r * 0xff) / 5;
778 color->rgbtGreen = (g * 0xff) / 5;
779 color->rgbtBlue = (b * 0xff) / 5;
780 color++;
783 else
785 INT r, g, b;
786 RGBQUAD *color;
788 memcpy(rgbQuads, DefLogPaletteQuads,
789 10 * sizeof(RGBQUAD));
790 memcpy(rgbQuads + 246, DefLogPaletteQuads + 10,
791 10 * sizeof(RGBQUAD));
792 color = rgbQuads + 10;
793 for(r = 0; r <= 5; r++) /* FIXME */
794 for(g = 0; g <= 5; g++)
795 for(b = 0; b <= 5; b++) {
796 color->rgbRed = (r * 0xff) / 5;
797 color->rgbGreen = (g * 0xff) / 5;
798 color->rgbBlue = (b * 0xff) / 5;
799 color->rgbReserved = 0;
800 color++;
807 break;
809 case 15:
810 if (info->bmiHeader.biCompression == BI_BITFIELDS)
812 ((PDWORD)info->bmiColors)[0] = 0x7c00;
813 ((PDWORD)info->bmiColors)[1] = 0x03e0;
814 ((PDWORD)info->bmiColors)[2] = 0x001f;
816 break;
818 case 16:
819 if (info->bmiHeader.biCompression == BI_BITFIELDS)
821 ((PDWORD)info->bmiColors)[0] = 0xf800;
822 ((PDWORD)info->bmiColors)[1] = 0x07e0;
823 ((PDWORD)info->bmiColors)[2] = 0x001f;
825 break;
827 case 24:
828 case 32:
829 if (info->bmiHeader.biCompression == BI_BITFIELDS)
831 ((PDWORD)info->bmiColors)[0] = 0xff0000;
832 ((PDWORD)info->bmiColors)[1] = 0x00ff00;
833 ((PDWORD)info->bmiColors)[2] = 0x0000ff;
835 break;
838 if (bits && lines)
840 /* If the bitmap object already have a dib section that contains image data, get the bits from it */
841 if(bmp->dib && bmp->dib->dsBm.bmBitsPixel >= 15 && bpp >= 15)
843 /*FIXME: Only RGB dibs supported for now */
844 unsigned int srcwidth = bmp->dib->dsBm.bmWidth, srcwidthb = bmp->dib->dsBm.bmWidthBytes;
845 unsigned int dstwidth = width;
846 int dstwidthb = DIB_GetDIBWidthBytes( width, bpp );
847 LPBYTE dbits = bits, sbits = (LPBYTE) bmp->dib->dsBm.bmBits + (startscan * srcwidthb);
848 unsigned int x, y, width, widthb;
850 if ((height < 0) ^ (bmp->dib->dsBmih.biHeight < 0))
852 dbits = (LPBYTE)bits + (dstwidthb * (lines-1));
853 dstwidthb = -dstwidthb;
856 switch( bpp ) {
858 case 15:
859 case 16: /* 16 bpp dstDIB */
861 LPWORD dstbits = (LPWORD)dbits;
862 WORD rmask = 0x7c00, gmask= 0x03e0, bmask = 0x001f;
864 /* FIXME: BI_BITFIELDS not supported yet */
866 switch(bmp->dib->dsBm.bmBitsPixel) {
868 case 16: /* 16 bpp srcDIB -> 16 bpp dstDIB */
870 widthb = min(srcwidthb, abs(dstwidthb));
871 /* FIXME: BI_BITFIELDS not supported yet */
872 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
873 memcpy(dbits, sbits, widthb);
875 break;
877 case 24: /* 24 bpp srcDIB -> 16 bpp dstDIB */
879 LPBYTE srcbits = sbits;
881 width = min(srcwidth, dstwidth);
882 for( y = 0; y < lines; y++) {
883 for( x = 0; x < width; x++, srcbits += 3)
884 *dstbits++ = ((srcbits[0] >> 3) & bmask) |
885 (((WORD)srcbits[1] << 2) & gmask) |
886 (((WORD)srcbits[2] << 7) & rmask);
888 dstbits = (LPWORD)(dbits+=dstwidthb);
889 srcbits = (sbits += srcwidthb);
892 break;
894 case 32: /* 32 bpp srcDIB -> 16 bpp dstDIB */
896 LPDWORD srcbits = (LPDWORD)sbits;
897 DWORD val;
899 width = min(srcwidth, dstwidth);
900 for( y = 0; y < lines; y++) {
901 for( x = 0; x < width; x++ ) {
902 val = *srcbits++;
903 *dstbits++ = (WORD)(((val >> 3) & bmask) | ((val >> 6) & gmask) |
904 ((val >> 9) & rmask));
906 dstbits = (LPWORD)(dbits+=dstwidthb);
907 srcbits = (LPDWORD)(sbits+=srcwidthb);
910 break;
912 default: /* ? bit bmp -> 16 bit DIB */
913 FIXME("15/16 bit DIB %d bit bitmap\n",
914 bmp->bitmap.bmBitsPixel);
915 break;
918 break;
920 case 24: /* 24 bpp dstDIB */
922 LPBYTE dstbits = dbits;
924 switch(bmp->dib->dsBm.bmBitsPixel) {
926 case 16: /* 16 bpp srcDIB -> 24 bpp dstDIB */
928 LPWORD srcbits = (LPWORD)sbits;
929 WORD val;
931 width = min(srcwidth, dstwidth);
932 /* FIXME: BI_BITFIELDS not supported yet */
933 for( y = 0; y < lines; y++) {
934 for( x = 0; x < width; x++ ) {
935 val = *srcbits++;
936 *dstbits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07));
937 *dstbits++ = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07));
938 *dstbits++ = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07));
940 dstbits = dbits+=dstwidthb;
941 srcbits = (LPWORD)(sbits+=srcwidthb);
944 break;
946 case 24: /* 24 bpp srcDIB -> 24 bpp dstDIB */
948 widthb = min(srcwidthb, abs(dstwidthb));
949 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
950 memcpy(dbits, sbits, widthb);
952 break;
954 case 32: /* 32 bpp srcDIB -> 24 bpp dstDIB */
956 LPBYTE srcbits = sbits;
958 width = min(srcwidth, dstwidth);
959 for( y = 0; y < lines; y++) {
960 for( x = 0; x < width; x++, srcbits++ ) {
961 *dstbits++ = *srcbits++;
962 *dstbits++ = *srcbits++;
963 *dstbits++ = *srcbits++;
965 dstbits = dbits+=dstwidthb;
966 srcbits = sbits+=srcwidthb;
969 break;
971 default: /* ? bit bmp -> 24 bit DIB */
972 FIXME("24 bit DIB %d bit bitmap\n",
973 bmp->bitmap.bmBitsPixel);
974 break;
977 break;
979 case 32: /* 32 bpp dstDIB */
981 LPDWORD dstbits = (LPDWORD)dbits;
983 /* FIXME: BI_BITFIELDS not supported yet */
985 switch(bmp->dib->dsBm.bmBitsPixel) {
986 case 16: /* 16 bpp srcDIB -> 32 bpp dstDIB */
988 LPWORD srcbits = (LPWORD)sbits;
989 DWORD val;
991 width = min(srcwidth, dstwidth);
992 /* FIXME: BI_BITFIELDS not supported yet */
993 for( y = 0; y < lines; y++) {
994 for( x = 0; x < width; x++ ) {
995 val = (DWORD)*srcbits++;
996 *dstbits++ = ((val << 3) & 0xf8) | ((val >> 2) & 0x07) |
997 ((val << 6) & 0xf800) | ((val << 1) & 0x0700) |
998 ((val << 9) & 0xf80000) | ((val << 4) & 0x070000);
1000 dstbits=(LPDWORD)(dbits+=dstwidthb);
1001 srcbits=(LPWORD)(sbits+=srcwidthb);
1004 break;
1006 case 24: /* 24 bpp srcDIB -> 32 bpp dstDIB */
1008 LPBYTE srcbits = sbits;
1010 width = min(srcwidth, dstwidth);
1011 for( y = 0; y < lines; y++) {
1012 for( x = 0; x < width; x++, srcbits+=3 )
1013 *dstbits++ = srcbits[0] |
1014 (srcbits[1] << 8) |
1015 (srcbits[2] << 16);
1016 dstbits=(LPDWORD)(dbits+=dstwidthb);
1017 srcbits=(sbits+=srcwidthb);
1020 break;
1022 case 32: /* 32 bpp srcDIB -> 32 bpp dstDIB */
1024 widthb = min(srcwidthb, abs(dstwidthb));
1025 /* FIXME: BI_BITFIELDS not supported yet */
1026 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb) {
1027 memcpy(dbits, sbits, widthb);
1030 break;
1032 default: /* ? bit bmp -> 32 bit DIB */
1033 FIXME("32 bit DIB %d bit bitmap\n",
1034 bmp->bitmap.bmBitsPixel);
1035 break;
1038 break;
1040 default: /* ? bit DIB */
1041 FIXME("Unsupported DIB depth %d\n", info->bmiHeader.biBitCount);
1042 break;
1045 /* Otherwise, get bits from the XImage */
1046 else
1048 if (!bmp->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) lines = 0;
1049 else
1051 if (bmp->funcs && bmp->funcs->pGetDIBits)
1052 lines = bmp->funcs->pGetDIBits( dc->physDev, hbitmap, startscan,
1053 lines, bits, info, coloruse );
1054 else
1055 lines = 0; /* FIXME: should copy from bmp->bitmap.bmBits */
1059 else lines = abs(height);
1061 /* The knowledge base article Q81498 ("DIBs and Their Uses") states that
1062 if bits == NULL and bpp != 0, only biSizeImage and the color table are
1063 filled in. */
1064 if (!core_header)
1066 /* FIXME: biSizeImage should be calculated according to the selected
1067 compression algorithm if biCompression != BI_RGB */
1068 info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes( width, height, bpp );
1069 TRACE("biSizeImage = %d, ", info->bmiHeader.biSizeImage);
1071 TRACE("biWidth = %d, biHeight = %d\n", width, height);
1073 done:
1074 release_dc_ptr( dc );
1075 GDI_ReleaseObj( hbitmap );
1076 return lines;
1080 /***********************************************************************
1081 * CreateDIBitmap (GDI32.@)
1083 * Creates a DDB (device dependent bitmap) from a DIB.
1084 * The DDB will have the same color depth as the reference DC.
1086 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
1087 DWORD init, LPCVOID bits, const BITMAPINFO *data,
1088 UINT coloruse )
1090 HBITMAP handle;
1091 LONG width;
1092 LONG height;
1093 WORD planes, bpp;
1094 DWORD compr, size;
1095 DC *dc;
1097 if (DIB_GetBitmapInfo( header, &width, &height, &planes, &bpp, &compr, &size ) == -1) return 0;
1099 if (width < 0)
1101 TRACE("Bitmap has a negative width\n");
1102 return 0;
1105 /* Top-down DIBs have a negative height */
1106 if (height < 0) height = -height;
1108 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1109 hdc, header, init, bits, data, coloruse, width, height, bpp, compr);
1111 if (hdc == NULL)
1112 handle = CreateBitmap( width, height, 1, 1, NULL );
1113 else
1114 handle = CreateCompatibleBitmap( hdc, width, height );
1116 if (handle)
1118 if (init == CBM_INIT) SetDIBits( hdc, handle, 0, height, bits, data, coloruse );
1120 else if (hdc && ((dc = get_dc_ptr( hdc )) != NULL) )
1122 if (!BITMAP_SetOwnerDC( handle, dc ))
1124 DeleteObject( handle );
1125 handle = 0;
1127 release_dc_ptr( dc );
1131 return handle;
1134 /***********************************************************************
1135 * CreateDIBSection (GDI.489)
1137 HBITMAP16 WINAPI CreateDIBSection16 (HDC16 hdc, const BITMAPINFO *bmi, UINT16 usage,
1138 SEGPTR *bits16, HANDLE section, DWORD offset)
1140 LPVOID bits32;
1141 HBITMAP hbitmap;
1143 hbitmap = CreateDIBSection( HDC_32(hdc), bmi, usage, &bits32, section, offset );
1144 if (hbitmap)
1146 BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr(hbitmap, BITMAP_MAGIC);
1147 if (bmp && bmp->dib && bits32)
1149 const BITMAPINFOHEADER *bi = &bmi->bmiHeader;
1150 LONG width, height;
1151 WORD planes, bpp;
1152 DWORD compr, size;
1153 INT width_bytes;
1154 WORD count, sel;
1155 int i;
1157 DIB_GetBitmapInfo(bi, &width, &height, &planes, &bpp, &compr, &size);
1159 height = height >= 0 ? height : -height;
1160 width_bytes = DIB_GetDIBWidthBytes(width, bpp);
1162 if (!size || (compr != BI_RLE4 && compr != BI_RLE8)) size = width_bytes * height;
1164 /* calculate number of sel's needed for size with 64K steps */
1165 count = (size + 0xffff) / 0x10000;
1166 sel = AllocSelectorArray16(count);
1168 for (i = 0; i < count; i++)
1170 SetSelectorBase(sel + (i << __AHSHIFT), (DWORD)bits32 + i * 0x10000);
1171 SetSelectorLimit16(sel + (i << __AHSHIFT), size - 1); /* yep, limit is correct */
1172 size -= 0x10000;
1174 bmp->segptr_bits = MAKESEGPTR( sel, 0 );
1175 if (bits16) *bits16 = bmp->segptr_bits;
1177 if (bmp) GDI_ReleaseObj( hbitmap );
1179 return HBITMAP_16(hbitmap);
1182 /* Copy/synthesize RGB palette from BITMAPINFO. Ripped from dlls/winex11.drv/dib.c */
1183 static void DIB_CopyColorTable( DC *dc, BITMAPOBJ *bmp, WORD coloruse, const BITMAPINFO *info )
1185 RGBQUAD *colorTable;
1186 unsigned int colors;
1187 int i;
1188 BOOL core_info = info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER);
1190 if (core_info)
1192 colors = 1 << ((const BITMAPCOREINFO*) info)->bmciHeader.bcBitCount;
1194 else
1196 colors = info->bmiHeader.biClrUsed;
1197 if (!colors) colors = 1 << info->bmiHeader.biBitCount;
1200 if (colors > 256) {
1201 ERR("called with >256 colors!\n");
1202 return;
1205 if (!(colorTable = HeapAlloc(GetProcessHeap(), 0, colors * sizeof(RGBQUAD) ))) return;
1207 if(coloruse == DIB_RGB_COLORS)
1209 if (core_info)
1211 /* Convert RGBTRIPLEs to RGBQUADs */
1212 for (i=0; i < colors; i++)
1214 colorTable[i].rgbRed = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtRed;
1215 colorTable[i].rgbGreen = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtGreen;
1216 colorTable[i].rgbBlue = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtBlue;
1217 colorTable[i].rgbReserved = 0;
1220 else
1222 memcpy(colorTable, (const BYTE*) info + (WORD) info->bmiHeader.biSize, colors * sizeof(RGBQUAD));
1225 else
1227 PALETTEENTRY entries[256];
1228 const WORD *index = (const WORD*) ((const BYTE*) info + (WORD) info->bmiHeader.biSize);
1229 UINT count = GetPaletteEntries( dc->hPalette, 0, colors, entries );
1231 for (i = 0; i < colors; i++, index++)
1233 PALETTEENTRY *entry = &entries[*index % count];
1234 colorTable[i].rgbRed = entry->peRed;
1235 colorTable[i].rgbGreen = entry->peGreen;
1236 colorTable[i].rgbBlue = entry->peBlue;
1237 colorTable[i].rgbReserved = 0;
1240 bmp->color_table = colorTable;
1241 bmp->nb_colors = colors;
1244 /***********************************************************************
1245 * CreateDIBSection (GDI32.@)
1247 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
1248 VOID **bits, HANDLE section, DWORD offset)
1250 HBITMAP ret = 0;
1251 DC *dc;
1252 BOOL bDesktopDC = FALSE;
1253 DIBSECTION *dib;
1254 BITMAPOBJ *bmp;
1255 int bitmap_type;
1256 LONG width, height;
1257 WORD planes, bpp;
1258 DWORD compression, sizeImage;
1259 void *mapBits = NULL;
1261 if(!bmi){
1262 if(bits) *bits = NULL;
1263 return NULL;
1266 if (((bitmap_type = DIB_GetBitmapInfo( &bmi->bmiHeader, &width, &height,
1267 &planes, &bpp, &compression, &sizeImage )) == -1))
1268 return 0;
1270 if (compression != BI_RGB && compression != BI_BITFIELDS)
1272 TRACE("can't create a compressed (%u) dibsection\n", compression);
1273 return 0;
1276 if (!(dib = HeapAlloc( GetProcessHeap(), 0, sizeof(*dib) ))) return 0;
1278 TRACE("format (%d,%d), planes %d, bpp %d, size %d, %s\n",
1279 width, height, planes, bpp, sizeImage, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1281 dib->dsBm.bmType = 0;
1282 dib->dsBm.bmWidth = width;
1283 dib->dsBm.bmHeight = height >= 0 ? height : -height;
1284 dib->dsBm.bmWidthBytes = DIB_GetDIBWidthBytes(width, bpp);
1285 dib->dsBm.bmPlanes = planes;
1286 dib->dsBm.bmBitsPixel = bpp;
1287 dib->dsBm.bmBits = NULL;
1289 if (!bitmap_type) /* core header */
1291 /* convert the BITMAPCOREHEADER to a BITMAPINFOHEADER */
1292 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1293 dib->dsBmih.biWidth = width;
1294 dib->dsBmih.biHeight = height;
1295 dib->dsBmih.biPlanes = planes;
1296 dib->dsBmih.biBitCount = bpp;
1297 dib->dsBmih.biCompression = compression;
1298 dib->dsBmih.biXPelsPerMeter = 0;
1299 dib->dsBmih.biYPelsPerMeter = 0;
1300 dib->dsBmih.biClrUsed = 0;
1301 dib->dsBmih.biClrImportant = 0;
1303 else
1305 /* truncate extended bitmap headers (BITMAPV4HEADER etc.) */
1306 dib->dsBmih = bmi->bmiHeader;
1307 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1310 /* set number of entries in bmi.bmiColors table */
1311 if( bpp <= 8 )
1312 dib->dsBmih.biClrUsed = 1 << bpp;
1314 dib->dsBmih.biSizeImage = dib->dsBm.bmWidthBytes * dib->dsBm.bmHeight;
1316 /* set dsBitfields values */
1317 if (usage == DIB_PAL_COLORS || bpp <= 8)
1319 dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
1321 else switch( bpp )
1323 case 15:
1324 case 16:
1325 dib->dsBitfields[0] = (compression == BI_BITFIELDS) ? *(const DWORD *)bmi->bmiColors : 0x7c00;
1326 dib->dsBitfields[1] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 1) : 0x03e0;
1327 dib->dsBitfields[2] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 2) : 0x001f;
1328 break;
1329 case 24:
1330 case 32:
1331 dib->dsBitfields[0] = (compression == BI_BITFIELDS) ? *(const DWORD *)bmi->bmiColors : 0xff0000;
1332 dib->dsBitfields[1] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 1) : 0x00ff00;
1333 dib->dsBitfields[2] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 2) : 0x0000ff;
1334 break;
1337 /* get storage location for DIB bits */
1339 if (section)
1341 SYSTEM_INFO SystemInfo;
1342 DWORD mapOffset;
1343 INT mapSize;
1345 GetSystemInfo( &SystemInfo );
1346 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
1347 mapSize = dib->dsBmih.biSizeImage + (offset - mapOffset);
1348 mapBits = MapViewOfFile( section, FILE_MAP_ALL_ACCESS, 0, mapOffset, mapSize );
1349 if (mapBits) dib->dsBm.bmBits = (char *)mapBits + (offset - mapOffset);
1351 else
1353 offset = 0;
1354 dib->dsBm.bmBits = VirtualAlloc( NULL, dib->dsBmih.biSizeImage,
1355 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
1357 dib->dshSection = section;
1358 dib->dsOffset = offset;
1360 if (!dib->dsBm.bmBits)
1362 HeapFree( GetProcessHeap(), 0, dib );
1363 return 0;
1366 /* If the reference hdc is null, take the desktop dc */
1367 if (hdc == 0)
1369 hdc = CreateCompatibleDC(0);
1370 bDesktopDC = TRUE;
1373 if (!(dc = get_dc_ptr( hdc ))) goto error;
1375 /* create Device Dependent Bitmap and add DIB pointer */
1376 ret = CreateBitmap( dib->dsBm.bmWidth, dib->dsBm.bmHeight, 1,
1377 (bpp == 1) ? 1 : GetDeviceCaps(hdc, BITSPIXEL), NULL );
1379 if (ret && ((bmp = GDI_GetObjPtr(ret, BITMAP_MAGIC))))
1381 bmp->dib = dib;
1382 bmp->funcs = dc->funcs;
1383 /* create local copy of DIB palette */
1384 if (bpp <= 8) DIB_CopyColorTable( dc, bmp, usage, bmi );
1385 GDI_ReleaseObj( ret );
1387 if (dc->funcs->pCreateDIBSection)
1389 if (!dc->funcs->pCreateDIBSection(dc->physDev, ret, bmi, usage))
1391 DeleteObject( ret );
1392 ret = 0;
1397 release_dc_ptr( dc );
1398 if (bDesktopDC) DeleteDC( hdc );
1399 if (ret && bits) *bits = dib->dsBm.bmBits;
1400 return ret;
1402 error:
1403 if (bDesktopDC) DeleteDC( hdc );
1404 if (section) UnmapViewOfFile( mapBits );
1405 else if (!offset) VirtualFree( dib->dsBm.bmBits, 0, MEM_RELEASE );
1406 HeapFree( GetProcessHeap(), 0, dib );
1407 return 0;