1 /*
2 * GDI device-independent bitmaps
3 *
4 * Copyright 1993,1994 Alexandre Julliard
5 *
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.
10 *
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.
15 *
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
19 */
20
21 /*
22 Important information:
23
24 * Current Windows versions support two different DIB structures:
25
26 - BITMAPCOREINFO / BITMAPCOREHEADER (legacy structures; used in OS/2)
27 - BITMAPINFO / BITMAPINFOHEADER
28
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.
33
34
35 * The palettes are stored in different formats:
36
37 - BITMAPCOREINFO: Array of RGBTRIPLE
38 - BITMAPINFO: Array of RGBQUAD
39
40
41 * There are even more DIB headers, but they all extend BITMAPINFOHEADER:
42
43 - BITMAPV4HEADER: Introduced in Windows 95 / NT 4.0
44 - BITMAPV5HEADER: Introduced in Windows 98 / 2000
45
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.
49
50
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:
54
55 BITMAPINFO* info;
56 void* colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
57
58
59 * More information:
60 Search for "Bitmap Structures" in MSDN
61 */
62
63 #include <stdarg.h>
64 #include <stdlib.h>
65 #include <string.h>
66
67 #include "windef.h"
68 #include "winbase.h"
69 #include "gdi_private.h"
70 #include "wine/debug.h"
71
72 WINE_DEFAULT_DEBUG_CHANNEL(bitmap);
73
74
75 /*
76 Some of the following helper functions are duplicated in
77 dlls/x11drv/dib.c
78 */
79
80 /***********************************************************************
81 * DIB_GetDIBWidthBytes
82 *
83 * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
84 */
85 int DIB_GetDIBWidthBytes( int width, int depth )
86 {
87 int words;
88
89 switch(depth)
90 {
91 case 1: words = (width + 31) / 32; break;
92 case 4: words = (width + 7) / 8; break;
93 case 8: words = (width + 3) / 4; break;
94 case 15:
95 case 16: words = (width + 1) / 2; break;
96 case 24: words = (width * 3 + 3)/4; break;
97
98 default:
99 WARN("(%d): Unsupported depth\n", depth );
100 /* fall through */
101 case 32:
102 words = width;
103 }
104 return 4 * words;
105 }
106
107 /***********************************************************************
108 * DIB_GetDIBImageBytes
109 *
110 * Return the number of bytes used to hold the image in a DIB bitmap.
111 */
112 int DIB_GetDIBImageBytes( int width, int height, int depth )
113 {
114 return DIB_GetDIBWidthBytes( width, depth ) * abs( height );
115 }
116
117
118 /***********************************************************************
119 * bitmap_info_size
120 *
121 * Return the size of the bitmap info structure including color table.
122 */
123 int bitmap_info_size( const BITMAPINFO * info, WORD coloruse )
124 {
125 unsigned int colors, size, masks = 0;
126
127 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
128 {
129 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
130 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
131 return sizeof(BITMAPCOREHEADER) + colors *
132 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
133 }
134 else /* assume BITMAPINFOHEADER */
135 {
136 colors = info->bmiHeader.biClrUsed;
137 if (colors > 256) colors = 256;
138 if (!colors && (info->bmiHeader.biBitCount <= 8))
139 colors = 1 << info->bmiHeader.biBitCount;
140 if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3;
141 size = max( info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD) );
142 return size + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
143 }
144 }
145
146
147 /***********************************************************************
148 * DIB_GetBitmapInfo
149 *
150 * Get the info from a bitmap header.
151 * Return 0 for COREHEADER, 1 for INFOHEADER, -1 for error.
152 */
153 int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
154 LONG *height, WORD *planes, WORD *bpp, DWORD *compr, DWORD *size )
155 {
156 if (header->biSize == sizeof(BITMAPCOREHEADER))
157 {
158 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)header;
159 *width = core->bcWidth;
160 *height = core->bcHeight;
161 *planes = core->bcPlanes;
162 *bpp = core->bcBitCount;
163 *compr = 0;
164 *size = 0;
165 return 0;
166 }
167 if (header->biSize >= sizeof(BITMAPINFOHEADER)) /* assume BITMAPINFOHEADER */
168 {
169 *width = header->biWidth;
170 *height = header->biHeight;
171 *planes = header->biPlanes;
172 *bpp = header->biBitCount;
173 *compr = header->biCompression;
174 *size = header->biSizeImage;
175 return 1;
176 }
177 ERR("(%d): unknown/wrong size for header\n", header->biSize );
178 return -1;
179 }
180
181 /* nulldrv fallback implementation using SetDIBits/StretchBlt */
182 INT CDECL nulldrv_StretchDIBits( PHYSDEV dev, INT xDst, INT yDst, INT widthDst, INT heightDst,
183 INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits,
184 const BITMAPINFO *info, UINT coloruse, DWORD rop )
185 {
186 DC *dc = get_nulldrv_dc( dev );
187 INT ret;
188 LONG width, height;
189 WORD planes, bpp;
190 DWORD compr, size;
191 HBITMAP hBitmap;
192 HDC hdcMem;
193
194 /* make sure we have a real implementation for StretchBlt and SetDIBits */
195 if (GET_DC_PHYSDEV( dc, pStretchBlt ) == dev || GET_DC_PHYSDEV( dc, pSetDIBits ) == dev)
196 return 0;
197
198 if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size ) == -1)
199 return 0;
200
201 if (width < 0) return 0;
202
203 if (xSrc == 0 && ySrc == 0 && widthDst == widthSrc && heightDst == heightSrc &&
204 info->bmiHeader.biCompression == BI_RGB)
205 {
206 /* Windows appears to have a fast case optimization
207 * that uses the wrong origin for top-down DIBs */
208 if (height < 0 && heightSrc < abs(height)) ySrc = abs(height) - heightSrc;
209
210 if (xDst == 0 && yDst == 0 && info->bmiHeader.biCompression == BI_RGB && rop == SRCCOPY)
211 {
212 BITMAP bm;
213 hBitmap = GetCurrentObject( dev->hdc, OBJ_BITMAP );
214 if (GetObjectW( hBitmap, sizeof(bm), &bm ) &&
215 bm.bmWidth == widthSrc && bm.bmHeight == heightSrc &&
216 bm.bmBitsPixel == bpp && bm.bmPlanes == planes)
217 {
218 /* fast path */
219 return SetDIBits( dev->hdc, hBitmap, 0, height, bits, info, coloruse );
220 }
221 }
222 }
223
224 hdcMem = CreateCompatibleDC( dev->hdc );
225 hBitmap = CreateCompatibleBitmap( dev->hdc, width, height );
226 SelectObject( hdcMem, hBitmap );
227 if (coloruse == DIB_PAL_COLORS)
228 SelectPalette( hdcMem, GetCurrentObject( dev->hdc, OBJ_PAL ), FALSE );
229
230 if (info->bmiHeader.biCompression == BI_RLE4 || info->bmiHeader.biCompression == BI_RLE8)
231 {
232 /* when RLE compression is used, there may be some gaps (ie the DIB doesn't
233 * contain all the rectangle described in bmiHeader, but only part of it.
234 * This mean that those undescribed pixels must be left untouched.
235 * So, we first copy on a memory bitmap the current content of the
236 * destination rectangle, blit the DIB bits on top of it - hence leaving
237 * the gaps untouched -, and blitting the rectangle back.
238 * This insure that gaps are untouched on the destination rectangle
239 */
240 StretchBlt( hdcMem, xSrc, abs(height) - heightSrc - ySrc, widthSrc, heightSrc,
241 dev->hdc, xDst, yDst, widthDst, heightDst, rop );
242 }
243 ret = SetDIBits( hdcMem, hBitmap, 0, height, bits, info, coloruse );
244 if (ret) StretchBlt( dev->hdc, xDst, yDst, widthDst, heightDst,
245 hdcMem, xSrc, abs(height) - heightSrc - ySrc, widthSrc, heightSrc, rop );
246 DeleteDC( hdcMem );
247 DeleteObject( hBitmap );
248 return ret;
249 }
250
251 /***********************************************************************
252 * StretchDIBits (GDI32.@)
253 */
254 INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst, INT heightDst,
255 INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits,
256 const BITMAPINFO *info, UINT coloruse, DWORD rop )
257 {
258 DC *dc;
259 INT ret = 0;
260
261 if (!bits || !info) return 0;
262
263 if ((dc = get_dc_ptr( hdc )))
264 {
265 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pStretchDIBits );
266 update_dc( dc );
267 ret = physdev->funcs->pStretchDIBits( physdev, xDst, yDst, widthDst, heightDst,
268 xSrc, ySrc, widthSrc, heightSrc, bits, info, coloruse, rop );
269 release_dc_ptr( dc );
270 }
271 return ret;
272 }
273
274
275 /******************************************************************************
276 * SetDIBits [GDI32.@]
277 *
278 * Sets pixels in a bitmap using colors from DIB.
279 *
280 * PARAMS
281 * hdc [I] Handle to device context
282 * hbitmap [I] Handle to bitmap
283 * startscan [I] Starting scan line
284 * lines [I] Number of scan lines
285 * bits [I] Array of bitmap bits
286 * info [I] Address of structure with data
287 * coloruse [I] Type of color indexes to use
288 *
289 * RETURNS
290 * Success: Number of scan lines copied
291 * Failure: 0
292 */
293 INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
294 UINT lines, LPCVOID bits, const BITMAPINFO *info,
295 UINT coloruse )
296 {
297 DC *dc = get_dc_ptr( hdc );
298 BOOL delete_hdc = FALSE;
299 PHYSDEV physdev;
300 BITMAPOBJ *bitmap;
301 INT result = 0;
302
303 if (coloruse == DIB_RGB_COLORS && !dc)
304 {
305 hdc = CreateCompatibleDC(0);
306 dc = get_dc_ptr( hdc );
307 delete_hdc = TRUE;
308 }
309
310 if (!dc) return 0;
311
312 update_dc( dc );
313
314 if (!(bitmap = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
315 {
316 release_dc_ptr( dc );
317 if (delete_hdc) DeleteDC(hdc);
318 return 0;
319 }
320
321 physdev = GET_DC_PHYSDEV( dc, pSetDIBits );
322 if (BITMAP_SetOwnerDC( hbitmap, physdev ))
323 result = physdev->funcs->pSetDIBits( physdev, hbitmap, startscan, lines, bits, info, coloruse );
324
325 GDI_ReleaseObj( hbitmap );
326 release_dc_ptr( dc );
327 if (delete_hdc) DeleteDC(hdc);
328 return result;
329 }
330
331
332 /***********************************************************************
333 * SetDIBitsToDevice (GDI32.@)
334 */
335 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
336 DWORD cy, INT xSrc, INT ySrc, UINT startscan,
337 UINT lines, LPCVOID bits, const BITMAPINFO *info,
338 UINT coloruse )
339 {
340 INT ret = 0;
341 DC *dc;
342
343 if (!bits) return 0;
344
345 if ((dc = get_dc_ptr( hdc )))
346 {
347 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDIBitsToDevice );
348 update_dc( dc );
349 ret = physdev->funcs->pSetDIBitsToDevice( physdev, xDest, yDest, cx, cy, xSrc,
350 ySrc, startscan, lines, bits, info, coloruse );
351 release_dc_ptr( dc );
352 }
353 return ret;
354 }
355
356 /***********************************************************************
357 * SetDIBColorTable (GDI32.@)
358 */
359 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, CONST RGBQUAD *colors )
360 {
361 DC * dc;
362 UINT result = 0;
363 BITMAPOBJ * bitmap;
364
365 if (!(dc = get_dc_ptr( hdc ))) return 0;
366
367 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
368 {
369 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDIBColorTable );
370
371 /* Check if currently selected bitmap is a DIB */
372 if (bitmap->color_table)
373 {
374 if (startpos < bitmap->nb_colors)
375 {
376 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
377 memcpy(bitmap->color_table + startpos, colors, entries * sizeof(RGBQUAD));
378 result = entries;
379 }
380 }
381 GDI_ReleaseObj( dc->hBitmap );
382 physdev->funcs->pSetDIBColorTable( physdev, startpos, entries, colors );
383 }
384 release_dc_ptr( dc );
385 return result;
386 }
387
388
389 /***********************************************************************
390 * GetDIBColorTable (GDI32.@)
391 */
392 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
393 {
394 DC * dc;
395 BITMAPOBJ *bitmap;
396 UINT result = 0;
397
398 if (!(dc = get_dc_ptr( hdc ))) return 0;
399
400 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
401 {
402 /* Check if currently selected bitmap is a DIB */
403 if (bitmap->color_table)
404 {
405 if (startpos < bitmap->nb_colors)
406 {
407 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
408 memcpy(colors, bitmap->color_table + startpos, entries * sizeof(RGBQUAD));
409 result = entries;
410 }
411 }
412 GDI_ReleaseObj( dc->hBitmap );
413 }
414 release_dc_ptr( dc );
415 return result;
416 }
417
418 /* FIXME the following two structs should be combined with __sysPalTemplate in
419 objects/color.c - this should happen after de-X11-ing both of these
420 files.
421 NB. RGBQUAD and PALETTEENTRY have different orderings of red, green
422 and blue - sigh */
423
424 static const RGBQUAD EGAColorsQuads[16] = {
425 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
426 { 0x00, 0x00, 0x00, 0x00 },
427 { 0x00, 0x00, 0x80, 0x00 },
428 { 0x00, 0x80, 0x00, 0x00 },
429 { 0x00, 0x80, 0x80, 0x00 },
430 { 0x80, 0x00, 0x00, 0x00 },
431 { 0x80, 0x00, 0x80, 0x00 },
432 { 0x80, 0x80, 0x00, 0x00 },
433 { 0x80, 0x80, 0x80, 0x00 },
434 { 0xc0, 0xc0, 0xc0, 0x00 },
435 { 0x00, 0x00, 0xff, 0x00 },
436 { 0x00, 0xff, 0x00, 0x00 },
437 { 0x00, 0xff, 0xff, 0x00 },
438 { 0xff, 0x00, 0x00, 0x00 },
439 { 0xff, 0x00, 0xff, 0x00 },
440 { 0xff, 0xff, 0x00, 0x00 },
441 { 0xff, 0xff, 0xff, 0x00 }
442 };
443
444 static const RGBTRIPLE EGAColorsTriples[16] = {
445 /* rgbBlue, rgbGreen, rgbRed */
446 { 0x00, 0x00, 0x00 },
447 { 0x00, 0x00, 0x80 },
448 { 0x00, 0x80, 0x00 },
449 { 0x00, 0x80, 0x80 },
450 { 0x80, 0x00, 0x00 },
451 { 0x80, 0x00, 0x80 },
452 { 0x80, 0x80, 0x00 },
453 { 0x80, 0x80, 0x80 },
454 { 0xc0, 0xc0, 0xc0 },
455 { 0x00, 0x00, 0xff },
456 { 0x00, 0xff, 0x00 },
457 { 0x00, 0xff, 0xff },
458 { 0xff, 0x00, 0x00 } ,
459 { 0xff, 0x00, 0xff },
460 { 0xff, 0xff, 0x00 },
461 { 0xff, 0xff, 0xff }
462 };
463
464 static const RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
465 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
466 { 0x00, 0x00, 0x00, 0x00 },
467 { 0x00, 0x00, 0x80, 0x00 },
468 { 0x00, 0x80, 0x00, 0x00 },
469 { 0x00, 0x80, 0x80, 0x00 },
470 { 0x80, 0x00, 0x00, 0x00 },
471 { 0x80, 0x00, 0x80, 0x00 },
472 { 0x80, 0x80, 0x00, 0x00 },
473 { 0xc0, 0xc0, 0xc0, 0x00 },
474 { 0xc0, 0xdc, 0xc0, 0x00 },
475 { 0xf0, 0xca, 0xa6, 0x00 },
476 { 0xf0, 0xfb, 0xff, 0x00 },
477 { 0xa4, 0xa0, 0xa0, 0x00 },
478 { 0x80, 0x80, 0x80, 0x00 },
479 { 0x00, 0x00, 0xf0, 0x00 },
480 { 0x00, 0xff, 0x00, 0x00 },
481 { 0x00, 0xff, 0xff, 0x00 },
482 { 0xff, 0x00, 0x00, 0x00 },
483 { 0xff, 0x00, 0xff, 0x00 },
484 { 0xff, 0xff, 0x00, 0x00 },
485 { 0xff, 0xff, 0xff, 0x00 }
486 };
487
488 static const RGBTRIPLE DefLogPaletteTriples[20] = { /* Copy of Default Logical Palette */
489 /* rgbBlue, rgbGreen, rgbRed */
490 { 0x00, 0x00, 0x00 },
491 { 0x00, 0x00, 0x80 },
492 { 0x00, 0x80, 0x00 },
493 { 0x00, 0x80, 0x80 },
494 { 0x80, 0x00, 0x00 },
495 { 0x80, 0x00, 0x80 },
496 { 0x80, 0x80, 0x00 },
497 { 0xc0, 0xc0, 0xc0 },
498 { 0xc0, 0xdc, 0xc0 },
499 { 0xf0, 0xca, 0xa6 },
500 { 0xf0, 0xfb, 0xff },
501 { 0xa4, 0xa0, 0xa0 },
502 { 0x80, 0x80, 0x80 },
503 { 0x00, 0x00, 0xf0 },
504 { 0x00, 0xff, 0x00 },
505 { 0x00, 0xff, 0xff },
506 { 0xff, 0x00, 0x00 },
507 { 0xff, 0x00, 0xff },
508 { 0xff, 0xff, 0x00 },
509 { 0xff, 0xff, 0xff}
510 };
511
512
513 /******************************************************************************
514 * GetDIBits [GDI32.@]
515 *
516 * Retrieves bits of bitmap and copies to buffer.
517 *
518 * RETURNS
519 * Success: Number of scan lines copied from bitmap
520 * Failure: 0
521 */
522 INT WINAPI GetDIBits(
523 HDC hdc, /* [in] Handle to device context */
524 HBITMAP hbitmap, /* [in] Handle to bitmap */
525 UINT startscan, /* [in] First scan line to set in dest bitmap */
526 UINT lines, /* [in] Number of scan lines to copy */
527 LPVOID bits, /* [out] Address of array for bitmap bits */
528 BITMAPINFO * info, /* [out] Address of structure with bitmap data */
529 UINT coloruse) /* [in] RGB or palette index */
530 {
531 DC * dc;
532 BITMAPOBJ * bmp;
533 int i;
534 int bitmap_type;
535 BOOL core_header;
536 LONG width;
537 LONG height;
538 WORD planes, bpp;
539 DWORD compr, size;
540 void* colorPtr;
541 RGBTRIPLE* rgbTriples;
542 RGBQUAD* rgbQuads;
543
544 if (!info) return 0;
545
546 bitmap_type = DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size);
547 if (bitmap_type == -1)
548 {
549 ERR("Invalid bitmap format\n");
550 return 0;
551 }
552 core_header = (bitmap_type == 0);
553 if (!(dc = get_dc_ptr( hdc )))
554 {
555 SetLastError( ERROR_INVALID_PARAMETER );
556 return 0;
557 }
558 update_dc( dc );
559 if (!(bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
560 {
561 release_dc_ptr( dc );
562 return 0;
563 }
564
565 colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
566 rgbTriples = colorPtr;
567 rgbQuads = colorPtr;
568
569 /* Transfer color info */
570
571 switch (bpp)
572 {
573 case 0: /* query bitmap info only */
574 if (core_header)
575 {
576 BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) info;
577 coreheader->bcWidth = bmp->bitmap.bmWidth;
578 coreheader->bcHeight = bmp->bitmap.bmHeight;
579 coreheader->bcPlanes = 1;
580 coreheader->bcBitCount = bmp->bitmap.bmBitsPixel;
581 }
582 else
583 {
584 info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
585 info->bmiHeader.biHeight = bmp->bitmap.bmHeight;
586 info->bmiHeader.biPlanes = 1;
587 info->bmiHeader.biSizeImage =
588 DIB_GetDIBImageBytes( bmp->bitmap.bmWidth,
589 bmp->bitmap.bmHeight,
590 bmp->bitmap.bmBitsPixel );
591 if (bmp->dib)
592 {
593 info->bmiHeader.biBitCount = bmp->dib->dsBm.bmBitsPixel;
594 switch (bmp->dib->dsBm.bmBitsPixel)
595 {
596 case 16:
597 case 32:
598 info->bmiHeader.biCompression = BI_BITFIELDS;
599 break;
600 default:
601 info->bmiHeader.biCompression = BI_RGB;
602 break;
603 }
604 }
605 else
606 {
607 info->bmiHeader.biCompression = (bmp->bitmap.bmBitsPixel > 8) ? BI_BITFIELDS : BI_RGB;
608 info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
609 }
610 info->bmiHeader.biXPelsPerMeter = 0;
611 info->bmiHeader.biYPelsPerMeter = 0;
612 info->bmiHeader.biClrUsed = 0;
613 info->bmiHeader.biClrImportant = 0;
614
615 /* Windows 2000 doesn't touch the additional struct members if
616 it's a BITMAPV4HEADER or a BITMAPV5HEADER */
617 }
618 lines = abs(bmp->bitmap.bmHeight);
619 goto done;
620
621 case 1:
622 case 4:
623 case 8:
624 if (!core_header) info->bmiHeader.biClrUsed = 0;
625
626 /* If the bitmap object already has a dib section at the
627 same color depth then get the color map from it */
628 if (bmp->dib && bmp->dib->dsBm.bmBitsPixel == bpp) {
629 if(coloruse == DIB_RGB_COLORS) {
630 unsigned int colors = min( bmp->nb_colors, 1 << bpp );
631
632 if (core_header)
633 {
634 /* Convert the color table (RGBQUAD to RGBTRIPLE) */
635 RGBTRIPLE* index = rgbTriples;
636
637 for (i=0; i < colors; i++, index++)
638 {
639 index->rgbtRed = bmp->color_table[i].rgbRed;
640 index->rgbtGreen = bmp->color_table[i].rgbGreen;
641 index->rgbtBlue = bmp->color_table[i].rgbBlue;
642 }
643 }
644 else
645 {
646 if (colors != 1 << bpp) info->bmiHeader.biClrUsed = colors;
647 memcpy(colorPtr, bmp->color_table, colors * sizeof(RGBQUAD));
648 }
649 }
650 else {
651 WORD *index = colorPtr;
652 for(i = 0; i < 1 << info->bmiHeader.biBitCount; i++, index++)
653 *index = i;
654 }
655 }
656 else {
657 if (coloruse == DIB_PAL_COLORS) {
658 for (i = 0; i < (1 << bpp); i++)
659 ((WORD *)colorPtr)[i] = (WORD)i;
660 }
661 else if(bpp > 1 && bpp == bmp->bitmap.bmBitsPixel) {
662 /* For color DDBs in native depth (mono DDBs always have
663 a black/white palette):
664 Generate the color map from the selected palette */
665 PALETTEENTRY palEntry[256];
666
667 memset( palEntry, 0, sizeof(palEntry) );
668 if (!GetPaletteEntries( dc->hPalette, 0, 1 << bmp->bitmap.bmBitsPixel, palEntry ))
669 {
670 release_dc_ptr( dc );
671 GDI_ReleaseObj( hbitmap );
672 return 0;
673 }
674 for (i = 0; i < (1 << bmp->bitmap.bmBitsPixel); i++) {
675 if (core_header)
676 {
677 rgbTriples[i].rgbtRed = palEntry[i].peRed;
678 rgbTriples[i].rgbtGreen = palEntry[i].peGreen;
679 rgbTriples[i].rgbtBlue = palEntry[i].peBlue;
680 }
681 else
682 {
683 rgbQuads[i].rgbRed = palEntry[i].peRed;
684 rgbQuads[i].rgbGreen = palEntry[i].peGreen;
685 rgbQuads[i].rgbBlue = palEntry[i].peBlue;
686 rgbQuads[i].rgbReserved = 0;
687 }
688 }
689 } else {
690 switch (bpp) {
691 case 1:
692 if (core_header)
693 {
694 rgbTriples[0].rgbtRed = rgbTriples[0].rgbtGreen =
695 rgbTriples[0].rgbtBlue = 0;
696 rgbTriples[1].rgbtRed = rgbTriples[1].rgbtGreen =
697 rgbTriples[1].rgbtBlue = 0xff;
698 }
699 else
700 {
701 rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen =
702 rgbQuads[0].rgbBlue = 0;
703 rgbQuads[0].rgbReserved = 0;
704 rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen =
705 rgbQuads[1].rgbBlue = 0xff;
706 rgbQuads[1].rgbReserved = 0;
707 }
708 break;
709
710 case 4:
711 if (core_header)
712 memcpy(colorPtr, EGAColorsTriples, sizeof(EGAColorsTriples));
713 else
714 memcpy(colorPtr, EGAColorsQuads, sizeof(EGAColorsQuads));
715
716 break;
717
718 case 8:
719 {
720 if (core_header)
721 {
722 INT r, g, b;
723 RGBTRIPLE *color;
724
725 memcpy(rgbTriples, DefLogPaletteTriples,
726 10 * sizeof(RGBTRIPLE));
727 memcpy(rgbTriples + 246, DefLogPaletteTriples + 10,
728 10 * sizeof(RGBTRIPLE));
729 color = rgbTriples + 10;
730 for(r = 0; r <= 5; r++) /* FIXME */
731 for(g = 0; g <= 5; g++)
732 for(b = 0; b <= 5; b++) {
733 color->rgbtRed = (r * 0xff) / 5;
734 color->rgbtGreen = (g * 0xff) / 5;
735 color->rgbtBlue = (b * 0xff) / 5;
736 color++;
737 }
738 }
739 else
740 {
741 INT r, g, b;
742 RGBQUAD *color;
743
744 memcpy(rgbQuads, DefLogPaletteQuads,
745 10 * sizeof(RGBQUAD));
746 memcpy(rgbQuads + 246, DefLogPaletteQuads + 10,
747 10 * sizeof(RGBQUAD));
748 color = rgbQuads + 10;
749 for(r = 0; r <= 5; r++) /* FIXME */
750 for(g = 0; g <= 5; g++)
751 for(b = 0; b <= 5; b++) {
752 color->rgbRed = (r * 0xff) / 5;
753 color->rgbGreen = (g * 0xff) / 5;
754 color->rgbBlue = (b * 0xff) / 5;
755 color->rgbReserved = 0;
756 color++;
757 }
758 }
759 }
760 }
761 }
762 }
763 break;
764
765 case 15:
766 if (info->bmiHeader.biCompression == BI_BITFIELDS)
767 {
768 ((PDWORD)info->bmiColors)[0] = 0x7c00;
769 ((PDWORD)info->bmiColors)[1] = 0x03e0;
770 ((PDWORD)info->bmiColors)[2] = 0x001f;
771 }
772 break;
773
774 case 16:
775 if (info->bmiHeader.biCompression == BI_BITFIELDS)
776 {
777 if (bmp->dib)
778 {
779 if (bmp->dib->dsBmih.biCompression == BI_BITFIELDS)
780 memcpy( info->bmiColors, bmp->dib->dsBitfields, 3 * sizeof(DWORD) );
781 else
782 {
783 ((PDWORD)info->bmiColors)[0] = 0x7c00;
784 ((PDWORD)info->bmiColors)[1] = 0x03e0;
785 ((PDWORD)info->bmiColors)[2] = 0x001f;
786 }
787 }
788 else
789 {
790 ((PDWORD)info->bmiColors)[0] = 0xf800;
791 ((PDWORD)info->bmiColors)[1] = 0x07e0;
792 ((PDWORD)info->bmiColors)[2] = 0x001f;
793 }
794 }
795 break;
796
797 case 24:
798 case 32:
799 if (info->bmiHeader.biCompression == BI_BITFIELDS)
800 {
801 if (bmp->dib && bmp->dib->dsBmih.biCompression == BI_BITFIELDS)
802 memcpy( info->bmiColors, bmp->dib->dsBitfields, 3 * sizeof(DWORD) );
803 else
804 {
805 ((PDWORD)info->bmiColors)[0] = 0xff0000;
806 ((PDWORD)info->bmiColors)[1] = 0x00ff00;
807 ((PDWORD)info->bmiColors)[2] = 0x0000ff;
808 }
809 }
810 break;
811 }
812
813 if (bits && lines)
814 {
815 /* If the bitmap object already have a dib section that contains image data, get the bits from it */
816 if(bmp->dib && bmp->dib->dsBm.bmBitsPixel >= 15 && bpp >= 15)
817 {
818 /*FIXME: Only RGB dibs supported for now */
819 unsigned int srcwidth = bmp->dib->dsBm.bmWidth;
820 int srcwidthb = bmp->dib->dsBm.bmWidthBytes;
821 unsigned int dstwidth = width;
822 int dstwidthb = DIB_GetDIBWidthBytes( width, bpp );
823 LPBYTE dbits = bits, sbits = (LPBYTE) bmp->dib->dsBm.bmBits + (startscan * srcwidthb);
824 unsigned int x, y, width, widthb;
825
826 /*
827 * If copying from a top-down source bitmap, move the source
828 * pointer to the end of the source bitmap and negate the width
829 * so that we copy the bits upside-down.
830 */
831 if (bmp->dib->dsBmih.biHeight < 0)
832 {
833 sbits += (srcwidthb * (int)(abs(bmp->dib->dsBmih.biHeight) - 2 * startscan - 1));
834 srcwidthb = -srcwidthb;
835 }
836 /*Same for the destination.*/
837 if (height < 0)
838 {
839 dbits = (LPBYTE)bits + (dstwidthb * (lines - 1));
840 dstwidthb = -dstwidthb;
841 }
842 switch( bpp ) {
843
844 case 15:
845 case 16: /* 16 bpp dstDIB */
846 {
847 LPWORD dstbits = (LPWORD)dbits;
848 WORD rmask = 0x7c00, gmask= 0x03e0, bmask = 0x001f;
849
850 /* FIXME: BI_BITFIELDS not supported yet */
851
852 switch(bmp->dib->dsBm.bmBitsPixel) {
853
854 case 16: /* 16 bpp srcDIB -> 16 bpp dstDIB */
855 {
856 widthb = min(abs(srcwidthb), abs(dstwidthb));
857 /* FIXME: BI_BITFIELDS not supported yet */
858 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
859 memcpy(dbits, sbits, widthb);
860 }
861 break;
862
863 case 24: /* 24 bpp srcDIB -> 16 bpp dstDIB */
864 {
865 LPBYTE srcbits = sbits;
866
867 width = min(srcwidth, dstwidth);
868 for( y = 0; y < lines; y++) {
869 for( x = 0; x < width; x++, srcbits += 3)
870 *dstbits++ = ((srcbits[0] >> 3) & bmask) |
871 (((WORD)srcbits[1] << 2) & gmask) |
872 (((WORD)srcbits[2] << 7) & rmask);
873
874 dstbits = (LPWORD)(dbits+=dstwidthb);
875 srcbits = (sbits += srcwidthb);
876 }
877 }
878 break;
879
880 case 32: /* 32 bpp srcDIB -> 16 bpp dstDIB */
881 {
882 LPDWORD srcbits = (LPDWORD)sbits;
883 DWORD val;
884
885 width = min(srcwidth, dstwidth);
886 for( y = 0; y < lines; y++) {
887 for( x = 0; x < width; x++ ) {
888 val = *srcbits++;
889 *dstbits++ = (WORD)(((val >> 3) & bmask) | ((val >> 6) & gmask) |
890 ((val >> 9) & rmask));
891 }
892 dstbits = (LPWORD)(dbits+=dstwidthb);
893 srcbits = (LPDWORD)(sbits+=srcwidthb);
894 }
895 }
896 break;
897
898 default: /* ? bit bmp -> 16 bit DIB */
899 FIXME("15/16 bit DIB %d bit bitmap\n",
900 bmp->bitmap.bmBitsPixel);
901 break;
902 }
903 }
904 break;
905
906 case 24: /* 24 bpp dstDIB */
907 {
908 LPBYTE dstbits = dbits;
909
910 switch(bmp->dib->dsBm.bmBitsPixel) {
911
912 case 16: /* 16 bpp srcDIB -> 24 bpp dstDIB */
913 {
914 LPWORD srcbits = (LPWORD)sbits;
915 WORD val;
916
917 width = min(srcwidth, dstwidth);
918 /* FIXME: BI_BITFIELDS not supported yet */
919 for( y = 0; y < lines; y++) {
920 for( x = 0; x < width; x++ ) {
921 val = *srcbits++;
922 *dstbits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07));
923 *dstbits++ = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07));
924 *dstbits++ = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07));
925 }
926 dstbits = dbits+=dstwidthb;
927 srcbits = (LPWORD)(sbits+=srcwidthb);
928 }
929 }
930 break;
931
932 case 24: /* 24 bpp srcDIB -> 24 bpp dstDIB */
933 {
934 widthb = min(abs(srcwidthb), abs(dstwidthb));
935 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
936 memcpy(dbits, sbits, widthb);
937 }
938 break;
939
940 case 32: /* 32 bpp srcDIB -> 24 bpp dstDIB */
941 {
942 LPBYTE srcbits = sbits;
943
944 width = min(srcwidth, dstwidth);
945 for( y = 0; y < lines; y++) {
946 for( x = 0; x < width; x++, srcbits++ ) {
947 *dstbits++ = *srcbits++;
948 *dstbits++ = *srcbits++;
949 *dstbits++ = *srcbits++;
950 }
951 dstbits = dbits+=dstwidthb;
952 srcbits = sbits+=srcwidthb;
953 }
954 }
955 break;
956
957 default: /* ? bit bmp -> 24 bit DIB */
958 FIXME("24 bit DIB %d bit bitmap\n",
959 bmp->bitmap.bmBitsPixel);
960 break;
961 }
962 }
963 break;
964
965 case 32: /* 32 bpp dstDIB */
966 {
967 LPDWORD dstbits = (LPDWORD)dbits;
968
969 /* FIXME: BI_BITFIELDS not supported yet */
970
971 switch(bmp->dib->dsBm.bmBitsPixel) {
972 case 16: /* 16 bpp srcDIB -> 32 bpp dstDIB */
973 {
974 LPWORD srcbits = (LPWORD)sbits;
975 DWORD val;
976
977 width = min(srcwidth, dstwidth);
978 /* FIXME: BI_BITFIELDS not supported yet */
979 for( y = 0; y < lines; y++) {
980 for( x = 0; x < width; x++ ) {
981 val = (DWORD)*srcbits++;
982 *dstbits++ = ((val << 3) & 0xf8) | ((val >> 2) & 0x07) |
983 ((val << 6) & 0xf800) | ((val << 1) & 0x0700) |
984 ((val << 9) & 0xf80000) | ((val << 4) & 0x070000);
985 }
986 dstbits=(LPDWORD)(dbits+=dstwidthb);
987 srcbits=(LPWORD)(sbits+=srcwidthb);
988 }
989 }
990 break;
991
992 case 24: /* 24 bpp srcDIB -> 32 bpp dstDIB */
993 {
994 LPBYTE srcbits = sbits;
995
996 width = min(srcwidth, dstwidth);
997 for( y = 0; y < lines; y++) {
998 for( x = 0; x < width; x++, srcbits+=3 )
999 *dstbits++ = srcbits[0] |
1000 (srcbits[1] << 8) |
1001 (srcbits[2] << 16);
1002 dstbits=(LPDWORD)(dbits+=dstwidthb);
1003 srcbits=(sbits+=srcwidthb);
1004 }
1005 }
1006 break;
1007
1008 case 32: /* 32 bpp srcDIB -> 32 bpp dstDIB */
1009 {
1010 widthb = min(abs(srcwidthb), abs(dstwidthb));
1011 /* FIXME: BI_BITFIELDS not supported yet */
1012 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb) {
1013 memcpy(dbits, sbits, widthb);
1014 }
1015 }
1016 break;
1017
1018 default: /* ? bit bmp -> 32 bit DIB */
1019 FIXME("32 bit DIB %d bit bitmap\n",
1020 bmp->bitmap.bmBitsPixel);
1021 break;
1022 }
1023 }
1024 break;
1025
1026 default: /* ? bit DIB */
1027 FIXME("Unsupported DIB depth %d\n", info->bmiHeader.biBitCount);
1028 break;
1029 }
1030 }
1031 /* Otherwise, get bits from the XImage */
1032 else
1033 {
1034 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pGetDIBits );
1035 if (!BITMAP_SetOwnerDC( hbitmap, physdev )) lines = 0;
1036 else lines = physdev->funcs->pGetDIBits( physdev, hbitmap, startscan,
1037 lines, bits, info, coloruse );
1038 }
1039 }
1040 else lines = abs(height);
1041
1042 /* The knowledge base article Q81498 ("DIBs and Their Uses") states that
1043 if bits == NULL and bpp != 0, only biSizeImage and the color table are
1044 filled in. */
1045 if (!core_header)
1046 {
1047 /* FIXME: biSizeImage should be calculated according to the selected
1048 compression algorithm if biCompression != BI_RGB */
1049 info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes( width, height, bpp );
1050 TRACE("biSizeImage = %d, ", info->bmiHeader.biSizeImage);
1051 }
1052 TRACE("biWidth = %d, biHeight = %d\n", width, height);
1053
1054 done:
1055 release_dc_ptr( dc );
1056 GDI_ReleaseObj( hbitmap );
1057 return lines;
1058 }
1059
1060
1061 /***********************************************************************
1062 * CreateDIBitmap (GDI32.@)
1063 *
1064 * Creates a DDB (device dependent bitmap) from a DIB.
1065 * The DDB will have the same color depth as the reference DC.
1066 */
1067 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
1068 DWORD init, LPCVOID bits, const BITMAPINFO *data,
1069 UINT coloruse )
1070 {
1071 HBITMAP handle;
1072 LONG width;
1073 LONG height;
1074 WORD planes, bpp;
1075 DWORD compr, size;
1076
1077 if (!header) return 0;
1078
1079 if (DIB_GetBitmapInfo( header, &width, &height, &planes, &bpp, &compr, &size ) == -1) return 0;
1080
1081 if (width < 0)
1082 {
1083 TRACE("Bitmap has a negative width\n");
1084 return 0;
1085 }
1086
1087 /* Top-down DIBs have a negative height */
1088 if (height < 0) height = -height;
1089
1090 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1091 hdc, header, init, bits, data, coloruse, width, height, bpp, compr);
1092
1093 if (hdc == NULL)
1094 handle = CreateBitmap( width, height, 1, 1, NULL );
1095 else
1096 handle = CreateCompatibleBitmap( hdc, width, height );
1097
1098 if (handle)
1099 {
1100 if (init & CBM_INIT)
1101 {
1102 if (SetDIBits( hdc, handle, 0, height, bits, data, coloruse ) == 0)
1103 {
1104 DeleteObject( handle );
1105 handle = 0;
1106 }
1107 }
1108 }
1109
1110 return handle;
1111 }
1112
1113 /* Copy/synthesize RGB palette from BITMAPINFO. Ripped from dlls/winex11.drv/dib.c */
1114 static void DIB_CopyColorTable( DC *dc, BITMAPOBJ *bmp, WORD coloruse, const BITMAPINFO *info )
1115 {
1116 RGBQUAD *colorTable;
1117 unsigned int colors, i;
1118 BOOL core_info = info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER);
1119
1120 if (core_info)
1121 {
1122 colors = 1 << ((const BITMAPCOREINFO*) info)->bmciHeader.bcBitCount;
1123 }
1124 else
1125 {
1126 colors = info->bmiHeader.biClrUsed;
1127 if (!colors) colors = 1 << info->bmiHeader.biBitCount;
1128 }
1129
1130 if (colors > 256) {
1131 ERR("called with >256 colors!\n");
1132 return;
1133 }
1134
1135 if (!(colorTable = HeapAlloc(GetProcessHeap(), 0, colors * sizeof(RGBQUAD) ))) return;
1136
1137 if(coloruse == DIB_RGB_COLORS)
1138 {
1139 if (core_info)
1140 {
1141 /* Convert RGBTRIPLEs to RGBQUADs */
1142 for (i=0; i < colors; i++)
1143 {
1144 colorTable[i].rgbRed = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtRed;
1145 colorTable[i].rgbGreen = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtGreen;
1146 colorTable[i].rgbBlue = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtBlue;
1147 colorTable[i].rgbReserved = 0;
1148 }
1149 }
1150 else
1151 {
1152 memcpy(colorTable, (const BYTE*) info + (WORD) info->bmiHeader.biSize, colors * sizeof(RGBQUAD));
1153 }
1154 }
1155 else
1156 {
1157 PALETTEENTRY entries[256];
1158 const WORD *index = (const WORD*) ((const BYTE*) info + (WORD) info->bmiHeader.biSize);
1159 UINT count = GetPaletteEntries( dc->hPalette, 0, colors, entries );
1160
1161 for (i = 0; i < colors; i++, index++)
1162 {
1163 PALETTEENTRY *entry = &entries[*index % count];
1164 colorTable[i].rgbRed = entry->peRed;
1165 colorTable[i].rgbGreen = entry->peGreen;
1166 colorTable[i].rgbBlue = entry->peBlue;
1167 colorTable[i].rgbReserved = 0;
1168 }
1169 }
1170 bmp->color_table = colorTable;
1171 bmp->nb_colors = colors;
1172 }
1173
1174 /***********************************************************************
1175 * CreateDIBSection (GDI32.@)
1176 */
1177 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
1178 VOID **bits, HANDLE section, DWORD offset)
1179 {
1180 HBITMAP ret = 0;
1181 DC *dc;
1182 BOOL bDesktopDC = FALSE;
1183 DIBSECTION *dib;
1184 BITMAPOBJ *bmp;
1185 int bitmap_type;
1186 LONG width, height;
1187 WORD planes, bpp;
1188 DWORD compression, sizeImage;
1189 void *mapBits = NULL;
1190
1191 if(!bmi){
1192 if(bits) *bits = NULL;
1193 return NULL;
1194 }
1195
1196 if (((bitmap_type = DIB_GetBitmapInfo( &bmi->bmiHeader, &width, &height,
1197 &planes, &bpp, &compression, &sizeImage )) == -1))
1198 return 0;
1199
1200 switch (bpp)
1201 {
1202 case 16:
1203 case 32:
1204 if (compression == BI_BITFIELDS) break;
1205 /* fall through */
1206 case 1:
1207 case 4:
1208 case 8:
1209 case 24:
1210 if (compression == BI_RGB) break;
1211 /* fall through */
1212 default:
1213 WARN( "invalid %u bpp compression %u\n", bpp, compression );
1214 return 0;
1215 }
1216
1217 if (!(dib = HeapAlloc( GetProcessHeap(), 0, sizeof(*dib) ))) return 0;
1218
1219 TRACE("format (%d,%d), planes %d, bpp %d, %s, size %d %s\n",
1220 width, height, planes, bpp, compression == BI_BITFIELDS? "BI_BITFIELDS" : "BI_RGB",
1221 sizeImage, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1222
1223 dib->dsBm.bmType = 0;
1224 dib->dsBm.bmWidth = width;
1225 dib->dsBm.bmHeight = height >= 0 ? height : -height;
1226 dib->dsBm.bmWidthBytes = DIB_GetDIBWidthBytes(width, bpp);
1227 dib->dsBm.bmPlanes = planes;
1228 dib->dsBm.bmBitsPixel = bpp;
1229 dib->dsBm.bmBits = NULL;
1230
1231 if (!bitmap_type) /* core header */
1232 {
1233 /* convert the BITMAPCOREHEADER to a BITMAPINFOHEADER */
1234 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1235 dib->dsBmih.biWidth = width;
1236 dib->dsBmih.biHeight = height;
1237 dib->dsBmih.biPlanes = planes;
1238 dib->dsBmih.biBitCount = bpp;
1239 dib->dsBmih.biCompression = compression;
1240 dib->dsBmih.biXPelsPerMeter = 0;
1241 dib->dsBmih.biYPelsPerMeter = 0;
1242 dib->dsBmih.biClrUsed = 0;
1243 dib->dsBmih.biClrImportant = 0;
1244 }
1245 else
1246 {
1247 /* truncate extended bitmap headers (BITMAPV4HEADER etc.) */
1248 dib->dsBmih = bmi->bmiHeader;
1249 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1250 }
1251
1252 /* set number of entries in bmi.bmiColors table */
1253 if( bpp <= 8 )
1254 dib->dsBmih.biClrUsed = 1 << bpp;
1255
1256 dib->dsBmih.biSizeImage = dib->dsBm.bmWidthBytes * dib->dsBm.bmHeight;
1257
1258 /* set dsBitfields values */
1259 dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
1260
1261 if((bpp == 15 || bpp == 16) && compression == BI_RGB)
1262 {
1263 /* In this case Windows changes biCompression to BI_BITFIELDS,
1264 however for now we won't do this, as there are a lot
1265 of places where BI_BITFIELDS is currently unsupported. */
1266
1267 /* dib->dsBmih.biCompression = compression = BI_BITFIELDS;*/
1268 dib->dsBitfields[0] = 0x7c00;
1269 dib->dsBitfields[1] = 0x03e0;
1270 dib->dsBitfields[2] = 0x001f;
1271 }
1272 else if(compression == BI_BITFIELDS)
1273 {
1274 dib->dsBitfields[0] = *(const DWORD *)bmi->bmiColors;
1275 dib->dsBitfields[1] = *((const DWORD *)bmi->bmiColors + 1);
1276 dib->dsBitfields[2] = *((const DWORD *)bmi->bmiColors + 2);
1277 }
1278
1279 /* get storage location for DIB bits */
1280
1281 if (section)
1282 {
1283 SYSTEM_INFO SystemInfo;
1284 DWORD mapOffset;
1285 INT mapSize;
1286
1287 GetSystemInfo( &SystemInfo );
1288 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
1289 mapSize = dib->dsBmih.biSizeImage + (offset - mapOffset);
1290 mapBits = MapViewOfFile( section, FILE_MAP_ALL_ACCESS, 0, mapOffset, mapSize );
1291 if (mapBits) dib->dsBm.bmBits = (char *)mapBits + (offset - mapOffset);
1292 }
1293 else
1294 {
1295 offset = 0;
1296 dib->dsBm.bmBits = VirtualAlloc( NULL, dib->dsBmih.biSizeImage,
1297 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
1298 }
1299 dib->dshSection = section;
1300 dib->dsOffset = offset;
1301
1302 if (!dib->dsBm.bmBits)
1303 {
1304 HeapFree( GetProcessHeap(), 0, dib );
1305 return 0;
1306 }
1307
1308 /* If the reference hdc is null, take the desktop dc */
1309 if (hdc == 0)
1310 {
1311 hdc = CreateCompatibleDC(0);
1312 bDesktopDC = TRUE;
1313 }
1314
1315 if (!(dc = get_dc_ptr( hdc ))) goto error;
1316
1317 /* create Device Dependent Bitmap and add DIB pointer */
1318 ret = CreateBitmap( dib->dsBm.bmWidth, dib->dsBm.bmHeight, 1,
1319 (bpp == 1) ? 1 : GetDeviceCaps(hdc, BITSPIXEL), NULL );
1320
1321 if (ret && ((bmp = GDI_GetObjPtr(ret, OBJ_BITMAP))))
1322 {
1323 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pCreateDIBSection );
1324 bmp->dib = dib;
1325 bmp->funcs = physdev->funcs;
1326 /* create local copy of DIB palette */
1327 if (bpp <= 8) DIB_CopyColorTable( dc, bmp, usage, bmi );
1328 GDI_ReleaseObj( ret );
1329
1330 if (!physdev->funcs->pCreateDIBSection( physdev, ret, bmi, usage ))
1331 {
1332 DeleteObject( ret );
1333 ret = 0;
1334 }
1335 }
1336
1337 release_dc_ptr( dc );
1338 if (bDesktopDC) DeleteDC( hdc );
1339 if (ret && bits) *bits = dib->dsBm.bmBits;
1340 return ret;
1341
1342 error:
1343 if (bDesktopDC) DeleteDC( hdc );
1344 if (section) UnmapViewOfFile( mapBits );
1345 else if (!offset) VirtualFree( dib->dsBm.bmBits, 0, MEM_RELEASE );
1346 HeapFree( GetProcessHeap(), 0, dib );
1347 return 0;
1348 }
1349
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.