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