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