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