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