gdi32: Use the helper to retrieve the number of colours.
[wine.git] / dlls / gdi32 / dib.c
blob5adafcbcdffecbcce7d63af33c6eeb974af1c661
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>
66 #include <assert.h>
68 #include "windef.h"
69 #include "winbase.h"
70 #include "gdi_private.h"
71 #include "wine/debug.h"
73 WINE_DEFAULT_DEBUG_CHANNEL(bitmap);
76 /***********************************************************************
77 * bitmap_info_size
79 * Return the size of the bitmap info structure including color table.
81 int bitmap_info_size( const BITMAPINFO * info, WORD coloruse )
83 unsigned int colors, size, masks = 0;
85 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
87 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
88 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
89 return sizeof(BITMAPCOREHEADER) + colors *
90 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
92 else /* assume BITMAPINFOHEADER */
94 colors = get_dib_num_of_colors( info );
95 if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3;
96 size = max( info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD) );
97 return size + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
102 /***********************************************************************
103 * DIB_GetBitmapInfo
105 * Get the info from a bitmap header.
106 * Return 0 for COREHEADER, 1 for INFOHEADER, -1 for error.
108 int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
109 LONG *height, WORD *planes, WORD *bpp, DWORD *compr, DWORD *size )
111 if (header->biSize == sizeof(BITMAPCOREHEADER))
113 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)header;
114 *width = core->bcWidth;
115 *height = core->bcHeight;
116 *planes = core->bcPlanes;
117 *bpp = core->bcBitCount;
118 *compr = 0;
119 *size = 0;
120 return 0;
122 if (header->biSize >= sizeof(BITMAPINFOHEADER)) /* assume BITMAPINFOHEADER */
124 *width = header->biWidth;
125 *height = header->biHeight;
126 *planes = header->biPlanes;
127 *bpp = header->biBitCount;
128 *compr = header->biCompression;
129 *size = header->biSizeImage;
130 return 1;
132 ERR("(%d): unknown/wrong size for header\n", header->biSize );
133 return -1;
136 /*******************************************************************************************
137 * Fill out a true BITMAPINFO from a variable sized BITMAPINFO / BITMAPCOREINFO.
139 static BOOL bitmapinfo_from_user_bitmapinfo( BITMAPINFO *dst, const BITMAPINFO *info, UINT coloruse )
141 LONG width, height;
142 WORD planes, bpp;
143 DWORD compr, size;
144 void *src_colors = (char *)info + info->bmiHeader.biSize;
145 unsigned int colors;
146 int bitmap_type = DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size );
148 if (bitmap_type == -1) return FALSE;
150 if (bitmap_type == 1)
152 dst->bmiHeader = info->bmiHeader;
153 dst->bmiHeader.biSize = sizeof(dst->bmiHeader);
155 colors = get_dib_num_of_colors( dst );
157 if (info->bmiHeader.biCompression == BI_BITFIELDS)
158 /* bitfields are always at bmiColors even in larger structures */
159 memcpy( dst->bmiColors, info->bmiColors, 3 * sizeof(DWORD) );
160 else if (colors)
162 unsigned int size;
164 if (coloruse == DIB_PAL_COLORS)
165 size = colors * sizeof(WORD);
166 else
167 size = colors * sizeof(RGBQUAD);
168 memcpy( dst->bmiColors, src_colors, size );
171 else
173 dst->bmiHeader.biSize = sizeof(dst->bmiHeader);
174 dst->bmiHeader.biWidth = width;
175 dst->bmiHeader.biHeight = height;
176 dst->bmiHeader.biPlanes = planes;
177 dst->bmiHeader.biBitCount = bpp;
178 dst->bmiHeader.biCompression = compr;
179 dst->bmiHeader.biSizeImage = size;
180 dst->bmiHeader.biXPelsPerMeter = 0;
181 dst->bmiHeader.biYPelsPerMeter = 0;
182 dst->bmiHeader.biClrUsed = 0;
183 dst->bmiHeader.biClrImportant = 0;
185 colors = get_dib_num_of_colors( dst );
187 if (colors)
189 if (coloruse == DIB_PAL_COLORS)
190 memcpy( dst->bmiColors, src_colors, colors * sizeof(WORD) );
191 else
193 unsigned int i;
194 RGBTRIPLE *triple = (RGBTRIPLE *)src_colors;
195 for (i = 0; i < colors; i++)
197 dst->bmiColors[i].rgbRed = triple[i].rgbtRed;
198 dst->bmiColors[i].rgbGreen = triple[i].rgbtGreen;
199 dst->bmiColors[i].rgbBlue = triple[i].rgbtBlue;
200 dst->bmiColors[i].rgbReserved = 0;
206 return TRUE;
209 static int fill_color_table_from_palette( BITMAPINFO *info, DC *dc )
211 PALETTEENTRY palEntry[256];
212 int i, colors = get_dib_num_of_colors( info );
214 if (!colors) return 0;
216 memset( palEntry, 0, sizeof(palEntry) );
217 if (!GetPaletteEntries( dc->hPalette, 0, colors, palEntry ))
218 return 0;
220 for (i = 0; i < colors; i++)
222 info->bmiColors[i].rgbRed = palEntry[i].peRed;
223 info->bmiColors[i].rgbGreen = palEntry[i].peGreen;
224 info->bmiColors[i].rgbBlue = palEntry[i].peBlue;
225 info->bmiColors[i].rgbReserved = 0;
228 return colors;
231 static void *get_pixel_ptr( const BITMAPINFO *info, void *bits, int x, int y )
233 const int width = info->bmiHeader.biWidth, height = info->bmiHeader.biHeight;
234 const int bpp = info->bmiHeader.biBitCount;
236 if (height > 0)
237 return (char *)bits + (height - y - 1) * get_dib_stride( width, bpp ) + x * bpp / 8;
238 else
239 return (char *)bits + y * get_dib_stride( width, bpp ) + x * bpp / 8;
242 static BOOL build_rle_bitmap( const BITMAPINFO *info, struct gdi_image_bits *bits, HRGN *clip )
244 int i = 0;
245 int left, right;
246 int x, y, width = info->bmiHeader.biWidth, height = info->bmiHeader.biHeight;
247 HRGN run = NULL;
248 BYTE skip, num, data;
249 BYTE *out_bits, *in_bits = bits->ptr;
251 *clip = NULL;
253 assert( info->bmiHeader.biBitCount == 4 || info->bmiHeader.biBitCount == 8 );
255 out_bits = HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( info ) );
256 *clip = CreateRectRgn( 0, 0, 0, 0 );
257 run = CreateRectRgn( 0, 0, 0, 0 );
258 if (!out_bits || !*clip || !run) goto fail;
260 x = left = right = 0;
261 y = height - 1;
263 while (i < info->bmiHeader.biSizeImage - 1)
265 num = in_bits[i];
266 data = in_bits[i + 1];
267 i += 2;
269 if (num)
271 if (x + num > width) num = width - x;
272 if (num)
274 BYTE s = data, *out_ptr = get_pixel_ptr( info, out_bits, x, y );
275 if (info->bmiHeader.biBitCount == 8)
276 memset( out_ptr, s, num );
277 else
279 if(x & 1)
281 s = ((s >> 4) & 0x0f) | ((s << 4) & 0xf0);
282 *out_ptr = (*out_ptr & 0xf0) | (s & 0x0f);
283 out_ptr++;
284 x++;
285 num--;
287 /* this will write one too many if num is odd, but that doesn't matter */
288 if (num) memset( out_ptr, s, (num + 1) / 2 );
291 x += num;
292 right = x;
294 else
296 if (data < 3)
298 if(left != right)
300 SetRectRgn( run, left, y, right, y + 1 );
301 CombineRgn( *clip, run, *clip, RGN_OR );
303 switch (data)
305 case 0: /* eol */
306 left = right = x = 0;
307 y--;
308 if(y < 0) goto done;
309 break;
311 case 1: /* eod */
312 goto done;
314 case 2: /* delta */
315 if (i >= info->bmiHeader.biSizeImage - 1) goto done;
316 x += in_bits[i];
317 if (x > width) x = width;
318 left = right = x;
319 y -= in_bits[i + 1];
320 if(y < 0) goto done;
321 i += 2;
324 else /* data bytes of data */
326 num = data;
327 skip = (num * info->bmiHeader.biBitCount + 7) / 8;
328 if (skip > info->bmiHeader.biSizeImage - i) goto done;
329 skip = (skip + 1) & ~1;
330 if (x + num > width) num = width - x;
331 if (num)
333 BYTE *out_ptr = get_pixel_ptr( info, out_bits, x, y );
334 if (info->bmiHeader.biBitCount == 8)
335 memcpy( out_ptr, in_bits + i, num );
336 else
338 if(x & 1)
340 const BYTE *in_ptr = in_bits + i;
341 for ( ; num; num--, x++)
343 if (x & 1)
345 *out_ptr = (*out_ptr & 0xf0) | ((*in_ptr >> 4) & 0x0f);
346 out_ptr++;
348 else
349 *out_ptr = (*in_ptr++ << 4) & 0xf0;
352 else
353 memcpy( out_ptr, in_bits + i, (num + 1) / 2);
356 x += num;
357 right = x;
358 i += skip;
363 done:
364 DeleteObject( run );
365 if (bits->free) bits->free( bits );
367 bits->ptr = out_bits;
368 bits->is_copy = TRUE;
369 bits->free = free_heap_bits;
371 return TRUE;
373 fail:
374 if (run) DeleteObject( run );
375 if (*clip) DeleteObject( *clip );
376 HeapFree( GetProcessHeap(), 0, out_bits );
377 return FALSE;
382 /* nulldrv fallback implementation using SetDIBits/StretchBlt */
383 INT nulldrv_StretchDIBits( PHYSDEV dev, INT xDst, INT yDst, INT widthDst, INT heightDst,
384 INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits,
385 const BITMAPINFO *info, UINT coloruse, DWORD rop )
387 DC *dc = get_nulldrv_dc( dev );
388 INT ret;
389 LONG width, height;
390 WORD planes, bpp;
391 DWORD compr, size;
392 HBITMAP hBitmap;
393 HDC hdcMem;
395 /* make sure we have a real implementation for StretchBlt and PutImage */
396 if (GET_DC_PHYSDEV( dc, pStretchBlt ) == dev || GET_DC_PHYSDEV( dc, pPutImage ) == dev)
397 return 0;
399 if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size ) == -1)
400 return 0;
402 if (width < 0) return 0;
404 if (xSrc == 0 && ySrc == 0 && widthDst == widthSrc && heightDst == heightSrc &&
405 info->bmiHeader.biCompression == BI_RGB)
407 /* Windows appears to have a fast case optimization
408 * that uses the wrong origin for top-down DIBs */
409 if (height < 0 && heightSrc < abs(height)) ySrc = abs(height) - heightSrc;
411 if (xDst == 0 && yDst == 0 && info->bmiHeader.biCompression == BI_RGB && rop == SRCCOPY)
413 BITMAP bm;
414 hBitmap = GetCurrentObject( dev->hdc, OBJ_BITMAP );
415 if (GetObjectW( hBitmap, sizeof(bm), &bm ) &&
416 bm.bmWidth == widthSrc && bm.bmHeight == heightSrc &&
417 bm.bmBitsPixel == bpp && bm.bmPlanes == planes)
419 /* fast path */
420 return SetDIBits( dev->hdc, hBitmap, 0, abs( height ), bits, info, coloruse );
425 hdcMem = CreateCompatibleDC( dev->hdc );
426 hBitmap = CreateCompatibleBitmap( dev->hdc, width, height );
427 SelectObject( hdcMem, hBitmap );
428 if (coloruse == DIB_PAL_COLORS)
429 SelectPalette( hdcMem, GetCurrentObject( dev->hdc, OBJ_PAL ), FALSE );
431 if (info->bmiHeader.biCompression == BI_RLE4 || info->bmiHeader.biCompression == BI_RLE8)
433 /* when RLE compression is used, there may be some gaps (ie the DIB doesn't
434 * contain all the rectangle described in bmiHeader, but only part of it.
435 * This mean that those undescribed pixels must be left untouched.
436 * So, we first copy on a memory bitmap the current content of the
437 * destination rectangle, blit the DIB bits on top of it - hence leaving
438 * the gaps untouched -, and blitting the rectangle back.
439 * This insure that gaps are untouched on the destination rectangle
441 StretchBlt( hdcMem, xSrc, abs(height) - heightSrc - ySrc, widthSrc, heightSrc,
442 dev->hdc, xDst, yDst, widthDst, heightDst, rop );
444 ret = SetDIBits( hdcMem, hBitmap, 0, abs( height ), bits, info, coloruse );
445 if (ret) StretchBlt( dev->hdc, xDst, yDst, widthDst, heightDst,
446 hdcMem, xSrc, abs(height) - heightSrc - ySrc, widthSrc, heightSrc, rop );
447 DeleteDC( hdcMem );
448 DeleteObject( hBitmap );
449 return ret;
452 /***********************************************************************
453 * StretchDIBits (GDI32.@)
455 INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst, INT heightDst,
456 INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits,
457 const BITMAPINFO *info, UINT coloruse, DWORD rop )
459 DC *dc;
460 INT ret = 0;
462 if (!bits || !info) return 0;
464 if ((dc = get_dc_ptr( hdc )))
466 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pStretchDIBits );
467 update_dc( dc );
468 ret = physdev->funcs->pStretchDIBits( physdev, xDst, yDst, widthDst, heightDst,
469 xSrc, ySrc, widthSrc, heightSrc, bits, info, coloruse, rop );
470 release_dc_ptr( dc );
472 return ret;
476 /******************************************************************************
477 * SetDIBits [GDI32.@]
479 * Sets pixels in a bitmap using colors from DIB.
481 * PARAMS
482 * hdc [I] Handle to device context
483 * hbitmap [I] Handle to bitmap
484 * startscan [I] Starting scan line
485 * lines [I] Number of scan lines
486 * bits [I] Array of bitmap bits
487 * info [I] Address of structure with data
488 * coloruse [I] Type of color indexes to use
490 * RETURNS
491 * Success: Number of scan lines copied
492 * Failure: 0
494 INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
495 UINT lines, LPCVOID bits, const BITMAPINFO *info,
496 UINT coloruse )
498 DC *dc = get_dc_ptr( hdc );
499 BOOL delete_hdc = FALSE;
500 PHYSDEV physdev;
501 BITMAPOBJ *bitmap;
502 char src_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
503 BITMAPINFO *src_info = (BITMAPINFO *)src_bmibuf;
504 char dst_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
505 BITMAPINFO *dst_info = (BITMAPINFO *)dst_bmibuf;
506 INT result = 0;
507 DWORD err;
508 struct gdi_image_bits src_bits;
509 struct bitblt_coords src, dst;
510 INT src_to_dst_offset;
511 HRGN clip = 0;
513 src_bits.ptr = (void *)bits;
514 src_bits.is_copy = FALSE;
515 src_bits.free = NULL;
516 src_bits.param = NULL;
518 if (coloruse == DIB_RGB_COLORS && !dc)
520 hdc = CreateCompatibleDC(0);
521 dc = get_dc_ptr( hdc );
522 delete_hdc = TRUE;
525 if (!dc) return 0;
527 update_dc( dc );
529 if (!(bitmap = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
531 release_dc_ptr( dc );
532 if (delete_hdc) DeleteDC(hdc);
533 return 0;
536 if (!bitmapinfo_from_user_bitmapinfo( src_info, info, coloruse )) goto done;
538 if (coloruse == DIB_PAL_COLORS)
539 if (!fill_color_table_from_palette( src_info, dc )) goto done;
541 if (src_info->bmiHeader.biCompression == BI_RLE4 || src_info->bmiHeader.biCompression == BI_RLE8)
543 if ( src_info->bmiHeader.biHeight < 0 ||
544 (src_info->bmiHeader.biCompression == BI_RLE4 && src_info->bmiHeader.biBitCount != 4) ||
545 (src_info->bmiHeader.biCompression == BI_RLE8 && src_info->bmiHeader.biBitCount != 8) )
547 SetLastError( ERROR_INVALID_PARAMETER );
548 goto done;
551 if (lines == 0) goto done;
552 else lines = src_info->bmiHeader.biHeight;
553 startscan = 0;
555 if (!build_rle_bitmap( src_info, &src_bits, &clip )) goto done;
558 dst.visrect.left = 0;
559 dst.visrect.top = 0;
560 dst.visrect.right = bitmap->bitmap.bmWidth;
561 dst.visrect.bottom = bitmap->bitmap.bmHeight;
563 src.visrect.left = 0;
564 src.visrect.top = 0;
565 src.visrect.right = src_info->bmiHeader.biWidth;
566 src.visrect.bottom = abs( src_info->bmiHeader.biHeight );
568 if (src_info->bmiHeader.biHeight > 0)
570 src_to_dst_offset = -startscan;
571 lines = min( lines, src.visrect.bottom - startscan );
572 if (lines < src.visrect.bottom) src.visrect.top = src.visrect.bottom - lines;
574 else
576 src_to_dst_offset = src.visrect.bottom - lines - startscan;
577 /* Unlike the bottom-up case, Windows doesn't limit lines. */
578 if (lines < src.visrect.bottom) src.visrect.bottom = lines;
581 physdev = GET_DC_PHYSDEV( dc, pPutImage );
582 if (!BITMAP_SetOwnerDC( hbitmap, physdev )) goto done;
584 result = lines;
586 offset_rect( &src.visrect, 0, src_to_dst_offset );
587 if (!intersect_rect( &dst.visrect, &src.visrect, &dst.visrect )) goto done;
588 src.visrect = dst.visrect;
589 offset_rect( &src.visrect, 0, -src_to_dst_offset );
591 src.x = src.visrect.left;
592 src.y = src.visrect.top;
593 src.width = src.visrect.right - src.visrect.left;
594 src.height = src.visrect.bottom - src.visrect.top;
596 dst.x = dst.visrect.left;
597 dst.y = dst.visrect.top;
598 dst.width = dst.visrect.right - dst.visrect.left;
599 dst.height = dst.visrect.bottom - dst.visrect.top;
601 memcpy( dst_info, src_info, FIELD_OFFSET( BITMAPINFO, bmiColors[256] ));
603 err = physdev->funcs->pPutImage( physdev, hbitmap, clip, dst_info, &src_bits, &src, &dst, 0 );
604 if (err == ERROR_BAD_FORMAT)
606 void *ptr;
608 dst_info->bmiHeader.biWidth = dst.width;
609 ptr = HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( dst_info ));
610 if (ptr)
612 err = convert_bitmapinfo( src_info, src_bits.ptr, &src.visrect, dst_info, ptr );
614 if (src_bits.free) src_bits.free( &src_bits );
615 src_bits.ptr = ptr;
616 src_bits.is_copy = TRUE;
617 src_bits.free = free_heap_bits;
618 if (!err)
619 err = physdev->funcs->pPutImage( physdev, hbitmap, clip, dst_info, &src_bits, &src, &dst, 0 );
622 else err = ERROR_OUTOFMEMORY;
624 if(err) result = 0;
626 done:
627 if (src_bits.free) src_bits.free( &src_bits );
628 if (clip) DeleteObject( clip );
629 GDI_ReleaseObj( hbitmap );
630 release_dc_ptr( dc );
631 if (delete_hdc) DeleteDC(hdc);
632 return result;
636 /***********************************************************************
637 * SetDIBitsToDevice (GDI32.@)
639 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
640 DWORD cy, INT xSrc, INT ySrc, UINT startscan,
641 UINT lines, LPCVOID bits, const BITMAPINFO *info,
642 UINT coloruse )
644 INT ret = 0;
645 DC *dc;
647 if (!bits) return 0;
649 if ((dc = get_dc_ptr( hdc )))
651 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDIBitsToDevice );
652 update_dc( dc );
653 ret = physdev->funcs->pSetDIBitsToDevice( physdev, xDest, yDest, cx, cy, xSrc,
654 ySrc, startscan, lines, bits, info, coloruse );
655 release_dc_ptr( dc );
657 return ret;
660 /***********************************************************************
661 * SetDIBColorTable (GDI32.@)
663 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, CONST RGBQUAD *colors )
665 DC * dc;
666 UINT result = 0;
667 BITMAPOBJ * bitmap;
669 if (!(dc = get_dc_ptr( hdc ))) return 0;
671 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
673 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDIBColorTable );
675 /* Check if currently selected bitmap is a DIB */
676 if (bitmap->color_table)
678 if (startpos < bitmap->nb_colors)
680 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
681 memcpy(bitmap->color_table + startpos, colors, entries * sizeof(RGBQUAD));
682 result = entries;
685 GDI_ReleaseObj( dc->hBitmap );
686 physdev->funcs->pSetDIBColorTable( physdev, startpos, entries, colors );
688 release_dc_ptr( dc );
689 return result;
693 /***********************************************************************
694 * GetDIBColorTable (GDI32.@)
696 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
698 DC * dc;
699 BITMAPOBJ *bitmap;
700 UINT result = 0;
702 if (!(dc = get_dc_ptr( hdc ))) return 0;
704 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
706 /* Check if currently selected bitmap is a DIB */
707 if (bitmap->color_table)
709 if (startpos < bitmap->nb_colors)
711 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
712 memcpy(colors, bitmap->color_table + startpos, entries * sizeof(RGBQUAD));
713 result = entries;
716 GDI_ReleaseObj( dc->hBitmap );
718 release_dc_ptr( dc );
719 return result;
722 static const RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
723 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
724 { 0x00, 0x00, 0x00, 0x00 },
725 { 0x00, 0x00, 0x80, 0x00 },
726 { 0x00, 0x80, 0x00, 0x00 },
727 { 0x00, 0x80, 0x80, 0x00 },
728 { 0x80, 0x00, 0x00, 0x00 },
729 { 0x80, 0x00, 0x80, 0x00 },
730 { 0x80, 0x80, 0x00, 0x00 },
731 { 0xc0, 0xc0, 0xc0, 0x00 },
732 { 0xc0, 0xdc, 0xc0, 0x00 },
733 { 0xf0, 0xca, 0xa6, 0x00 },
734 { 0xf0, 0xfb, 0xff, 0x00 },
735 { 0xa4, 0xa0, 0xa0, 0x00 },
736 { 0x80, 0x80, 0x80, 0x00 },
737 { 0x00, 0x00, 0xff, 0x00 },
738 { 0x00, 0xff, 0x00, 0x00 },
739 { 0x00, 0xff, 0xff, 0x00 },
740 { 0xff, 0x00, 0x00, 0x00 },
741 { 0xff, 0x00, 0xff, 0x00 },
742 { 0xff, 0xff, 0x00, 0x00 },
743 { 0xff, 0xff, 0xff, 0x00 }
746 static const DWORD bit_fields_888[3] = {0xff0000, 0x00ff00, 0x0000ff};
747 static const DWORD bit_fields_565[3] = {0xf800, 0x07e0, 0x001f};
748 static const DWORD bit_fields_555[3] = {0x7c00, 0x03e0, 0x001f};
750 static int fill_query_info( BITMAPINFO *info, BITMAPOBJ *bmp )
752 BITMAPINFOHEADER header;
754 header.biSize = info->bmiHeader.biSize; /* Ensure we don't overwrite the original size when we copy back */
755 header.biWidth = bmp->bitmap.bmWidth;
756 header.biHeight = bmp->bitmap.bmHeight;
757 header.biPlanes = 1;
759 if (bmp->dib)
761 header.biBitCount = bmp->dib->dsBm.bmBitsPixel;
762 switch (bmp->dib->dsBm.bmBitsPixel)
764 case 16:
765 case 32:
766 header.biCompression = BI_BITFIELDS;
767 break;
768 default:
769 header.biCompression = BI_RGB;
770 break;
773 else
775 header.biCompression = (bmp->bitmap.bmBitsPixel > 8) ? BI_BITFIELDS : BI_RGB;
776 header.biBitCount = bmp->bitmap.bmBitsPixel;
779 header.biSizeImage = get_dib_image_size( (BITMAPINFO *)&header );
780 header.biXPelsPerMeter = 0;
781 header.biYPelsPerMeter = 0;
782 header.biClrUsed = 0;
783 header.biClrImportant = 0;
785 if ( info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER) )
787 BITMAPCOREHEADER *coreheader = (BITMAPCOREHEADER *)info;
789 coreheader->bcWidth = header.biWidth;
790 coreheader->bcHeight = header.biHeight;
791 coreheader->bcPlanes = header.biPlanes;
792 coreheader->bcBitCount = header.biBitCount;
794 else
795 info->bmiHeader = header;
797 return abs(bmp->bitmap.bmHeight);
800 /************************************************************************
801 * copy_color_info
803 * Copy BITMAPINFO color information where dst may be a BITMAPCOREINFO.
805 static void copy_color_info(BITMAPINFO *dst, const BITMAPINFO *src, UINT coloruse)
807 unsigned int colors = get_dib_num_of_colors( src );
808 RGBQUAD *src_colors = (RGBQUAD *)((char *)src + src->bmiHeader.biSize);
810 assert( src->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) );
812 if (dst->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
814 BITMAPCOREINFO *core = (BITMAPCOREINFO *)dst;
815 if (coloruse == DIB_PAL_COLORS)
816 memcpy( core->bmciColors, src_colors, colors * sizeof(WORD) );
817 else
819 unsigned int i;
820 for (i = 0; i < colors; i++)
822 core->bmciColors[i].rgbtRed = src_colors[i].rgbRed;
823 core->bmciColors[i].rgbtGreen = src_colors[i].rgbGreen;
824 core->bmciColors[i].rgbtBlue = src_colors[i].rgbBlue;
828 else
830 dst->bmiHeader.biClrUsed = src->bmiHeader.biClrUsed;
831 dst->bmiHeader.biSizeImage = src->bmiHeader.biSizeImage;
833 if (src->bmiHeader.biCompression == BI_BITFIELDS)
834 /* bitfields are always at bmiColors even in larger structures */
835 memcpy( dst->bmiColors, src->bmiColors, 3 * sizeof(DWORD) );
836 else if (colors)
838 void *colorptr = (char *)dst + dst->bmiHeader.biSize;
839 unsigned int size;
841 if (coloruse == DIB_PAL_COLORS)
842 size = colors * sizeof(WORD);
843 else
844 size = colors * sizeof(RGBQUAD);
845 memcpy( colorptr, src_colors, size );
850 static void fill_default_color_table( BITMAPINFO *info )
852 int i;
854 switch (info->bmiHeader.biBitCount)
856 case 1:
857 info->bmiColors[0].rgbRed = info->bmiColors[0].rgbGreen = info->bmiColors[0].rgbBlue = 0;
858 info->bmiColors[0].rgbReserved = 0;
859 info->bmiColors[1].rgbRed = info->bmiColors[1].rgbGreen = info->bmiColors[1].rgbBlue = 0xff;
860 info->bmiColors[1].rgbReserved = 0;
861 break;
863 case 4:
864 /* The EGA palette is the first and last 8 colours of the default palette
865 with the innermost pair swapped */
866 memcpy(info->bmiColors, DefLogPaletteQuads, 7 * sizeof(RGBQUAD));
867 memcpy(info->bmiColors + 7, DefLogPaletteQuads + 12, 1 * sizeof(RGBQUAD));
868 memcpy(info->bmiColors + 8, DefLogPaletteQuads + 7, 1 * sizeof(RGBQUAD));
869 memcpy(info->bmiColors + 9, DefLogPaletteQuads + 13, 7 * sizeof(RGBQUAD));
870 break;
872 case 8:
873 memcpy(info->bmiColors, DefLogPaletteQuads, 10 * sizeof(RGBQUAD));
874 memcpy(info->bmiColors + 246, DefLogPaletteQuads + 10, 10 * sizeof(RGBQUAD));
875 for (i = 10; i < 246; i++)
877 info->bmiColors[i].rgbRed = (i & 0x07) << 5;
878 info->bmiColors[i].rgbGreen = (i & 0x38) << 2;
879 info->bmiColors[i].rgbBlue = i & 0xc0;
880 info->bmiColors[i].rgbReserved = 0;
882 break;
884 default:
885 ERR("called with bitcount %d\n", info->bmiHeader.biBitCount);
889 /******************************************************************************
890 * GetDIBits [GDI32.@]
892 * Retrieves bits of bitmap and copies to buffer.
894 * RETURNS
895 * Success: Number of scan lines copied from bitmap
896 * Failure: 0
898 INT WINAPI GetDIBits(
899 HDC hdc, /* [in] Handle to device context */
900 HBITMAP hbitmap, /* [in] Handle to bitmap */
901 UINT startscan, /* [in] First scan line to set in dest bitmap */
902 UINT lines, /* [in] Number of scan lines to copy */
903 LPVOID bits, /* [out] Address of array for bitmap bits */
904 BITMAPINFO * info, /* [out] Address of structure with bitmap data */
905 UINT coloruse) /* [in] RGB or palette index */
907 DC * dc;
908 BITMAPOBJ * bmp;
909 int i;
910 int bitmap_type;
911 LONG width;
912 LONG height;
913 WORD planes, bpp;
914 DWORD compr, size;
915 char dst_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
916 BITMAPINFO *dst_info = (BITMAPINFO *)dst_bmibuf;
917 unsigned int colors = 0;
919 if (!info) return 0;
921 bitmap_type = DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size);
922 if (bitmap_type == -1)
924 ERR("Invalid bitmap format\n");
925 return 0;
927 if (!(dc = get_dc_ptr( hdc )))
929 SetLastError( ERROR_INVALID_PARAMETER );
930 return 0;
932 update_dc( dc );
933 if (!(bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
935 release_dc_ptr( dc );
936 return 0;
940 if (bpp == 0) /* query bitmap info only */
942 lines = fill_query_info( info, bmp );
943 goto done;
946 /* Since info may be a BITMAPCOREINFO or any of the larger BITMAPINFO structures, we'll use our
947 own copy and transfer the colour info back at the end */
949 dst_info->bmiHeader.biSize = sizeof(dst_info->bmiHeader);
950 dst_info->bmiHeader.biWidth = width;
951 dst_info->bmiHeader.biHeight = height;
952 dst_info->bmiHeader.biPlanes = planes;
953 dst_info->bmiHeader.biBitCount = bpp;
954 dst_info->bmiHeader.biCompression = compr;
955 dst_info->bmiHeader.biSizeImage = get_dib_image_size( dst_info );
956 dst_info->bmiHeader.biXPelsPerMeter = 0;
957 dst_info->bmiHeader.biYPelsPerMeter = 0;
958 dst_info->bmiHeader.biClrUsed = 0;
959 dst_info->bmiHeader.biClrImportant = 0;
961 switch (bpp)
963 case 1:
964 case 4:
965 case 8:
967 colors = 1 << bpp;
969 /* If the bitmap object is a dib section at the
970 same color depth then get the color map from it */
971 if (bmp->dib && bpp == bmp->dib->dsBm.bmBitsPixel && coloruse == DIB_RGB_COLORS)
973 colors = min( colors, bmp->nb_colors );
974 if (colors != 1 << bpp) dst_info->bmiHeader.biClrUsed = colors;
975 memcpy( dst_info->bmiColors, bmp->color_table, colors * sizeof(RGBQUAD) );
978 /* For color DDBs in native depth (mono DDBs always have a black/white palette):
979 Generate the color map from the selected palette. In the DIB_PAL_COLORS
980 case we'll fix up the indices after the format conversion. */
981 else if ( (bpp > 1 && bpp == bmp->bitmap.bmBitsPixel) || coloruse == DIB_PAL_COLORS )
983 if (!fill_color_table_from_palette( dst_info, dc ))
985 lines = 0;
986 goto done;
989 else
990 fill_default_color_table( dst_info );
991 break;
994 case 15:
995 if (dst_info->bmiHeader.biCompression == BI_BITFIELDS)
996 memcpy( dst_info->bmiColors, bit_fields_555, sizeof(bit_fields_555) );
997 break;
999 case 16:
1000 if (dst_info->bmiHeader.biCompression == BI_BITFIELDS)
1002 if (bmp->dib)
1004 if (bmp->dib->dsBmih.biCompression == BI_BITFIELDS && bmp->dib->dsBmih.biBitCount == bpp)
1005 memcpy( dst_info->bmiColors, bmp->dib->dsBitfields, 3 * sizeof(DWORD) );
1006 else
1007 memcpy( dst_info->bmiColors, bit_fields_555, sizeof(bit_fields_555) );
1009 else
1010 memcpy( dst_info->bmiColors, bit_fields_565, sizeof(bit_fields_565) );
1012 break;
1014 case 24:
1015 case 32:
1016 if (dst_info->bmiHeader.biCompression == BI_BITFIELDS)
1018 if (bmp->dib && bmp->dib->dsBmih.biCompression == BI_BITFIELDS && bmp->dib->dsBmih.biBitCount == bpp)
1019 memcpy( dst_info->bmiColors, bmp->dib->dsBitfields, 3 * sizeof(DWORD) );
1020 else
1021 memcpy( dst_info->bmiColors, bit_fields_888, sizeof(bit_fields_888) );
1023 break;
1026 if (bits && lines)
1028 char src_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1029 BITMAPINFO *src_info = (BITMAPINFO *)src_bmibuf;
1030 struct gdi_image_bits src_bits;
1031 struct bitblt_coords src, dst;
1032 DWORD err;
1033 int dst_to_src_offset;
1034 BOOL empty_rect;
1036 src.visrect.left = 0;
1037 src.visrect.top = 0;
1038 src.visrect.right = bmp->bitmap.bmWidth;
1039 src.visrect.bottom = bmp->bitmap.bmHeight;
1041 dst.visrect.left = 0;
1042 dst.visrect.top = 0;
1043 dst.visrect.right = dst_info->bmiHeader.biWidth;
1044 dst.visrect.bottom = abs( dst_info->bmiHeader.biHeight );
1046 if (startscan >= dst.visrect.bottom)
1048 lines = 1; /* yes, this is strange */
1049 goto empty_image;
1052 if (dst_info->bmiHeader.biHeight > 0)
1054 dst_to_src_offset = -startscan;
1055 lines = min( lines, dst.visrect.bottom - startscan );
1056 if (lines < dst.visrect.bottom) dst.visrect.top = dst.visrect.bottom - lines;
1058 else
1060 dst_to_src_offset = dst.visrect.bottom - lines - startscan;
1061 if (dst_to_src_offset < 0)
1063 dst_to_src_offset = 0;
1064 lines = dst.visrect.bottom - startscan;
1066 if (lines < dst.visrect.bottom) dst.visrect.bottom = lines;
1069 offset_rect( &dst.visrect, 0, dst_to_src_offset );
1070 empty_rect = !intersect_rect( &src.visrect, &src.visrect, &dst.visrect );
1071 dst.visrect = src.visrect;
1072 offset_rect( &dst.visrect, 0, -dst_to_src_offset );
1074 if (dst_info->bmiHeader.biHeight > 0)
1076 if (dst.visrect.bottom < dst_info->bmiHeader.biHeight)
1078 int pad_lines = min( dst_info->bmiHeader.biHeight - dst.visrect.bottom, lines );
1079 int pad_bytes = pad_lines * get_dib_stride( width, bpp );
1080 memset( bits, 0, pad_bytes );
1081 bits = (char *)bits + pad_bytes;
1084 else
1086 if (dst.visrect.bottom < lines)
1088 int pad_lines = lines - dst.visrect.bottom, stride = get_dib_stride( width, bpp );
1089 int pad_bytes = pad_lines * stride;
1090 memset( (char *)bits + dst.visrect.bottom * stride, 0, pad_bytes );
1094 if (empty_rect)
1096 lines = 0;
1097 goto empty_image;
1100 src.x = src.visrect.left;
1101 src.y = src.visrect.top;
1102 src.width = src.visrect.right - src.visrect.left;
1103 src.height = src.visrect.bottom - src.visrect.top;
1105 lines = src.height;
1107 err = bmp->funcs->pGetImage( NULL, hbitmap, src_info, &src_bits, &src );
1109 if(err)
1111 lines = 0;
1112 goto done;
1115 if (src_info->bmiHeader.biBitCount <= 8 && src_info->bmiHeader.biClrUsed == 0)
1117 if (bmp->dib)
1118 memcpy( src_info->bmiColors, bmp->color_table, bmp->nb_colors * sizeof(RGBQUAD) );
1119 else
1120 fill_default_color_table( src_info );
1123 if(dst_info->bmiHeader.biHeight > 0)
1124 dst_info->bmiHeader.biHeight = src.height;
1125 else
1126 dst_info->bmiHeader.biHeight = -src.height;
1128 convert_bitmapinfo( src_info, src_bits.ptr, &src.visrect, dst_info, bits );
1129 if (src_bits.free) src_bits.free( &src_bits );
1131 else lines = abs(height);
1133 empty_image:
1134 if (coloruse == DIB_PAL_COLORS)
1136 WORD *index = (WORD *)dst_info->bmiColors;
1137 for (i = 0; i < colors; i++, index++)
1138 *index = i;
1141 copy_color_info( info, dst_info, coloruse );
1143 done:
1144 release_dc_ptr( dc );
1145 GDI_ReleaseObj( hbitmap );
1146 return lines;
1150 /***********************************************************************
1151 * CreateDIBitmap (GDI32.@)
1153 * Creates a DDB (device dependent bitmap) from a DIB.
1154 * The DDB will have the same color depth as the reference DC.
1156 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
1157 DWORD init, LPCVOID bits, const BITMAPINFO *data,
1158 UINT coloruse )
1160 HBITMAP handle;
1161 LONG width;
1162 LONG height;
1163 WORD planes, bpp;
1164 DWORD compr, size;
1166 if (!header) return 0;
1168 if (DIB_GetBitmapInfo( header, &width, &height, &planes, &bpp, &compr, &size ) == -1) return 0;
1170 if (width < 0)
1172 TRACE("Bitmap has a negative width\n");
1173 return 0;
1176 /* Top-down DIBs have a negative height */
1177 if (height < 0) height = -height;
1179 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1180 hdc, header, init, bits, data, coloruse, width, height, bpp, compr);
1182 if (hdc == NULL)
1183 handle = CreateBitmap( width, height, 1, 1, NULL );
1184 else
1185 handle = CreateCompatibleBitmap( hdc, width, height );
1187 if (handle)
1189 if (init & CBM_INIT)
1191 if (SetDIBits( hdc, handle, 0, height, bits, data, coloruse ) == 0)
1193 DeleteObject( handle );
1194 handle = 0;
1199 return handle;
1202 /* Copy/synthesize RGB palette from BITMAPINFO. Ripped from dlls/winex11.drv/dib.c */
1203 static void DIB_CopyColorTable( DC *dc, BITMAPOBJ *bmp, WORD coloruse, const BITMAPINFO *info )
1205 RGBQUAD *colorTable;
1206 unsigned int colors, i;
1207 BOOL core_info = info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER);
1209 if (core_info)
1211 colors = 1 << ((const BITMAPCOREINFO*) info)->bmciHeader.bcBitCount;
1213 else
1215 colors = get_dib_num_of_colors( info );
1218 if (colors > 256) {
1219 ERR("called with >256 colors!\n");
1220 return;
1223 if (!(colorTable = HeapAlloc(GetProcessHeap(), 0, colors * sizeof(RGBQUAD) ))) return;
1225 if(coloruse == DIB_RGB_COLORS)
1227 if (core_info)
1229 /* Convert RGBTRIPLEs to RGBQUADs */
1230 for (i=0; i < colors; i++)
1232 colorTable[i].rgbRed = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtRed;
1233 colorTable[i].rgbGreen = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtGreen;
1234 colorTable[i].rgbBlue = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtBlue;
1235 colorTable[i].rgbReserved = 0;
1238 else
1240 memcpy(colorTable, (const BYTE*) info + (WORD) info->bmiHeader.biSize, colors * sizeof(RGBQUAD));
1243 else
1245 PALETTEENTRY entries[256];
1246 const WORD *index = (const WORD*) ((const BYTE*) info + (WORD) info->bmiHeader.biSize);
1247 UINT count = GetPaletteEntries( dc->hPalette, 0, colors, entries );
1249 for (i = 0; i < colors; i++, index++)
1251 PALETTEENTRY *entry = &entries[*index % count];
1252 colorTable[i].rgbRed = entry->peRed;
1253 colorTable[i].rgbGreen = entry->peGreen;
1254 colorTable[i].rgbBlue = entry->peBlue;
1255 colorTable[i].rgbReserved = 0;
1258 bmp->color_table = colorTable;
1259 bmp->nb_colors = colors;
1262 /***********************************************************************
1263 * CreateDIBSection (GDI32.@)
1265 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
1266 VOID **bits, HANDLE section, DWORD offset)
1268 HBITMAP ret = 0;
1269 DC *dc;
1270 BOOL bDesktopDC = FALSE;
1271 DIBSECTION *dib;
1272 BITMAPOBJ *bmp;
1273 int bitmap_type;
1274 LONG width, height;
1275 WORD planes, bpp;
1276 DWORD compression, sizeImage;
1277 void *mapBits = NULL;
1279 if(!bmi){
1280 if(bits) *bits = NULL;
1281 return NULL;
1284 if (((bitmap_type = DIB_GetBitmapInfo( &bmi->bmiHeader, &width, &height,
1285 &planes, &bpp, &compression, &sizeImage )) == -1))
1286 return 0;
1288 switch (bpp)
1290 case 16:
1291 case 32:
1292 if (compression == BI_BITFIELDS) break;
1293 /* fall through */
1294 case 1:
1295 case 4:
1296 case 8:
1297 case 24:
1298 if (compression == BI_RGB) break;
1299 /* fall through */
1300 default:
1301 WARN( "invalid %u bpp compression %u\n", bpp, compression );
1302 return 0;
1305 if (!(dib = HeapAlloc( GetProcessHeap(), 0, sizeof(*dib) ))) return 0;
1307 TRACE("format (%d,%d), planes %d, bpp %d, %s, size %d %s\n",
1308 width, height, planes, bpp, compression == BI_BITFIELDS? "BI_BITFIELDS" : "BI_RGB",
1309 sizeImage, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1311 dib->dsBm.bmType = 0;
1312 dib->dsBm.bmWidth = width;
1313 dib->dsBm.bmHeight = height >= 0 ? height : -height;
1314 dib->dsBm.bmWidthBytes = get_dib_stride( width, bpp );
1315 dib->dsBm.bmPlanes = planes;
1316 dib->dsBm.bmBitsPixel = bpp;
1317 dib->dsBm.bmBits = NULL;
1319 if (!bitmap_type) /* core header */
1321 /* convert the BITMAPCOREHEADER to a BITMAPINFOHEADER */
1322 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1323 dib->dsBmih.biWidth = width;
1324 dib->dsBmih.biHeight = height;
1325 dib->dsBmih.biPlanes = planes;
1326 dib->dsBmih.biBitCount = bpp;
1327 dib->dsBmih.biCompression = compression;
1328 dib->dsBmih.biXPelsPerMeter = 0;
1329 dib->dsBmih.biYPelsPerMeter = 0;
1330 dib->dsBmih.biClrUsed = 0;
1331 dib->dsBmih.biClrImportant = 0;
1333 else
1335 /* truncate extended bitmap headers (BITMAPV4HEADER etc.) */
1336 dib->dsBmih = bmi->bmiHeader;
1337 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1340 /* set number of entries in bmi.bmiColors table */
1341 if( bpp <= 8 )
1342 dib->dsBmih.biClrUsed = 1 << bpp;
1344 dib->dsBmih.biSizeImage = dib->dsBm.bmWidthBytes * dib->dsBm.bmHeight;
1346 /* set dsBitfields values */
1347 dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
1349 if((bpp == 15 || bpp == 16) && compression == BI_RGB)
1351 /* In this case Windows changes biCompression to BI_BITFIELDS,
1352 however for now we won't do this, as there are a lot
1353 of places where BI_BITFIELDS is currently unsupported. */
1355 /* dib->dsBmih.biCompression = compression = BI_BITFIELDS;*/
1356 dib->dsBitfields[0] = 0x7c00;
1357 dib->dsBitfields[1] = 0x03e0;
1358 dib->dsBitfields[2] = 0x001f;
1360 else if(compression == BI_BITFIELDS)
1362 dib->dsBitfields[0] = *(const DWORD *)bmi->bmiColors;
1363 dib->dsBitfields[1] = *((const DWORD *)bmi->bmiColors + 1);
1364 dib->dsBitfields[2] = *((const DWORD *)bmi->bmiColors + 2);
1367 /* get storage location for DIB bits */
1369 if (section)
1371 SYSTEM_INFO SystemInfo;
1372 DWORD mapOffset;
1373 INT mapSize;
1375 GetSystemInfo( &SystemInfo );
1376 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
1377 mapSize = dib->dsBmih.biSizeImage + (offset - mapOffset);
1378 mapBits = MapViewOfFile( section, FILE_MAP_ALL_ACCESS, 0, mapOffset, mapSize );
1379 if (mapBits) dib->dsBm.bmBits = (char *)mapBits + (offset - mapOffset);
1381 else
1383 offset = 0;
1384 dib->dsBm.bmBits = VirtualAlloc( NULL, dib->dsBmih.biSizeImage,
1385 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
1387 dib->dshSection = section;
1388 dib->dsOffset = offset;
1390 if (!dib->dsBm.bmBits)
1392 HeapFree( GetProcessHeap(), 0, dib );
1393 return 0;
1396 /* If the reference hdc is null, take the desktop dc */
1397 if (hdc == 0)
1399 hdc = CreateCompatibleDC(0);
1400 bDesktopDC = TRUE;
1403 if (!(dc = get_dc_ptr( hdc ))) goto error;
1405 /* create Device Dependent Bitmap and add DIB pointer */
1406 ret = CreateBitmap( dib->dsBm.bmWidth, dib->dsBm.bmHeight, 1,
1407 (bpp == 1) ? 1 : GetDeviceCaps(hdc, BITSPIXEL), NULL );
1409 if (ret && ((bmp = GDI_GetObjPtr(ret, OBJ_BITMAP))))
1411 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pCreateDIBSection );
1412 bmp->dib = dib;
1413 bmp->funcs = physdev->funcs;
1414 /* create local copy of DIB palette */
1415 if (bpp <= 8) DIB_CopyColorTable( dc, bmp, usage, bmi );
1416 GDI_ReleaseObj( ret );
1418 if (!physdev->funcs->pCreateDIBSection( physdev, ret, bmi, usage ))
1420 DeleteObject( ret );
1421 ret = 0;
1425 release_dc_ptr( dc );
1426 if (bDesktopDC) DeleteDC( hdc );
1427 if (ret && bits) *bits = dib->dsBm.bmBits;
1428 return ret;
1430 error:
1431 if (bDesktopDC) DeleteDC( hdc );
1432 if (section) UnmapViewOfFile( mapBits );
1433 else if (!offset) VirtualFree( dib->dsBm.bmBits, 0, MEM_RELEASE );
1434 HeapFree( GetProcessHeap(), 0, dib );
1435 return 0;