Sync to trunk revision 63922.
[reactos.git] / win32ss / gdi / ntgdi / dibobj.c
1 /*
2 * PROJECT: ReactOS win32 kernel mode subsystem
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: subsystems/win32/win32k/objects/dibobj.c
5 * PURPOSE: Dib object functions
6 * PROGRAMMER:
7 */
8
9 #include <win32k.h>
10
11 #define NDEBUG
12 #include <debug.h>
13
14 static const RGBQUAD EGAColorsQuads[16] =
15 {
16 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
17 { 0x00, 0x00, 0x00, 0x00 },
18 { 0x00, 0x00, 0x80, 0x00 },
19 { 0x00, 0x80, 0x00, 0x00 },
20 { 0x00, 0x80, 0x80, 0x00 },
21 { 0x80, 0x00, 0x00, 0x00 },
22 { 0x80, 0x00, 0x80, 0x00 },
23 { 0x80, 0x80, 0x00, 0x00 },
24 { 0x80, 0x80, 0x80, 0x00 },
25 { 0xc0, 0xc0, 0xc0, 0x00 },
26 { 0x00, 0x00, 0xff, 0x00 },
27 { 0x00, 0xff, 0x00, 0x00 },
28 { 0x00, 0xff, 0xff, 0x00 },
29 { 0xff, 0x00, 0x00, 0x00 },
30 { 0xff, 0x00, 0xff, 0x00 },
31 { 0xff, 0xff, 0x00, 0x00 },
32 { 0xff, 0xff, 0xff, 0x00 }
33 };
34
35 static const RGBTRIPLE EGAColorsTriples[16] =
36 {
37 /* rgbBlue, rgbGreen, rgbRed */
38 { 0x00, 0x00, 0x00 },
39 { 0x00, 0x00, 0x80 },
40 { 0x00, 0x80, 0x00 },
41 { 0x00, 0x80, 0x80 },
42 { 0x80, 0x00, 0x00 },
43 { 0x80, 0x00, 0x80 },
44 { 0x80, 0x80, 0x00 },
45 { 0x80, 0x80, 0x80 },
46 { 0xc0, 0xc0, 0xc0 },
47 { 0x00, 0x00, 0xff },
48 { 0x00, 0xff, 0x00 },
49 { 0x00, 0xff, 0xff },
50 { 0xff, 0x00, 0x00 },
51 { 0xff, 0x00, 0xff },
52 { 0xff, 0xff, 0x00 },
53 { 0xff, 0xff, 0xff }
54 };
55
56 static const RGBQUAD DefLogPaletteQuads[20] = /* Copy of Default Logical Palette */
57 {
58 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
59 { 0x00, 0x00, 0x00, 0x00 },
60 { 0x00, 0x00, 0x80, 0x00 },
61 { 0x00, 0x80, 0x00, 0x00 },
62 { 0x00, 0x80, 0x80, 0x00 },
63 { 0x80, 0x00, 0x00, 0x00 },
64 { 0x80, 0x00, 0x80, 0x00 },
65 { 0x80, 0x80, 0x00, 0x00 },
66 { 0xc0, 0xc0, 0xc0, 0x00 },
67 { 0xc0, 0xdc, 0xc0, 0x00 },
68 { 0xf0, 0xca, 0xa6, 0x00 },
69 { 0xf0, 0xfb, 0xff, 0x00 },
70 { 0xa4, 0xa0, 0xa0, 0x00 },
71 { 0x80, 0x80, 0x80, 0x00 },
72 { 0x00, 0x00, 0xf0, 0x00 },
73 { 0x00, 0xff, 0x00, 0x00 },
74 { 0x00, 0xff, 0xff, 0x00 },
75 { 0xff, 0x00, 0x00, 0x00 },
76 { 0xff, 0x00, 0xff, 0x00 },
77 { 0xff, 0xff, 0x00, 0x00 },
78 { 0xff, 0xff, 0xff, 0x00 }
79 };
80
81 static const RGBQUAD DefLogPaletteTriples[20] = /* Copy of Default Logical Palette */
82 {
83 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
84 { 0x00, 0x00, 0x00 },
85 { 0x00, 0x00, 0x80 },
86 { 0x00, 0x80, 0x00 },
87 { 0x00, 0x80, 0x80 },
88 { 0x80, 0x00, 0x00 },
89 { 0x80, 0x00, 0x80 },
90 { 0x80, 0x80, 0x00 },
91 { 0xc0, 0xc0, 0xc0 },
92 { 0xc0, 0xdc, 0xc0 },
93 { 0xf0, 0xca, 0xa6 },
94 { 0xf0, 0xfb, 0xff },
95 { 0xa4, 0xa0, 0xa0 },
96 { 0x80, 0x80, 0x80 },
97 { 0x00, 0x00, 0xf0 },
98 { 0x00, 0xff, 0x00 },
99 { 0x00, 0xff, 0xff },
100 { 0xff, 0x00, 0x00 },
101 { 0xff, 0x00, 0xff },
102 { 0xff, 0xff, 0x00 },
103 { 0xff, 0xff, 0xff }
104 };
105
106 PPALETTE
107 NTAPI
108 CreateDIBPalette(
109 _In_ const BITMAPINFO *pbmi,
110 _In_ PDC pdc,
111 _In_ ULONG iUsage)
112 {
113 PPALETTE ppal;
114 ULONG i, cBitsPixel, cColors;
115
116 if (pbmi->bmiHeader.biSize < sizeof(BITMAPINFOHEADER))
117 {
118 PBITMAPCOREINFO pbci = (PBITMAPCOREINFO)pbmi;
119 cBitsPixel = pbci->bmciHeader.bcBitCount;
120 }
121 else
122 {
123 cBitsPixel = pbmi->bmiHeader.biBitCount;
124 }
125
126 /* Check if the colors are indexed */
127 if (cBitsPixel <= 8)
128 {
129 /* We create a "full" palette */
130 cColors = 1 << cBitsPixel;
131
132 /* Allocate the palette */
133 ppal = PALETTE_AllocPalette(PAL_INDEXED,
134 cColors,
135 NULL,
136 0,
137 0,
138 0);
139
140 /* Check if the BITMAPINFO specifies how many colors to use */
141 if ((pbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
142 (pbmi->bmiHeader.biClrUsed != 0))
143 {
144 /* This is how many colors we can actually process */
145 cColors = min(cColors, pbmi->bmiHeader.biClrUsed);
146 }
147
148 /* Check how to use the colors */
149 if (iUsage == DIB_PAL_COLORS)
150 {
151 COLORREF crColor;
152
153 /* The colors are an array of WORD indices into the DC palette */
154 PWORD pwColors = (PWORD)((PCHAR)pbmi + pbmi->bmiHeader.biSize);
155
156 /* Use the DCs palette or, if no DC is given, the default one */
157 PPALETTE ppalDC = pdc ? pdc->dclevel.ppal : gppalDefault;
158
159 /* Loop all color indices in the DIB */
160 for (i = 0; i < cColors; i++)
161 {
162 /* Get the palette index and handle wraparound when exceeding
163 the number of colors in the DC palette */
164 WORD wIndex = pwColors[i] % ppalDC->NumColors;
165
166 /* USe the RGB value from the DC palette */
167 crColor = PALETTE_ulGetRGBColorFromIndex(ppalDC, wIndex);
168 PALETTE_vSetRGBColorForIndex(ppal, i, crColor);
169 }
170 }
171 else if (iUsage == DIB_PAL_BRUSHHACK)
172 {
173 /* The colors are an array of WORD indices into the DC palette */
174 PWORD pwColors = (PWORD)((PCHAR)pbmi + pbmi->bmiHeader.biSize);
175
176 /* Loop all color indices in the DIB */
177 for (i = 0; i < cColors; i++)
178 {
179 /* Set the index directly as the RGB color, the real palette
180 containing RGB values will be calculated when the brush is
181 realized */
182 PALETTE_vSetRGBColorForIndex(ppal, i, pwColors[i]);
183 }
184
185 /* Mark the palette as a brush hack palette */
186 ppal->flFlags |= PAL_BRUSHHACK;
187 }
188 // else if (iUsage == 2)
189 // {
190 // FIXME: this one is undocumented
191 // ASSERT(FALSE);
192 // }
193 else if (pbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER))
194 {
195 /* The colors are an array of RGBQUAD values */
196 RGBQUAD *prgb = (RGBQUAD*)((PCHAR)pbmi + pbmi->bmiHeader.biSize);
197
198 // FIXME: do we need to handle PALETTEINDEX / PALETTERGB macro?
199
200 /* Loop all color indices in the DIB */
201 for (i = 0; i < cColors; i++)
202 {
203 /* Get the color value and translate it to a COLORREF */
204 RGBQUAD rgb = prgb[i];
205 COLORREF crColor = RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
206
207 /* Set the RGB value in the palette */
208 PALETTE_vSetRGBColorForIndex(ppal, i, crColor);
209 }
210 }
211 else
212 {
213 /* The colors are an array of RGBTRIPLE values */
214 RGBTRIPLE *prgb = (RGBTRIPLE*)((PCHAR)pbmi + pbmi->bmiHeader.biSize);
215
216 /* Loop all color indices in the DIB */
217 for (i = 0; i < cColors; i++)
218 {
219 /* Get the color value and translate it to a COLORREF */
220 RGBTRIPLE rgb = prgb[i];
221 COLORREF crColor = RGB(rgb.rgbtRed, rgb.rgbtGreen, rgb.rgbtBlue);
222
223 /* Set the RGB value in the palette */
224 PALETTE_vSetRGBColorForIndex(ppal, i, crColor);
225 }
226 }
227 }
228 else
229 {
230 /* This is a bitfield / RGB palette */
231 ULONG flRedMask, flGreenMask, flBlueMask;
232
233 /* Check if the DIB contains bitfield values */
234 if ((pbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
235 (pbmi->bmiHeader.biCompression == BI_BITFIELDS))
236 {
237 /* Check if we have a v4/v5 header */
238 if (pbmi->bmiHeader.biSize >= sizeof(BITMAPV4HEADER))
239 {
240 /* The masks are dedicated fields in the header */
241 PBITMAPV4HEADER pbmV4Header = (PBITMAPV4HEADER)&pbmi->bmiHeader;
242 flRedMask = pbmV4Header->bV4RedMask;
243 flGreenMask = pbmV4Header->bV4GreenMask;
244 flBlueMask = pbmV4Header->bV4BlueMask;
245 }
246 else
247 {
248 /* The masks are the first 3 values in the DIB color table */
249 PDWORD pdwColors = (PVOID)((PCHAR)pbmi + pbmi->bmiHeader.biSize);
250 flRedMask = pdwColors[0];
251 flGreenMask = pdwColors[1];
252 flBlueMask = pdwColors[2];
253 }
254 }
255 else
256 {
257 /* Check what bit depth we have. Note: optimization flags are
258 calculated in PALETTE_AllocPalette() */
259 if (cBitsPixel == 16)
260 {
261 /* This is an RGB 555 palette */
262 flRedMask = 0x7C00;
263 flGreenMask = 0x03E0;
264 flBlueMask = 0x001F;
265 }
266 else
267 {
268 /* This is an RGB 888 palette */
269 flRedMask = 0xFF0000;
270 flGreenMask = 0x00FF00;
271 flBlueMask = 0x0000FF;
272 }
273 }
274
275 /* Allocate the bitfield palette */
276 ppal = PALETTE_AllocPalette(PAL_BITFIELDS,
277 0,
278 NULL,
279 flRedMask,
280 flGreenMask,
281 flBlueMask);
282 }
283
284 /* We're done, return the palette */
285 return ppal;
286 }
287
288 // Converts a DIB to a device-dependent bitmap
289 static INT
290 FASTCALL
291 IntSetDIBits(
292 PDC DC,
293 HBITMAP hBitmap,
294 UINT StartScan,
295 UINT ScanLines,
296 CONST VOID *Bits,
297 CONST BITMAPINFO *bmi,
298 UINT ColorUse)
299 {
300 HBITMAP SourceBitmap;
301 PSURFACE psurfDst, psurfSrc;
302 INT result = 0;
303 RECT rcDst;
304 POINTL ptSrc;
305 EXLATEOBJ exlo;
306 PPALETTE ppalDIB = 0;
307
308 if (!bmi) return 0;
309
310 SourceBitmap = GreCreateBitmapEx(bmi->bmiHeader.biWidth,
311 ScanLines,
312 0,
313 BitmapFormat(bmi->bmiHeader.biBitCount,
314 bmi->bmiHeader.biCompression),
315 bmi->bmiHeader.biHeight < 0 ? BMF_TOPDOWN : 0,
316 bmi->bmiHeader.biSizeImage,
317 (PVOID)Bits,
318 0);
319 if (!SourceBitmap)
320 {
321 DPRINT1("Error: Could not create a bitmap.\n");
322 EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
323 return 0;
324 }
325
326 psurfDst = SURFACE_ShareLockSurface(hBitmap);
327 psurfSrc = SURFACE_ShareLockSurface(SourceBitmap);
328
329 if(!(psurfSrc && psurfDst))
330 {
331 DPRINT1("Error: Could not lock surfaces\n");
332 goto cleanup;
333 }
334
335 /* Create a palette for the DIB */
336 ppalDIB = CreateDIBPalette(bmi, DC, ColorUse);
337 if (!ppalDIB)
338 {
339 EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
340 goto cleanup;
341 }
342
343 /* Initialize EXLATEOBJ */
344 EXLATEOBJ_vInitialize(&exlo,
345 ppalDIB,
346 psurfDst->ppal,
347 RGB(0xff, 0xff, 0xff),
348 RGB(0xff, 0xff, 0xff), //DC->pdcattr->crBackgroundClr,
349 0); // DC->pdcattr->crForegroundClr);
350
351 rcDst.top = StartScan;
352 rcDst.left = 0;
353 rcDst.bottom = rcDst.top + ScanLines;
354 rcDst.right = psurfDst->SurfObj.sizlBitmap.cx;
355 ptSrc.x = 0;
356 ptSrc.y = 0;
357
358 result = IntEngCopyBits(&psurfDst->SurfObj,
359 &psurfSrc->SurfObj,
360 NULL,
361 &exlo.xlo,
362 &rcDst,
363 &ptSrc);
364 if(result)
365 result = ScanLines;
366
367 EXLATEOBJ_vCleanup(&exlo);
368
369 cleanup:
370 if (ppalDIB) PALETTE_ShareUnlockPalette(ppalDIB);
371 if(psurfSrc) SURFACE_ShareUnlockSurface(psurfSrc);
372 if(psurfDst) SURFACE_ShareUnlockSurface(psurfDst);
373 GreDeleteObject(SourceBitmap);
374
375 return result;
376 }
377
378 static
379 HBITMAP
380 IntGdiCreateMaskFromRLE(
381 DWORD Width,
382 DWORD Height,
383 ULONG Compression,
384 const BYTE* Bits,
385 DWORD BitsSize)
386 {
387 HBITMAP Mask;
388 DWORD x, y;
389 SURFOBJ* SurfObj;
390 UINT i = 0;
391 BYTE Data, NumPixels, ToSkip;
392
393 ASSERT((Compression == BI_RLE8) || (Compression == BI_RLE4));
394
395 /* Create the bitmap */
396 Mask = GreCreateBitmapEx(Width, Height, 0, BMF_1BPP, 0, 0, NULL, 0);
397 if (!Mask)
398 return NULL;
399
400 SurfObj = EngLockSurface((HSURF)Mask);
401 if (!SurfObj)
402 {
403 GreDeleteObject(Mask);
404 return NULL;
405 }
406 ASSERT(SurfObj->pvBits != NULL);
407
408 x = y = 0;
409
410 while (i < BitsSize)
411 {
412 NumPixels = Bits[i];
413 Data = Bits[i + 1];
414 i += 2;
415
416 if (NumPixels != 0)
417 {
418 if ((x + NumPixels) > Width)
419 NumPixels = Width - x;
420
421 if (NumPixels == 0)
422 continue;
423
424 DIB_1BPP_HLine(SurfObj, x, x + NumPixels, y, 1);
425 x += NumPixels;
426 continue;
427 }
428
429 if (Data < 3)
430 {
431 switch (Data)
432 {
433 case 0:
434 /* End of line */
435 y++;
436 if (y == Height)
437 goto done;
438 x = 0;
439 break;
440 case 1:
441 /* End of file */
442 goto done;
443 case 2:
444 /* Jump */
445 if (i >= (BitsSize - 1))
446 goto done;
447 x += Bits[i];
448 if (x > Width)
449 x = Width;
450 y += Bits[i + 1];
451 if (y >= Height)
452 goto done;
453 i += 2;
454 break;
455 }
456 /* Done for this run */
457 continue;
458 }
459
460 /* Embedded data into the RLE */
461 NumPixels = Data;
462 if (Compression == BI_RLE8)
463 ToSkip = NumPixels;
464 else
465 ToSkip = (NumPixels / 2) + (NumPixels & 1);
466
467 if ((i + ToSkip) > BitsSize)
468 goto done;
469 ToSkip = (ToSkip + 1) & ~1;
470
471 if ((x + NumPixels) > Width)
472 NumPixels = Width - x;
473
474 if (NumPixels != 0)
475 {
476 DIB_1BPP_HLine(SurfObj, x, x + NumPixels, y, 1);
477 x += NumPixels;
478 }
479 i += ToSkip;
480 }
481
482 done:
483 EngUnlockSurface(SurfObj);
484 return Mask;
485 }
486
487 W32KAPI
488 INT
489 APIENTRY
490 NtGdiSetDIBitsToDeviceInternal(
491 IN HDC hDC,
492 IN INT XDest,
493 IN INT YDest,
494 IN DWORD Width,
495 IN DWORD Height,
496 IN INT XSrc,
497 IN INT YSrc,
498 IN DWORD StartScan,
499 IN DWORD ScanLines,
500 IN LPBYTE Bits,
501 IN LPBITMAPINFO bmi,
502 IN DWORD ColorUse,
503 IN UINT cjMaxBits,
504 IN UINT cjMaxInfo,
505 IN BOOL bTransformCoordinates,
506 IN OPTIONAL HANDLE hcmXform)
507 {
508 INT ret = 0;
509 NTSTATUS Status = STATUS_SUCCESS;
510 PDC pDC;
511 HBITMAP hSourceBitmap = NULL, hMaskBitmap = NULL;
512 SURFOBJ *pDestSurf, *pSourceSurf = NULL, *pMaskSurf = NULL;
513 SURFACE *pSurf;
514 RECTL rcDest;
515 POINTL ptSource;
516 //INT DIBWidth;
517 SIZEL SourceSize;
518 EXLATEOBJ exlo;
519 PPALETTE ppalDIB = NULL;
520 LPBITMAPINFO pbmiSafe;
521
522 if (!Bits) return 0;
523
524 pbmiSafe = ExAllocatePoolWithTag(PagedPool, cjMaxInfo, 'pmTG');
525 if (!pbmiSafe) return 0;
526
527 _SEH2_TRY
528 {
529 ProbeForRead(bmi, cjMaxInfo, 1);
530 ProbeForRead(Bits, cjMaxBits, 1);
531 RtlCopyMemory(pbmiSafe, bmi, cjMaxInfo);
532 bmi = pbmiSafe;
533 }
534 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
535 {
536 Status = _SEH2_GetExceptionCode();
537 }
538 _SEH2_END
539
540 if (!NT_SUCCESS(Status))
541 {
542 goto Exit2;
543 }
544
545 ScanLines = min(ScanLines, abs(bmi->bmiHeader.biHeight) - StartScan);
546
547 pDC = DC_LockDc(hDC);
548 if (!pDC)
549 {
550 EngSetLastError(ERROR_INVALID_HANDLE);
551 goto Exit2;
552 }
553
554 if (pDC->dctype == DC_TYPE_INFO)
555 {
556 DC_UnlockDc(pDC);
557 goto Exit;
558 }
559
560 rcDest.left = XDest;
561 rcDest.top = YDest;
562 if (bTransformCoordinates)
563 {
564 IntLPtoDP(pDC, (LPPOINT)&rcDest, 2);
565 }
566 rcDest.left += pDC->ptlDCOrig.x;
567 rcDest.top += pDC->ptlDCOrig.y;
568 rcDest.right = rcDest.left + Width;
569 rcDest.bottom = rcDest.top + Height;
570 rcDest.top += StartScan;
571
572 ptSource.x = XSrc;
573 ptSource.y = YSrc;
574
575 SourceSize.cx = bmi->bmiHeader.biWidth;
576 SourceSize.cy = ScanLines;
577
578 //DIBWidth = WIDTH_BYTES_ALIGN32(SourceSize.cx, bmi->bmiHeader.biBitCount);
579
580 hSourceBitmap = GreCreateBitmapEx(bmi->bmiHeader.biWidth,
581 ScanLines,
582 0,
583 BitmapFormat(bmi->bmiHeader.biBitCount,
584 bmi->bmiHeader.biCompression),
585 bmi->bmiHeader.biHeight < 0 ? BMF_TOPDOWN : 0,
586 bmi->bmiHeader.biSizeImage,
587 Bits,
588 0);
589
590 if (!hSourceBitmap)
591 {
592 EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
593 Status = STATUS_NO_MEMORY;
594 goto Exit;
595 }
596
597 pSourceSurf = EngLockSurface((HSURF)hSourceBitmap);
598 if (!pSourceSurf)
599 {
600 Status = STATUS_UNSUCCESSFUL;
601 goto Exit;
602 }
603
604 /* HACK: If this is a RLE bitmap, only the relevant pixels must be set. */
605 if ((bmi->bmiHeader.biCompression == BI_RLE8) || (bmi->bmiHeader.biCompression == BI_RLE4))
606 {
607 hMaskBitmap = IntGdiCreateMaskFromRLE(bmi->bmiHeader.biWidth,
608 ScanLines,
609 bmi->bmiHeader.biCompression,
610 Bits,
611 cjMaxBits);
612 if (!hMaskBitmap)
613 {
614 EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
615 Status = STATUS_NO_MEMORY;
616 goto Exit;
617 }
618 pMaskSurf = EngLockSurface((HSURF)hMaskBitmap);
619 if (!pMaskSurf)
620 {
621 Status = STATUS_UNSUCCESSFUL;
622 goto Exit;
623 }
624 }
625
626 /* Create a palette for the DIB */
627 ppalDIB = CreateDIBPalette(bmi, pDC, ColorUse);
628 if (!ppalDIB)
629 {
630 EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
631 Status = STATUS_NO_MEMORY;
632 goto Exit;
633 }
634
635 /* This is actually a blit */
636 DC_vPrepareDCsForBlit(pDC, &rcDest, NULL, NULL);
637 pSurf = pDC->dclevel.pSurface;
638 if (!pSurf)
639 {
640 DC_vFinishBlit(pDC, NULL);
641 ret = ScanLines;
642 goto Exit;
643 }
644
645 ASSERT(pSurf->ppal);
646
647 /* Initialize EXLATEOBJ */
648 EXLATEOBJ_vInitialize(&exlo,
649 ppalDIB,
650 pSurf->ppal,
651 RGB(0xff, 0xff, 0xff),
652 pDC->pdcattr->crBackgroundClr,
653 pDC->pdcattr->crForegroundClr);
654
655 pDestSurf = &pSurf->SurfObj;
656
657 /* Copy the bits */
658 DPRINT("BitsToDev with dstsurf=(%d|%d) (%d|%d), src=(%d|%d) w=%d h=%d\n",
659 rcDest.left, rcDest.top, rcDest.right, rcDest.bottom,
660 ptSource.x, ptSource.y, SourceSize.cx, SourceSize.cy);
661 Status = IntEngBitBlt(pDestSurf,
662 pSourceSurf,
663 pMaskSurf,
664 &pDC->co.ClipObj,
665 &exlo.xlo,
666 &rcDest,
667 &ptSource,
668 pMaskSurf ? &ptSource : NULL,
669 NULL,
670 NULL,
671 pMaskSurf ? ROP4_MASK : ROP4_FROM_INDEX(R3_OPINDEX_SRCCOPY));
672
673 /* Cleanup EXLATEOBJ */
674 EXLATEOBJ_vCleanup(&exlo);
675
676 /* We're done */
677 DC_vFinishBlit(pDC, NULL);
678
679 Exit:
680 if (NT_SUCCESS(Status))
681 {
682 ret = ScanLines;
683 }
684
685 if (ppalDIB) PALETTE_ShareUnlockPalette(ppalDIB);
686
687 if (pSourceSurf) EngUnlockSurface(pSourceSurf);
688 if (hSourceBitmap) EngDeleteSurface((HSURF)hSourceBitmap);
689 if (pMaskSurf) EngUnlockSurface(pMaskSurf);
690 if (hMaskBitmap) EngDeleteSurface((HSURF)hMaskBitmap);
691 DC_UnlockDc(pDC);
692 Exit2:
693 ExFreePoolWithTag(pbmiSafe, 'pmTG');
694 return ret;
695 }
696
697
698 /* Converts a device-dependent bitmap to a DIB */
699 INT
700 APIENTRY
701 GreGetDIBitsInternal(
702 HDC hDC,
703 HBITMAP hBitmap,
704 UINT StartScan,
705 UINT ScanLines,
706 LPBYTE Bits,
707 LPBITMAPINFO Info,
708 UINT Usage,
709 UINT MaxBits,
710 UINT MaxInfo)
711 {
712 BITMAPCOREINFO* pbmci = NULL;
713 PSURFACE psurf = NULL;
714 PDC pDC;
715 LONG width, height;
716 WORD planes, bpp;
717 DWORD compr, size ;
718 USHORT i;
719 int bitmap_type;
720 RGBQUAD* rgbQuads;
721 VOID* colorPtr;
722
723 DPRINT("Entered NtGdiGetDIBitsInternal()\n");
724
725 if ((Usage && Usage != DIB_PAL_COLORS) || !Info || !hBitmap)
726 return 0;
727
728 colorPtr = (LPBYTE)Info + Info->bmiHeader.biSize;
729 rgbQuads = colorPtr;
730
731 bitmap_type = DIB_GetBitmapInfo(&Info->bmiHeader,
732 &width,
733 &height,
734 &planes,
735 &bpp,
736 &compr,
737 &size);
738 if(bitmap_type == -1)
739 {
740 DPRINT("Wrong bitmap format\n");
741 EngSetLastError(ERROR_INVALID_PARAMETER);
742 return 0;
743 }
744 else if(bitmap_type == 0)
745 {
746 /* We need a BITMAPINFO to create a DIB, but we have to fill
747 * the BITMAPCOREINFO we're provided */
748 pbmci = (BITMAPCOREINFO*)Info;
749 Info = DIB_ConvertBitmapInfo((BITMAPINFO*)pbmci, Usage);
750 if(Info == NULL)
751 {
752 DPRINT1("Error, could not convert the BITMAPCOREINFO!\n");
753 return 0;
754 }
755 rgbQuads = Info->bmiColors;
756 }
757
758 pDC = DC_LockDc(hDC);
759 if (pDC == NULL || pDC->dctype == DC_TYPE_INFO)
760 {
761 ScanLines = 0;
762 goto done;
763 }
764
765 /* Get a pointer to the source bitmap object */
766 psurf = SURFACE_ShareLockSurface(hBitmap);
767 if (psurf == NULL)
768 {
769 ScanLines = 0;
770 goto done;
771 }
772
773 /* Fill in the structure */
774 switch(bpp)
775 {
776 case 0: /* Only info */
777 Info->bmiHeader.biWidth = psurf->SurfObj.sizlBitmap.cx;
778 Info->bmiHeader.biHeight = (psurf->SurfObj.fjBitmap & BMF_TOPDOWN) ?
779 -psurf->SurfObj.sizlBitmap.cy :
780 psurf->SurfObj.sizlBitmap.cy;;
781 Info->bmiHeader.biPlanes = 1;
782 Info->bmiHeader.biBitCount = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
783 Info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes( Info->bmiHeader.biWidth,
784 Info->bmiHeader.biHeight,
785 Info->bmiHeader.biBitCount);
786 if(psurf->hSecure)
787 {
788 switch(Info->bmiHeader.biBitCount)
789 {
790 case 16:
791 case 32:
792 Info->bmiHeader.biCompression = BI_BITFIELDS;
793 break;
794 default:
795 Info->bmiHeader.biCompression = BI_RGB;
796 break;
797 }
798 }
799 else if(Info->bmiHeader.biBitCount > 8)
800 {
801 Info->bmiHeader.biCompression = BI_BITFIELDS;
802 }
803 else
804 {
805 Info->bmiHeader.biCompression = BI_RGB;
806 }
807 Info->bmiHeader.biXPelsPerMeter = 0;
808 Info->bmiHeader.biYPelsPerMeter = 0;
809 Info->bmiHeader.biClrUsed = 0;
810 Info->bmiHeader.biClrImportant = 0;
811 ScanLines = abs(Info->bmiHeader.biHeight);
812 goto done;
813
814 case 1:
815 case 4:
816 case 8:
817 Info->bmiHeader.biClrUsed = 0;
818
819 /* If the bitmap if a DIB section and has the same format than what
820 * we're asked, go ahead! */
821 if((psurf->hSecure) &&
822 (BitsPerFormat(psurf->SurfObj.iBitmapFormat) == bpp))
823 {
824 if(Usage == DIB_RGB_COLORS)
825 {
826 ULONG colors = min(psurf->ppal->NumColors, 256);
827 if(colors != 256) Info->bmiHeader.biClrUsed = colors;
828 for(i = 0; i < colors; i++)
829 {
830 rgbQuads[i].rgbRed = psurf->ppal->IndexedColors[i].peRed;
831 rgbQuads[i].rgbGreen = psurf->ppal->IndexedColors[i].peGreen;
832 rgbQuads[i].rgbBlue = psurf->ppal->IndexedColors[i].peBlue;
833 rgbQuads[i].rgbReserved = 0;
834 }
835 }
836 else
837 {
838 for(i = 0; i < 256; i++)
839 ((WORD*)rgbQuads)[i] = i;
840 }
841 }
842 else
843 {
844 if(Usage == DIB_PAL_COLORS)
845 {
846 for(i = 0; i < 256; i++)
847 {
848 ((WORD*)rgbQuads)[i] = i;
849 }
850 }
851 else if(bpp > 1 && bpp == BitsPerFormat(psurf->SurfObj.iBitmapFormat))
852 {
853 /* For color DDBs in native depth (mono DDBs always have
854 a black/white palette):
855 Generate the color map from the selected palette */
856 PPALETTE pDcPal = PALETTE_ShareLockPalette(pDC->dclevel.hpal);
857 if(!pDcPal)
858 {
859 ScanLines = 0 ;
860 goto done ;
861 }
862 for (i = 0; i < pDcPal->NumColors; i++)
863 {
864 rgbQuads[i].rgbRed = pDcPal->IndexedColors[i].peRed;
865 rgbQuads[i].rgbGreen = pDcPal->IndexedColors[i].peGreen;
866 rgbQuads[i].rgbBlue = pDcPal->IndexedColors[i].peBlue;
867 rgbQuads[i].rgbReserved = 0;
868 }
869 PALETTE_ShareUnlockPalette(pDcPal);
870 }
871 else
872 {
873 switch (bpp)
874 {
875 case 1:
876 rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen = rgbQuads[0].rgbBlue = 0;
877 rgbQuads[0].rgbReserved = 0;
878 rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen = rgbQuads[1].rgbBlue = 0xff;
879 rgbQuads[1].rgbReserved = 0;
880 break;
881
882 case 4:
883 RtlCopyMemory(rgbQuads, EGAColorsQuads, sizeof(EGAColorsQuads));
884 break;
885
886 case 8:
887 {
888 INT r, g, b;
889 RGBQUAD *color;
890 memcpy(rgbQuads, DefLogPaletteQuads,
891 10 * sizeof(RGBQUAD));
892 memcpy(rgbQuads + 246, DefLogPaletteQuads + 10,
893 10 * sizeof(RGBQUAD));
894 color = rgbQuads + 10;
895 for(r = 0; r <= 5; r++) /* FIXME */
896 {
897 for(g = 0; g <= 5; g++)
898 {
899 for(b = 0; b <= 5; b++)
900 {
901 color->rgbRed = (r * 0xff) / 5;
902 color->rgbGreen = (g * 0xff) / 5;
903 color->rgbBlue = (b * 0xff) / 5;
904 color->rgbReserved = 0;
905 color++;
906 }
907 }
908 }
909 }
910 }
911 }
912 }
913 break;
914
915 case 15:
916 if (Info->bmiHeader.biCompression == BI_BITFIELDS)
917 {
918 ((PDWORD)Info->bmiColors)[0] = 0x7c00;
919 ((PDWORD)Info->bmiColors)[1] = 0x03e0;
920 ((PDWORD)Info->bmiColors)[2] = 0x001f;
921 }
922 break;
923
924 case 16:
925 if (Info->bmiHeader.biCompression == BI_BITFIELDS)
926 {
927 if (psurf->hSecure)
928 {
929 ((PDWORD)Info->bmiColors)[0] = psurf->ppal->RedMask;
930 ((PDWORD)Info->bmiColors)[1] = psurf->ppal->GreenMask;
931 ((PDWORD)Info->bmiColors)[2] = psurf->ppal->BlueMask;
932 }
933 else
934 {
935 ((PDWORD)Info->bmiColors)[0] = 0xf800;
936 ((PDWORD)Info->bmiColors)[1] = 0x07e0;
937 ((PDWORD)Info->bmiColors)[2] = 0x001f;
938 }
939 }
940 break;
941
942 case 24:
943 case 32:
944 if (Info->bmiHeader.biCompression == BI_BITFIELDS)
945 {
946 if (psurf->hSecure)
947 {
948 ((PDWORD)Info->bmiColors)[0] = psurf->ppal->RedMask;
949 ((PDWORD)Info->bmiColors)[1] = psurf->ppal->GreenMask;
950 ((PDWORD)Info->bmiColors)[2] = psurf->ppal->BlueMask;
951 }
952 else
953 {
954 ((PDWORD)Info->bmiColors)[0] = 0xff0000;
955 ((PDWORD)Info->bmiColors)[1] = 0x00ff00;
956 ((PDWORD)Info->bmiColors)[2] = 0x0000ff;
957 }
958 }
959 break;
960 }
961 Info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(width, height, bpp);
962
963 if(Bits && ScanLines)
964 {
965 /* Create a DIBSECTION, blt it, profit */
966 PVOID pDIBits ;
967 HBITMAP hBmpDest;
968 PSURFACE psurfDest;
969 EXLATEOBJ exlo;
970 RECT rcDest;
971 POINTL srcPoint;
972 BOOL ret ;
973
974 if (StartScan > (ULONG)psurf->SurfObj.sizlBitmap.cy)
975 {
976 ScanLines = 0;
977 goto done;
978 }
979 else
980 {
981 ScanLines = min(ScanLines, psurf->SurfObj.sizlBitmap.cy - StartScan);
982 }
983
984 /* Fixup values */
985 Info->bmiHeader.biWidth = psurf->SurfObj.sizlBitmap.cx;
986 Info->bmiHeader.biHeight = (height < 0) ?
987 -(LONG)ScanLines : ScanLines;
988 /* Create the DIB */
989 hBmpDest = DIB_CreateDIBSection(pDC, Info, Usage, &pDIBits, NULL, 0, 0);
990 /* Restore them */
991 Info->bmiHeader.biWidth = width;
992 Info->bmiHeader.biHeight = height;
993
994 if(!hBmpDest)
995 {
996 DPRINT1("Unable to create a DIB Section!\n");
997 EngSetLastError(ERROR_INVALID_PARAMETER);
998 ScanLines = 0;
999 goto done ;
1000 }
1001
1002 psurfDest = SURFACE_ShareLockSurface(hBmpDest);
1003
1004 RECTL_vSetRect(&rcDest, 0, 0, psurf->SurfObj.sizlBitmap.cx, ScanLines);
1005
1006 srcPoint.x = 0;
1007
1008 if(height < 0)
1009 {
1010 srcPoint.y = 0;
1011
1012 if(ScanLines <= StartScan)
1013 {
1014 ScanLines = 1;
1015 SURFACE_ShareUnlockSurface(psurfDest);
1016 GreDeleteObject(hBmpDest);
1017 goto done;
1018 }
1019
1020 ScanLines -= StartScan;
1021 }
1022 else
1023 {
1024 srcPoint.y = StartScan;
1025 }
1026
1027 EXLATEOBJ_vInitialize(&exlo, psurf->ppal, psurfDest->ppal, 0xffffff, 0xffffff, 0);
1028
1029 ret = IntEngCopyBits(&psurfDest->SurfObj,
1030 &psurf->SurfObj,
1031 NULL,
1032 &exlo.xlo,
1033 &rcDest,
1034 &srcPoint);
1035
1036 SURFACE_ShareUnlockSurface(psurfDest);
1037
1038 if(!ret)
1039 ScanLines = 0;
1040 else
1041 {
1042 RtlCopyMemory(Bits, pDIBits, DIB_GetDIBImageBytes (width, ScanLines, bpp));
1043 }
1044
1045 GreDeleteObject(hBmpDest);
1046 EXLATEOBJ_vCleanup(&exlo);
1047 }
1048 else ScanLines = abs(height);
1049
1050 done:
1051
1052 if(pDC) DC_UnlockDc(pDC);
1053 if(psurf) SURFACE_ShareUnlockSurface(psurf);
1054 if(pbmci) DIB_FreeConvertedBitmapInfo(Info, (BITMAPINFO*)pbmci, Usage);
1055
1056 return ScanLines;
1057 }
1058
1059 INT
1060 APIENTRY
1061 NtGdiGetDIBitsInternal(
1062 _In_ HDC hdc,
1063 _In_ HBITMAP hbm,
1064 _In_ UINT iStartScan,
1065 _In_ UINT cScans,
1066 _Out_opt_ LPBYTE pjBits,
1067 _Inout_ LPBITMAPINFO pbmiUser,
1068 _In_ UINT iUsage,
1069 _In_ UINT cjMaxBits,
1070 _In_ UINT cjMaxInfo)
1071 {
1072 PBITMAPINFO pbmi;
1073 HANDLE hSecure = NULL;
1074 INT iResult = 0;
1075 UINT cjAlloc;
1076
1077 /* Check for bad iUsage */
1078 if (iUsage > 2) return 0;
1079
1080 /* Check if the size of the bitmap info is large enough */
1081 if (cjMaxInfo < sizeof(BITMAPCOREHEADER))
1082 {
1083 return 0;
1084 }
1085
1086 /* Use maximum size */
1087 cjMaxInfo = min(cjMaxInfo, sizeof(BITMAPV5HEADER) + 256 * sizeof(RGBQUAD));
1088
1089 // HACK: the underlying code sucks and doesn't care for the size, so we
1090 // give it the maximum ever needed
1091 cjAlloc = sizeof(BITMAPV5HEADER) + 256 * sizeof(RGBQUAD);
1092
1093 /* Allocate a buffer the bitmapinfo */
1094 pbmi = ExAllocatePoolWithTag(PagedPool, cjAlloc, 'imBG');
1095 if (!pbmi)
1096 {
1097 /* Fail */
1098 return 0;
1099 }
1100
1101 /* Use SEH */
1102 _SEH2_TRY
1103 {
1104 /* Probe and copy the BITMAPINFO */
1105 ProbeForRead(pbmiUser, cjMaxInfo, 1);
1106 RtlCopyMemory(pbmi, pbmiUser, cjMaxInfo);
1107 }
1108 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1109 {
1110 _SEH2_YIELD(goto cleanup;)
1111 }
1112 _SEH2_END;
1113
1114 /* Check if the header size is large enough */
1115 if ((pbmi->bmiHeader.biSize < sizeof(BITMAPCOREHEADER)) ||
1116 (pbmi->bmiHeader.biSize > cjMaxInfo))
1117 {
1118 goto cleanup;
1119 }
1120
1121 /* Check if the caller provided bitmap bits */
1122 if (pjBits)
1123 {
1124 /* Secure the user mode memory */
1125 hSecure = EngSecureMem(pjBits, cjMaxBits);
1126 if (!hSecure)
1127 {
1128 goto cleanup;
1129 }
1130 }
1131
1132 /* Now call the internal function */
1133 iResult = GreGetDIBitsInternal(hdc,
1134 hbm,
1135 iStartScan,
1136 cScans,
1137 pjBits,
1138 pbmi,
1139 iUsage,
1140 cjMaxBits,
1141 cjMaxInfo);
1142
1143 /* Check for success */
1144 if (iResult)
1145 {
1146 /* Use SEH to copy back to user mode */
1147 _SEH2_TRY
1148 {
1149 /* Copy the data back */
1150 ProbeForWrite(pbmiUser, cjMaxInfo, 1);
1151 RtlCopyMemory(pbmiUser, pbmi, cjMaxInfo);
1152 }
1153 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1154 {
1155 /* Ignore */
1156 }
1157 _SEH2_END;
1158 }
1159
1160 cleanup:
1161 if (hSecure) EngUnsecureMem(hSecure);
1162 ExFreePoolWithTag(pbmi, 'imBG');
1163
1164 return iResult;
1165 }
1166
1167
1168 #define ROP_TO_ROP4(Rop) ((Rop) >> 16)
1169
1170 W32KAPI
1171 INT
1172 APIENTRY
1173 NtGdiStretchDIBitsInternal(
1174 IN HDC hdc,
1175 IN INT xDst,
1176 IN INT yDst,
1177 IN INT cxDst,
1178 IN INT cyDst,
1179 IN INT xSrc,
1180 IN INT ySrc,
1181 IN INT cxSrc,
1182 IN INT cySrc,
1183 IN OPTIONAL LPBYTE pjInit,
1184 IN LPBITMAPINFO pbmi,
1185 IN DWORD dwUsage,
1186 IN DWORD dwRop, // MS ntgdi.h says dwRop4(?)
1187 IN UINT cjMaxInfo,
1188 IN UINT cjMaxBits,
1189 IN HANDLE hcmXform)
1190 {
1191 BOOL bResult = FALSE;
1192 SIZEL sizel;
1193 RECTL rcSrc, rcDst;
1194 PDC pdc;
1195 HBITMAP hbmTmp = 0;
1196 PSURFACE psurfTmp = 0, psurfDst = 0;
1197 PPALETTE ppalDIB = 0;
1198 EXLATEOBJ exlo;
1199 PVOID pvBits;
1200
1201 if (!(pdc = DC_LockDc(hdc)))
1202 {
1203 EngSetLastError(ERROR_INVALID_HANDLE);
1204 return 0;
1205 }
1206
1207 /* Check for info / mem DC without surface */
1208 if (!pdc->dclevel.pSurface)
1209 {
1210 DC_UnlockDc(pdc);
1211 // CHECKME
1212 return TRUE;
1213 }
1214
1215 /* Transform dest size */
1216 sizel.cx = cxDst;
1217 sizel.cy = cyDst;
1218 IntLPtoDP(pdc, (POINTL*)&sizel, 1);
1219 DC_UnlockDc(pdc);
1220
1221 /* Check if we can use NtGdiSetDIBitsToDeviceInternal */
1222 if (sizel.cx == cxSrc && sizel.cy == cySrc && dwRop == SRCCOPY)
1223 {
1224 /* Yes, we can! */
1225 return NtGdiSetDIBitsToDeviceInternal(hdc,
1226 xDst,
1227 yDst,
1228 cxDst,
1229 cyDst,
1230 xSrc,
1231 ySrc,
1232 0,
1233 cySrc,
1234 pjInit,
1235 pbmi,
1236 dwUsage,
1237 cjMaxBits,
1238 cjMaxInfo,
1239 TRUE,
1240 hcmXform);
1241 }
1242
1243 if (pjInit && (cjMaxBits > 0))
1244 {
1245 pvBits = ExAllocatePoolWithTag(PagedPool, cjMaxBits, 'pmeT');
1246 if (!pvBits)
1247 {
1248 return 0;
1249 }
1250
1251 _SEH2_TRY
1252 {
1253 ProbeForRead(pjInit, cjMaxBits, 1);
1254 RtlCopyMemory(pvBits, pjInit, cjMaxBits);
1255 }
1256 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1257 {
1258 ExFreePoolWithTag(pvBits, 'pmeT');
1259 _SEH2_YIELD(return 0);
1260 }
1261 _SEH2_END
1262 }
1263 else
1264 {
1265 pvBits = NULL;
1266 }
1267
1268 /* FIXME: Locking twice is cheesy, coord tranlation in UM will fix it */
1269 if (!(pdc = DC_LockDc(hdc)))
1270 {
1271 DPRINT1("Could not lock dc\n");
1272 EngSetLastError(ERROR_INVALID_HANDLE);
1273 goto cleanup;
1274 }
1275
1276 /* Calculate source and destination rect */
1277 rcSrc.left = xSrc;
1278 rcSrc.top = ySrc;
1279 rcSrc.right = xSrc + abs(cxSrc);
1280 rcSrc.bottom = ySrc + abs(cySrc);
1281 rcDst.left = xDst;
1282 rcDst.top = yDst;
1283 rcDst.right = rcDst.left + cxDst;
1284 rcDst.bottom = rcDst.top + cyDst;
1285 IntLPtoDP(pdc, (POINTL*)&rcDst, 2);
1286 RECTL_vOffsetRect(&rcDst, pdc->ptlDCOrig.x, pdc->ptlDCOrig.y);
1287
1288 hbmTmp = GreCreateBitmapEx(pbmi->bmiHeader.biWidth,
1289 pbmi->bmiHeader.biHeight,
1290 0,
1291 BitmapFormat(pbmi->bmiHeader.biBitCount,
1292 pbmi->bmiHeader.biCompression),
1293 pbmi->bmiHeader.biHeight < 0 ? BMF_TOPDOWN : 0,
1294 pbmi->bmiHeader.biSizeImage,
1295 pvBits,
1296 0);
1297
1298 if (!hbmTmp)
1299 {
1300 bResult = FALSE;
1301 goto cleanup;
1302 }
1303
1304 psurfTmp = SURFACE_ShareLockSurface(hbmTmp);
1305 if (!psurfTmp)
1306 {
1307 bResult = FALSE;
1308 goto cleanup;
1309 }
1310
1311 /* Create a palette for the DIB */
1312 ppalDIB = CreateDIBPalette(pbmi, pdc, dwUsage);
1313 if (!ppalDIB)
1314 {
1315 bResult = FALSE;
1316 goto cleanup;
1317 }
1318
1319 /* Prepare DC for blit */
1320 DC_vPrepareDCsForBlit(pdc, &rcDst, NULL, NULL);
1321
1322 psurfDst = pdc->dclevel.pSurface;
1323
1324 /* Initialize XLATEOBJ */
1325 EXLATEOBJ_vInitialize(&exlo,
1326 ppalDIB,
1327 psurfDst->ppal,
1328 RGB(0xff, 0xff, 0xff),
1329 pdc->pdcattr->crBackgroundClr,
1330 pdc->pdcattr->crForegroundClr);
1331
1332 /* Perform the stretch operation */
1333 bResult = IntEngStretchBlt(&psurfDst->SurfObj,
1334 &psurfTmp->SurfObj,
1335 NULL,
1336 &pdc->co.ClipObj,
1337 &exlo.xlo,
1338 &pdc->dclevel.ca,
1339 &rcDst,
1340 &rcSrc,
1341 NULL,
1342 &pdc->eboFill.BrushObject,
1343 NULL,
1344 ROP_TO_ROP4(dwRop));
1345
1346 /* Cleanup */
1347 DC_vFinishBlit(pdc, NULL);
1348 EXLATEOBJ_vCleanup(&exlo);
1349 cleanup:
1350 if (ppalDIB) PALETTE_ShareUnlockPalette(ppalDIB);
1351 if (psurfTmp) SURFACE_ShareUnlockSurface(psurfTmp);
1352 if (hbmTmp) GreDeleteObject(hbmTmp);
1353 if (pdc) DC_UnlockDc(pdc);
1354 if (pvBits) ExFreePoolWithTag(pvBits, 'pmeT');
1355
1356 return bResult;
1357 }
1358
1359
1360 HBITMAP
1361 FASTCALL
1362 IntCreateDIBitmap(
1363 PDC Dc,
1364 INT width,
1365 INT height,
1366 UINT bpp,
1367 DWORD init,
1368 LPBYTE bits,
1369 PBITMAPINFO data,
1370 DWORD coloruse)
1371 {
1372 HBITMAP handle;
1373 BOOL fColor;
1374
1375 // Check if we should create a monochrome or color bitmap. We create a monochrome bitmap only if it has exactly 2
1376 // colors, which are black followed by white, nothing else. In all other cases, we create a color bitmap.
1377
1378 if (bpp != 1) fColor = TRUE;
1379 else if ((coloruse != DIB_RGB_COLORS) || (init != CBM_INIT) || !data) fColor = FALSE;
1380 else
1381 {
1382 const RGBQUAD *rgb = (RGBQUAD*)((PBYTE)data + data->bmiHeader.biSize);
1383 DWORD col = RGB(rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue);
1384
1385 // Check if the first color of the colormap is black
1386 if ((col == RGB(0, 0, 0)))
1387 {
1388 rgb++;
1389 col = RGB(rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue);
1390
1391 // If the second color is white, create a monochrome bitmap
1392 fColor = (col != RGB(0xff,0xff,0xff));
1393 }
1394 else fColor = TRUE;
1395 }
1396
1397 // Now create the bitmap
1398 if (fColor)
1399 {
1400 handle = IntCreateCompatibleBitmap(Dc, width, height);
1401 }
1402 else
1403 {
1404 handle = GreCreateBitmap(width,
1405 height,
1406 1,
1407 1,
1408 NULL);
1409 }
1410
1411 if (height < 0)
1412 height = -height;
1413
1414 if (NULL != handle && CBM_INIT == init)
1415 {
1416 IntSetDIBits(Dc, handle, 0, height, bits, data, coloruse);
1417 }
1418
1419 return handle;
1420 }
1421
1422 // The CreateDIBitmap function creates a device-dependent bitmap (DDB) from a DIB and, optionally, sets the bitmap bits
1423 // The DDB that is created will be whatever bit depth your reference DC is
1424 HBITMAP
1425 APIENTRY
1426 NtGdiCreateDIBitmapInternal(
1427 IN HDC hDc,
1428 IN INT cx,
1429 IN INT cy,
1430 IN DWORD fInit,
1431 IN OPTIONAL LPBYTE pjInit,
1432 IN OPTIONAL LPBITMAPINFO pbmi,
1433 IN DWORD iUsage,
1434 IN UINT cjMaxInitInfo,
1435 IN UINT cjMaxBits,
1436 IN FLONG fl,
1437 IN HANDLE hcmXform)
1438 {
1439 NTSTATUS Status = STATUS_SUCCESS;
1440 PBYTE safeBits = NULL;
1441 HBITMAP hbmResult = NULL;
1442
1443 if(pjInit && (fInit == CBM_INIT))
1444 {
1445 if (cjMaxBits == 0) return NULL;
1446 safeBits = ExAllocatePoolWithTag(PagedPool, cjMaxBits, TAG_DIB);
1447 if(!safeBits)
1448 {
1449 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
1450 return NULL;
1451 }
1452 }
1453
1454 _SEH2_TRY
1455 {
1456 if(pbmi) ProbeForRead(pbmi, cjMaxInitInfo, 1);
1457 if(pjInit && (fInit == CBM_INIT))
1458 {
1459 ProbeForRead(pjInit, cjMaxBits, 1);
1460 RtlCopyMemory(safeBits, pjInit, cjMaxBits);
1461 }
1462 }
1463 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1464 {
1465 Status = _SEH2_GetExceptionCode();
1466 }
1467 _SEH2_END
1468
1469 if(!NT_SUCCESS(Status))
1470 {
1471 SetLastNtError(Status);
1472 goto cleanup;
1473 }
1474
1475 hbmResult = GreCreateDIBitmapInternal(hDc,
1476 cx,
1477 cy,
1478 fInit,
1479 safeBits,
1480 pbmi,
1481 iUsage,
1482 fl,
1483 cjMaxBits,
1484 hcmXform);
1485
1486 cleanup:
1487 if (safeBits) ExFreePoolWithTag(safeBits, TAG_DIB);
1488 return hbmResult;
1489 }
1490
1491 HBITMAP
1492 NTAPI
1493 GreCreateDIBitmapInternal(
1494 IN HDC hDc,
1495 IN INT cx,
1496 IN INT cy,
1497 IN DWORD fInit,
1498 IN OPTIONAL LPBYTE pjInit,
1499 IN OPTIONAL PBITMAPINFO pbmi,
1500 IN DWORD iUsage,
1501 IN FLONG fl,
1502 IN UINT cjMaxBits,
1503 IN HANDLE hcmXform)
1504 {
1505 PDC Dc;
1506 HBITMAP Bmp;
1507 WORD bpp;
1508 HDC hdcDest;
1509
1510 if (!hDc) /* 1bpp monochrome bitmap */
1511 {
1512 // Should use System Bitmap DC hSystemBM, with CreateCompatibleDC for this.
1513 hdcDest = NtGdiCreateCompatibleDC(0);
1514 if(!hdcDest)
1515 {
1516 return NULL;
1517 }
1518 }
1519 else
1520 {
1521 hdcDest = hDc;
1522 }
1523
1524 Dc = DC_LockDc(hdcDest);
1525 if (!Dc)
1526 {
1527 EngSetLastError(ERROR_INVALID_HANDLE);
1528 return NULL;
1529 }
1530 /* It's OK to set bpp=0 here, as IntCreateDIBitmap will create a compatible Bitmap
1531 * if bpp != 1 and ignore the real value that was passed */
1532 if (pbmi)
1533 bpp = pbmi->bmiHeader.biBitCount;
1534 else
1535 bpp = 0;
1536 Bmp = IntCreateDIBitmap(Dc, cx, cy, bpp, fInit, pjInit, pbmi, iUsage);
1537 DC_UnlockDc(Dc);
1538
1539 if(!hDc)
1540 {
1541 NtGdiDeleteObjectApp(hdcDest);
1542 }
1543 return Bmp;
1544 }
1545
1546
1547 HBITMAP
1548 APIENTRY
1549 NtGdiCreateDIBSection(
1550 IN HDC hDC,
1551 IN OPTIONAL HANDLE hSection,
1552 IN DWORD dwOffset,
1553 IN BITMAPINFO* bmi,
1554 IN DWORD Usage,
1555 IN UINT cjHeader,
1556 IN FLONG fl,
1557 IN ULONG_PTR dwColorSpace,
1558 OUT PVOID *Bits)
1559 {
1560 HBITMAP hbitmap = 0;
1561 DC *dc;
1562 BOOL bDesktopDC = FALSE;
1563 NTSTATUS Status = STATUS_SUCCESS;
1564
1565 if (!bmi) return hbitmap; // Make sure.
1566
1567 _SEH2_TRY
1568 {
1569 ProbeForRead(&bmi->bmiHeader.biSize, sizeof(DWORD), 1);
1570 ProbeForRead(bmi, bmi->bmiHeader.biSize, 1);
1571 ProbeForRead(bmi, DIB_BitmapInfoSize(bmi, (WORD)Usage), 1);
1572 }
1573 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1574 {
1575 Status = _SEH2_GetExceptionCode();
1576 }
1577 _SEH2_END
1578
1579 if(!NT_SUCCESS(Status))
1580 {
1581 SetLastNtError(Status);
1582 return NULL;
1583 }
1584
1585 // If the reference hdc is null, take the desktop dc
1586 if (hDC == 0)
1587 {
1588 hDC = NtGdiCreateCompatibleDC(0);
1589 bDesktopDC = TRUE;
1590 }
1591
1592 if ((dc = DC_LockDc(hDC)))
1593 {
1594 hbitmap = DIB_CreateDIBSection(dc,
1595 bmi,
1596 Usage,
1597 Bits,
1598 hSection,
1599 dwOffset,
1600 0);
1601 DC_UnlockDc(dc);
1602 }
1603 else
1604 {
1605 EngSetLastError(ERROR_INVALID_HANDLE);
1606 }
1607
1608 if (bDesktopDC)
1609 NtGdiDeleteObjectApp(hDC);
1610
1611 return hbitmap;
1612 }
1613
1614 HBITMAP
1615 APIENTRY
1616 DIB_CreateDIBSection(
1617 PDC dc,
1618 CONST BITMAPINFO *bmi,
1619 UINT usage,
1620 LPVOID *bits,
1621 HANDLE section,
1622 DWORD offset,
1623 DWORD ovr_pitch)
1624 {
1625 HBITMAP res = 0;
1626 SURFACE *bmp = NULL;
1627 void *mapBits = NULL;
1628 PPALETTE ppalDIB = NULL;
1629
1630 // Fill BITMAP32 structure with DIB data
1631 CONST BITMAPINFOHEADER *bi = &bmi->bmiHeader;
1632 INT effHeight;
1633 ULONG totalSize;
1634 BITMAP bm;
1635 //SIZEL Size;
1636 HANDLE hSecure;
1637
1638 DPRINT("format (%ld,%ld), planes %u, bpp %u, size %lu, colors %lu (%s)\n",
1639 bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
1640 bi->biSizeImage, bi->biClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1641
1642 /* CreateDIBSection should fail for compressed formats */
1643 if (bi->biCompression == BI_RLE4 || bi->biCompression == BI_RLE8)
1644 {
1645 DPRINT1("no compressed format allowed\n");
1646 return (HBITMAP)NULL;
1647 }
1648
1649 effHeight = bi->biHeight >= 0 ? bi->biHeight : -bi->biHeight;
1650 bm.bmType = 0;
1651 bm.bmWidth = bi->biWidth;
1652 bm.bmHeight = effHeight;
1653 bm.bmWidthBytes = ovr_pitch ? ovr_pitch : WIDTH_BYTES_ALIGN32(bm.bmWidth, bi->biBitCount);
1654
1655 bm.bmPlanes = bi->biPlanes;
1656 bm.bmBitsPixel = bi->biBitCount;
1657 bm.bmBits = NULL;
1658
1659 // Get storage location for DIB bits. Only use biSizeImage if it's valid and
1660 // we're dealing with a compressed bitmap. Otherwise, use width * height.
1661 totalSize = bi->biSizeImage && bi->biCompression != BI_RGB && bi->biCompression != BI_BITFIELDS
1662 ? bi->biSizeImage : (ULONG)(bm.bmWidthBytes * effHeight);
1663
1664 if (section)
1665 {
1666 SYSTEM_BASIC_INFORMATION Sbi;
1667 NTSTATUS Status;
1668 DWORD mapOffset;
1669 LARGE_INTEGER SectionOffset;
1670 SIZE_T mapSize;
1671
1672 Status = ZwQuerySystemInformation(SystemBasicInformation,
1673 &Sbi,
1674 sizeof Sbi,
1675 0);
1676 if (!NT_SUCCESS(Status))
1677 {
1678 DPRINT1("ZwQuerySystemInformation failed (0x%lx)\n", Status);
1679 return NULL;
1680 }
1681
1682 mapOffset = offset - (offset % Sbi.AllocationGranularity);
1683 mapSize = bi->biSizeImage + (offset - mapOffset);
1684
1685 SectionOffset.LowPart = mapOffset;
1686 SectionOffset.HighPart = 0;
1687
1688 Status = ZwMapViewOfSection(section,
1689 NtCurrentProcess(),
1690 &mapBits,
1691 0,
1692 0,
1693 &SectionOffset,
1694 &mapSize,
1695 ViewShare,
1696 0,
1697 PAGE_READWRITE);
1698 if (!NT_SUCCESS(Status))
1699 {
1700 DPRINT1("ZwMapViewOfSection failed (0x%lx)\n", Status);
1701 EngSetLastError(ERROR_INVALID_PARAMETER);
1702 return NULL;
1703 }
1704
1705 if (mapBits) bm.bmBits = (char *)mapBits + (offset - mapOffset);
1706 }
1707 else if (ovr_pitch && offset)
1708 bm.bmBits = (LPVOID) offset;
1709 else
1710 {
1711 offset = 0;
1712 bm.bmBits = EngAllocUserMem(totalSize, 0);
1713 if(!bm.bmBits)
1714 {
1715 DPRINT1("Failed to allocate memory\n");
1716 goto cleanup;
1717 }
1718 }
1719
1720 // hSecure = MmSecureVirtualMemory(bm.bmBits, totalSize, PAGE_READWRITE);
1721 hSecure = (HANDLE)0x1; // HACK OF UNIMPLEMENTED KERNEL STUFF !!!!
1722
1723
1724 // Create Device Dependent Bitmap and add DIB pointer
1725 //Size.cx = bm.bmWidth;
1726 //Size.cy = abs(bm.bmHeight);
1727 res = GreCreateBitmapEx(bm.bmWidth,
1728 abs(bm.bmHeight),
1729 bm.bmWidthBytes,
1730 BitmapFormat(bi->biBitCount * bi->biPlanes, bi->biCompression),
1731 BMF_DONTCACHE | BMF_USERMEM | BMF_NOZEROINIT |
1732 ((bi->biHeight < 0) ? BMF_TOPDOWN : 0),
1733 bi->biSizeImage,
1734 bm.bmBits,
1735 0);
1736 if (!res)
1737 {
1738 DPRINT1("GreCreateBitmapEx failed\n");
1739 EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
1740 goto cleanup;
1741 }
1742 bmp = SURFACE_ShareLockSurface(res); // HACK
1743 if (NULL == bmp)
1744 {
1745 DPRINT1("SURFACE_LockSurface failed\n");
1746 EngSetLastError(ERROR_INVALID_HANDLE);
1747 goto cleanup;
1748 }
1749
1750 /* WINE NOTE: WINE makes use of a colormap, which is a color translation
1751 table between the DIB and the X physical device. Obviously,
1752 this is left out of the ReactOS implementation. Instead,
1753 we call NtGdiSetDIBColorTable. */
1754 bmp->hDIBSection = section;
1755 bmp->hSecure = hSecure;
1756 bmp->dwOffset = offset;
1757 bmp->flags = API_BITMAP;
1758 bmp->biClrImportant = bi->biClrImportant;
1759
1760 /* Create a palette for the DIB */
1761 ppalDIB = CreateDIBPalette(bmi, dc, usage);
1762
1763 // Clean up in case of errors
1764 cleanup:
1765 if (!res || !bmp || !bm.bmBits || !ppalDIB)
1766 {
1767 DPRINT("Got an error res=%p, bmp=%p, bm.bmBits=%p\n", res, bmp, bm.bmBits);
1768 if (bm.bmBits)
1769 {
1770 // MmUnsecureVirtualMemory(hSecure); // FIXME: Implement this!
1771 if (section)
1772 {
1773 ZwUnmapViewOfSection(NtCurrentProcess(), mapBits);
1774 bm.bmBits = NULL;
1775 }
1776 else if (!offset)
1777 EngFreeUserMem(bm.bmBits), bm.bmBits = NULL;
1778 }
1779
1780 if (bmp)
1781 {
1782 SURFACE_ShareUnlockSurface(bmp);
1783 bmp = NULL;
1784 }
1785
1786 if (res)
1787 {
1788 GreDeleteObject(res);
1789 res = 0;
1790 }
1791
1792 if(ppalDIB)
1793 {
1794 PALETTE_ShareUnlockPalette(ppalDIB);
1795 }
1796 }
1797
1798 if (bmp)
1799 {
1800 /* If we're here, everything went fine */
1801 SURFACE_vSetPalette(bmp, ppalDIB);
1802 PALETTE_ShareUnlockPalette(ppalDIB);
1803 SURFACE_ShareUnlockSurface(bmp);
1804 }
1805
1806 // Return BITMAP handle and storage location
1807 if (NULL != bm.bmBits && NULL != bits)
1808 {
1809 *bits = bm.bmBits;
1810 }
1811
1812 return res;
1813 }
1814
1815 /***********************************************************************
1816 * DIB_GetBitmapInfo
1817 *
1818 * Get the info from a bitmap header.
1819 * Return 0 for COREHEADER, 1 for INFOHEADER, -1 for error.
1820 */
1821 int
1822 FASTCALL
1823 DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
1824 LONG *height, WORD *planes, WORD *bpp, DWORD *compr, DWORD *size )
1825 {
1826 if (header->biSize == sizeof(BITMAPCOREHEADER))
1827 {
1828 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)header;
1829 *width = core->bcWidth;
1830 *height = core->bcHeight;
1831 *planes = core->bcPlanes;
1832 *bpp = core->bcBitCount;
1833 *compr = BI_RGB;
1834 *size = 0;
1835 return 0;
1836 }
1837 if (header->biSize >= sizeof(BITMAPINFOHEADER)) /* Assume BITMAPINFOHEADER */
1838 {
1839 *width = header->biWidth;
1840 *height = header->biHeight;
1841 *planes = header->biPlanes;
1842 *bpp = header->biBitCount;
1843 *compr = header->biCompression;
1844 *size = header->biSizeImage;
1845 return 1;
1846 }
1847 DPRINT1("(%u): unknown/wrong size for header\n", header->biSize );
1848 return -1;
1849 }
1850
1851 /***********************************************************************
1852 * DIB_GetDIBImageBytes
1853 *
1854 * Return the number of bytes used to hold the image in a DIB bitmap.
1855 * 11/16/1999 (RJJ) lifted from wine
1856 */
1857
1858 INT APIENTRY DIB_GetDIBImageBytes(INT width, INT height, INT depth)
1859 {
1860 return WIDTH_BYTES_ALIGN32(width, depth) * (height < 0 ? -height : height);
1861 }
1862
1863 /***********************************************************************
1864 * DIB_BitmapInfoSize
1865 *
1866 * Return the size of the bitmap info structure including color table.
1867 * 11/16/1999 (RJJ) lifted from wine
1868 */
1869
1870 INT FASTCALL DIB_BitmapInfoSize(const BITMAPINFO * info, WORD coloruse)
1871 {
1872 unsigned int colors, size, masks = 0;
1873
1874 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
1875 {
1876 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
1877 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
1878 return sizeof(BITMAPCOREHEADER) + colors *
1879 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
1880 }
1881 else /* Assume BITMAPINFOHEADER */
1882 {
1883 colors = info->bmiHeader.biClrUsed;
1884 if (colors > 256) colors = 256;
1885 if (!colors && (info->bmiHeader.biBitCount <= 8))
1886 colors = 1 << info->bmiHeader.biBitCount;
1887 if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3;
1888 size = max( info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD) );
1889 return size + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
1890 }
1891 }
1892
1893 HPALETTE
1894 FASTCALL
1895 DIB_MapPaletteColors(PPALETTE ppalDc, CONST BITMAPINFO* lpbmi)
1896 {
1897 PPALETTE ppalNew;
1898 ULONG nNumColors,i;
1899 USHORT *lpIndex;
1900 HPALETTE hpal;
1901
1902 if (!(ppalDc->flFlags & PAL_INDEXED))
1903 {
1904 return NULL;
1905 }
1906
1907 nNumColors = 1 << lpbmi->bmiHeader.biBitCount;
1908 if (lpbmi->bmiHeader.biClrUsed)
1909 {
1910 nNumColors = min(nNumColors, lpbmi->bmiHeader.biClrUsed);
1911 }
1912
1913 ppalNew = PALETTE_AllocPalWithHandle(PAL_INDEXED, nNumColors, NULL, 0, 0, 0);
1914 if (ppalNew == NULL)
1915 {
1916 DPRINT1("Could not allocate palette\n");
1917 return NULL;
1918 }
1919
1920 lpIndex = (USHORT *)((PBYTE)lpbmi + lpbmi->bmiHeader.biSize);
1921
1922 for (i = 0; i < nNumColors; i++)
1923 {
1924 ULONG iColorIndex = *lpIndex % ppalDc->NumColors;
1925 ppalNew->IndexedColors[i] = ppalDc->IndexedColors[iColorIndex];
1926 lpIndex++;
1927 }
1928
1929 hpal = ppalNew->BaseObject.hHmgr;
1930 PALETTE_UnlockPalette(ppalNew);
1931
1932 return hpal;
1933 }
1934
1935 /* Converts a BITMAPCOREINFO to a BITMAPINFO structure,
1936 * or does nothing if it's already a BITMAPINFO (or V4 or V5) */
1937 BITMAPINFO*
1938 FASTCALL
1939 DIB_ConvertBitmapInfo (CONST BITMAPINFO* pbmi, DWORD Usage)
1940 {
1941 CONST BITMAPCOREINFO* pbmci = (BITMAPCOREINFO*)pbmi;
1942 BITMAPINFO* pNewBmi ;
1943 UINT numColors = 0, ColorsSize = 0;
1944
1945 if(pbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) return (BITMAPINFO*)pbmi;
1946 if(pbmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) return NULL;
1947
1948 if(pbmci->bmciHeader.bcBitCount <= 8)
1949 {
1950 numColors = 1 << pbmci->bmciHeader.bcBitCount;
1951 if(Usage == DIB_PAL_COLORS)
1952 {
1953 ColorsSize = numColors * sizeof(WORD);
1954 }
1955 else
1956 {
1957 ColorsSize = numColors * sizeof(RGBQUAD);
1958 }
1959 }
1960 else if (Usage == DIB_PAL_COLORS)
1961 {
1962 /* Invalid at high-res */
1963 return NULL;
1964 }
1965
1966 pNewBmi = ExAllocatePoolWithTag(PagedPool, sizeof(BITMAPINFOHEADER) + ColorsSize, TAG_DIB);
1967 if(!pNewBmi) return NULL;
1968
1969 RtlZeroMemory(pNewBmi, sizeof(BITMAPINFOHEADER) + ColorsSize);
1970
1971 pNewBmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1972 pNewBmi->bmiHeader.biBitCount = pbmci->bmciHeader.bcBitCount;
1973 pNewBmi->bmiHeader.biWidth = pbmci->bmciHeader.bcWidth;
1974 pNewBmi->bmiHeader.biHeight = pbmci->bmciHeader.bcHeight;
1975 pNewBmi->bmiHeader.biPlanes = pbmci->bmciHeader.bcPlanes;
1976 pNewBmi->bmiHeader.biCompression = BI_RGB ;
1977 pNewBmi->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(pNewBmi->bmiHeader.biWidth,
1978 pNewBmi->bmiHeader.biHeight,
1979 pNewBmi->bmiHeader.biBitCount);
1980
1981 if(Usage == DIB_PAL_COLORS)
1982 {
1983 RtlCopyMemory(pNewBmi->bmiColors, pbmci->bmciColors, ColorsSize);
1984 }
1985 else
1986 {
1987 UINT i;
1988 for(i=0; i<numColors; i++)
1989 {
1990 pNewBmi->bmiColors[i].rgbRed = pbmci->bmciColors[i].rgbtRed;
1991 pNewBmi->bmiColors[i].rgbGreen = pbmci->bmciColors[i].rgbtGreen;
1992 pNewBmi->bmiColors[i].rgbBlue = pbmci->bmciColors[i].rgbtBlue;
1993 }
1994 }
1995
1996 return pNewBmi ;
1997 }
1998
1999 /* Frees a BITMAPINFO created with DIB_ConvertBitmapInfo */
2000 VOID
2001 FASTCALL
2002 DIB_FreeConvertedBitmapInfo(BITMAPINFO* converted, BITMAPINFO* orig, DWORD usage)
2003 {
2004 BITMAPCOREINFO* pbmci;
2005 if(converted == orig)
2006 return;
2007
2008 if(usage == -1)
2009 {
2010 /* Caller don't want any conversion */
2011 ExFreePoolWithTag(converted, TAG_DIB);
2012 return;
2013 }
2014
2015 /* Perform inverse conversion */
2016 pbmci = (BITMAPCOREINFO*)orig;
2017
2018 ASSERT(pbmci->bmciHeader.bcSize == sizeof(BITMAPCOREHEADER));
2019 pbmci->bmciHeader.bcBitCount = converted->bmiHeader.biBitCount;
2020 pbmci->bmciHeader.bcWidth = converted->bmiHeader.biWidth;
2021 pbmci->bmciHeader.bcHeight = converted->bmiHeader.biHeight;
2022 pbmci->bmciHeader.bcPlanes = converted->bmiHeader.biPlanes;
2023
2024 if(pbmci->bmciHeader.bcBitCount <= 8)
2025 {
2026 UINT numColors = converted->bmiHeader.biClrUsed;
2027 if(!numColors) numColors = 1 << pbmci->bmciHeader.bcBitCount;
2028 if(usage == DIB_PAL_COLORS)
2029 {
2030 RtlZeroMemory(pbmci->bmciColors, (1 << pbmci->bmciHeader.bcBitCount) * sizeof(WORD));
2031 RtlCopyMemory(pbmci->bmciColors, converted->bmiColors, numColors * sizeof(WORD));
2032 }
2033 else
2034 {
2035 UINT i;
2036 RtlZeroMemory(pbmci->bmciColors, (1 << pbmci->bmciHeader.bcBitCount) * sizeof(RGBTRIPLE));
2037 for(i=0; i<numColors; i++)
2038 {
2039 pbmci->bmciColors[i].rgbtRed = converted->bmiColors[i].rgbRed;
2040 pbmci->bmciColors[i].rgbtGreen = converted->bmiColors[i].rgbGreen;
2041 pbmci->bmciColors[i].rgbtBlue = converted->bmiColors[i].rgbBlue;
2042 }
2043 }
2044 }
2045 /* Now free it, it's not needed anymore */
2046 ExFreePoolWithTag(converted, TAG_DIB);
2047 }
2048
2049 /* EOF */