4b1ce44d7dda31f30c2c0c7668a4c5609d775e18
[reactos.git] / subsystems / win32 / win32k / objects / dibobj.c
1 /*
2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include <win32k.h>
21
22 #define NDEBUG
23 #include <debug.h>
24
25 static const RGBQUAD EGAColorsQuads[16] = {
26 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
27 { 0x00, 0x00, 0x00, 0x00 },
28 { 0x00, 0x00, 0x80, 0x00 },
29 { 0x00, 0x80, 0x00, 0x00 },
30 { 0x00, 0x80, 0x80, 0x00 },
31 { 0x80, 0x00, 0x00, 0x00 },
32 { 0x80, 0x00, 0x80, 0x00 },
33 { 0x80, 0x80, 0x00, 0x00 },
34 { 0x80, 0x80, 0x80, 0x00 },
35 { 0xc0, 0xc0, 0xc0, 0x00 },
36 { 0x00, 0x00, 0xff, 0x00 },
37 { 0x00, 0xff, 0x00, 0x00 },
38 { 0x00, 0xff, 0xff, 0x00 },
39 { 0xff, 0x00, 0x00, 0x00 },
40 { 0xff, 0x00, 0xff, 0x00 },
41 { 0xff, 0xff, 0x00, 0x00 },
42 { 0xff, 0xff, 0xff, 0x00 }
43 };
44
45 static const RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
46 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
47 { 0x00, 0x00, 0x00, 0x00 },
48 { 0x00, 0x00, 0x80, 0x00 },
49 { 0x00, 0x80, 0x00, 0x00 },
50 { 0x00, 0x80, 0x80, 0x00 },
51 { 0x80, 0x00, 0x00, 0x00 },
52 { 0x80, 0x00, 0x80, 0x00 },
53 { 0x80, 0x80, 0x00, 0x00 },
54 { 0xc0, 0xc0, 0xc0, 0x00 },
55 { 0xc0, 0xdc, 0xc0, 0x00 },
56 { 0xf0, 0xca, 0xa6, 0x00 },
57 { 0xf0, 0xfb, 0xff, 0x00 },
58 { 0xa4, 0xa0, 0xa0, 0x00 },
59 { 0x80, 0x80, 0x80, 0x00 },
60 { 0x00, 0x00, 0xf0, 0x00 },
61 { 0x00, 0xff, 0x00, 0x00 },
62 { 0x00, 0xff, 0xff, 0x00 },
63 { 0xff, 0x00, 0x00, 0x00 },
64 { 0xff, 0x00, 0xff, 0x00 },
65 { 0xff, 0xff, 0x00, 0x00 },
66 { 0xff, 0xff, 0xff, 0x00 }
67 };
68
69
70 UINT
71 APIENTRY
72 IntSetDIBColorTable(
73 HDC hDC,
74 UINT StartIndex,
75 UINT Entries,
76 CONST RGBQUAD *Colors)
77 {
78 PDC dc;
79 PSURFACE psurf;
80 PPALETTE PalGDI;
81 UINT Index;
82 ULONG biBitCount;
83
84 if (!(dc = DC_LockDc(hDC))) return 0;
85 if (dc->dctype == DC_TYPE_INFO)
86 {
87 DC_UnlockDc(dc);
88 return 0;
89 }
90
91 psurf = dc->dclevel.pSurface;
92 if (psurf == NULL)
93 {
94 DC_UnlockDc(dc);
95 SetLastWin32Error(ERROR_INVALID_PARAMETER);
96 return 0;
97 }
98
99 if (psurf->hSecure == NULL)
100 {
101 DC_UnlockDc(dc);
102 SetLastWin32Error(ERROR_INVALID_PARAMETER);
103 return 0;
104 }
105
106 biBitCount = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
107 if (biBitCount <= 8 && StartIndex < (1 << biBitCount))
108 {
109 if (StartIndex + Entries > (1 << biBitCount))
110 Entries = (1 << biBitCount) - StartIndex;
111
112 if (psurf->ppal == NULL)
113 {
114 DC_UnlockDc(dc);
115 SetLastWin32Error(ERROR_INVALID_HANDLE);
116 return 0;
117 }
118
119 PalGDI = PALETTE_LockPalette(psurf->ppal->BaseObject.hHmgr);
120
121 for (Index = StartIndex;
122 Index < StartIndex + Entries && Index < PalGDI->NumColors;
123 Index++)
124 {
125 PalGDI->IndexedColors[Index].peRed = Colors[Index - StartIndex].rgbRed;
126 PalGDI->IndexedColors[Index].peGreen = Colors[Index - StartIndex].rgbGreen;
127 PalGDI->IndexedColors[Index].peBlue = Colors[Index - StartIndex].rgbBlue;
128 }
129 PALETTE_UnlockPalette(PalGDI);
130 }
131 else
132 Entries = 0;
133
134 /* Mark the brushes invalid */
135 dc->pdcattr->ulDirty_ |= DIRTY_FILL|DIRTY_LINE|DIRTY_BACKGROUND|DIRTY_TEXT;
136
137 DC_UnlockDc(dc);
138
139 return Entries;
140 }
141
142 UINT
143 APIENTRY
144 IntGetDIBColorTable(
145 HDC hDC,
146 UINT StartIndex,
147 UINT Entries,
148 RGBQUAD *Colors)
149 {
150 PDC dc;
151 PSURFACE psurf;
152 PPALETTE PalGDI;
153 UINT Index, Count = 0;
154 ULONG biBitCount;
155
156 if (!(dc = DC_LockDc(hDC))) return 0;
157 if (dc->dctype == DC_TYPE_INFO)
158 {
159 DC_UnlockDc(dc);
160 return 0;
161 }
162
163 psurf = dc->dclevel.pSurface;
164 if (psurf == NULL)
165 {
166 DC_UnlockDc(dc);
167 SetLastWin32Error(ERROR_INVALID_PARAMETER);
168 return 0;
169 }
170
171 if (psurf->hSecure == NULL)
172 {
173 DC_UnlockDc(dc);
174 SetLastWin32Error(ERROR_INVALID_PARAMETER);
175 return 0;
176 }
177
178 biBitCount = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
179 if (biBitCount <= 8 &&
180 StartIndex < (1 << biBitCount))
181 {
182 if (StartIndex + Entries > (1 << biBitCount))
183 Entries = (1 << biBitCount) - StartIndex;
184
185 if (psurf->ppal == NULL)
186 {
187 DC_UnlockDc(dc);
188 SetLastWin32Error(ERROR_INVALID_HANDLE);
189 return 0;
190 }
191
192 PalGDI = PALETTE_LockPalette(psurf->ppal->BaseObject.hHmgr);
193
194 for (Index = StartIndex;
195 Index < StartIndex + Entries && Index < PalGDI->NumColors;
196 Index++)
197 {
198 Colors[Index - StartIndex].rgbRed = PalGDI->IndexedColors[Index].peRed;
199 Colors[Index - StartIndex].rgbGreen = PalGDI->IndexedColors[Index].peGreen;
200 Colors[Index - StartIndex].rgbBlue = PalGDI->IndexedColors[Index].peBlue;
201 Colors[Index - StartIndex].rgbReserved = 0;
202 Count++;
203 }
204 PALETTE_UnlockPalette(PalGDI);
205 }
206
207 DC_UnlockDc(dc);
208
209 return Count;
210 }
211
212 // Converts a DIB to a device-dependent bitmap
213 static INT
214 FASTCALL
215 IntSetDIBits(
216 PDC DC,
217 HBITMAP hBitmap,
218 UINT StartScan,
219 UINT ScanLines,
220 CONST VOID *Bits,
221 CONST BITMAPV5INFO *bmi,
222 UINT ColorUse)
223 {
224 SURFACE *bitmap;
225 HBITMAP SourceBitmap;
226 INT result = 0;
227 BOOL copyBitsResult;
228 SURFOBJ *DestSurf, *SourceSurf;
229 SIZEL SourceSize;
230 POINTL ZeroPoint;
231 RECTL DestRect;
232 EXLATEOBJ exlo;
233 PPALETTE ppalDIB;
234 //RGBQUAD *lpRGB;
235 HPALETTE DIB_Palette;
236 ULONG DIB_Palette_Type;
237 INT DIBWidth;
238
239 // Check parameters
240 if (!(bitmap = SURFACE_LockSurface(hBitmap)))
241 {
242 return 0;
243 }
244
245 // Get RGB values
246 //if (ColorUse == DIB_PAL_COLORS)
247 // lpRGB = DIB_MapPaletteColors(hDC, bmi);
248 //else
249 // lpRGB = &bmi->bmiColors;
250
251 DestSurf = &bitmap->SurfObj;
252
253 // Create source surface
254 SourceSize.cx = bmi->bmiHeader.bV5Width;
255 SourceSize.cy = ScanLines;
256
257 // Determine width of DIB
258 DIBWidth = DIB_GetDIBWidthBytes(SourceSize.cx, bmi->bmiHeader.bV5BitCount);
259
260 SourceBitmap = EngCreateBitmap(SourceSize,
261 DIBWidth,
262 BitmapFormat(bmi->bmiHeader.bV5BitCount, bmi->bmiHeader.bV5Compression),
263 bmi->bmiHeader.bV5Height < 0 ? BMF_TOPDOWN : 0,
264 (PVOID) Bits);
265 if (0 == SourceBitmap)
266 {
267 SURFACE_UnlockSurface(bitmap);
268 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
269 return 0;
270 }
271
272 SourceSurf = EngLockSurface((HSURF)SourceBitmap);
273 if (NULL == SourceSurf)
274 {
275 EngDeleteSurface((HSURF)SourceBitmap);
276 SURFACE_UnlockSurface(bitmap);
277 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
278 return 0;
279 }
280
281 ASSERT(bitmap->ppal);
282
283 // Source palette obtained from the BITMAPINFO
284 DIB_Palette = BuildDIBPalette((BITMAPINFO*)bmi, (PINT)&DIB_Palette_Type);
285 if (NULL == DIB_Palette)
286 {
287 EngUnlockSurface(SourceSurf);
288 EngDeleteSurface((HSURF)SourceBitmap);
289 SURFACE_UnlockSurface(bitmap);
290 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
291 return 0;
292 }
293
294 ppalDIB = PALETTE_LockPalette(DIB_Palette);
295
296 /* Initialize XLATEOBJ for color translation */
297 EXLATEOBJ_vInitialize(&exlo, ppalDIB, bitmap->ppal, 0, 0, 0);
298
299 // Zero point
300 ZeroPoint.x = 0;
301 ZeroPoint.y = 0;
302
303 // Determine destination rectangle
304 DestRect.left = 0;
305 DestRect.top = abs(bmi->bmiHeader.bV5Height) - StartScan - ScanLines;
306 DestRect.right = SourceSize.cx;
307 DestRect.bottom = DestRect.top + ScanLines;
308
309 copyBitsResult = IntEngCopyBits(DestSurf, SourceSurf, NULL, &exlo.xlo, &DestRect, &ZeroPoint);
310
311 // If it succeeded, return number of scanlines copies
312 if (copyBitsResult == TRUE)
313 {
314 result = SourceSize.cy;
315 // or
316 // result = abs(bmi->bmiHeader.biHeight) - StartScan;
317 }
318
319 // Clean up
320 EXLATEOBJ_vCleanup(&exlo);
321 PALETTE_UnlockPalette(ppalDIB);
322 PALETTE_FreePaletteByHandle(DIB_Palette);
323 EngUnlockSurface(SourceSurf);
324 EngDeleteSurface((HSURF)SourceBitmap);
325
326 // if (ColorUse == DIB_PAL_COLORS)
327 // WinFree((LPSTR)lpRGB);
328
329 SURFACE_UnlockSurface(bitmap);
330
331 return result;
332 }
333
334 // FIXME by Removing NtGdiSetDIBits!!!
335 // This is a victim of the Win32k Initialization BUG!!!!!
336 // Converts a DIB to a device-dependent bitmap
337 INT
338 APIENTRY
339 NtGdiSetDIBits(
340 HDC hDC,
341 HBITMAP hBitmap,
342 UINT StartScan,
343 UINT ScanLines,
344 CONST VOID *Bits,
345 CONST BITMAPINFO *bmi,
346 UINT ColorUse)
347 {
348 PDC Dc;
349 INT Ret;
350 NTSTATUS Status = STATUS_SUCCESS;
351 BITMAPV5INFO bmiLocal;
352
353 if (!Bits) return 0;
354
355 _SEH2_TRY
356 {
357 Status = ProbeAndConvertToBitmapV5Info(&bmiLocal, bmi, ColorUse, 0);
358 ProbeForRead(Bits, bmiLocal.bmiHeader.bV5SizeImage, 1);
359 }
360 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
361 {
362 Status = _SEH2_GetExceptionCode();
363 }
364 _SEH2_END
365
366 if (!NT_SUCCESS(Status))
367 {
368 return 0;
369 }
370
371 Dc = DC_LockDc(hDC);
372 if (NULL == Dc)
373 {
374 SetLastWin32Error(ERROR_INVALID_HANDLE);
375 return 0;
376 }
377 if (Dc->dctype == DC_TYPE_INFO)
378 {
379 DC_UnlockDc(Dc);
380 return 0;
381 }
382
383 Ret = IntSetDIBits(Dc, hBitmap, StartScan, ScanLines, Bits, &bmiLocal, ColorUse);
384
385 DC_UnlockDc(Dc);
386
387 return Ret;
388 }
389
390 W32KAPI
391 INT
392 APIENTRY
393 NtGdiSetDIBitsToDeviceInternal(
394 IN HDC hDC,
395 IN INT XDest,
396 IN INT YDest,
397 IN DWORD Width,
398 IN DWORD Height,
399 IN INT XSrc,
400 IN INT YSrc,
401 IN DWORD StartScan,
402 IN DWORD ScanLines,
403 IN LPBYTE Bits,
404 IN LPBITMAPINFO bmi,
405 IN DWORD ColorUse,
406 IN UINT cjMaxBits,
407 IN UINT cjMaxInfo,
408 IN BOOL bTransformCoordinates,
409 IN OPTIONAL HANDLE hcmXform)
410 {
411 INT ret = 0;
412 NTSTATUS Status = STATUS_SUCCESS;
413 PDC pDC;
414 HBITMAP hSourceBitmap = NULL;
415 SURFOBJ *pDestSurf, *pSourceSurf = NULL;
416 SURFACE *pSurf;
417 RECTL rcDest;
418 POINTL ptSource;
419 INT DIBWidth;
420 SIZEL SourceSize;
421 EXLATEOBJ exlo;
422 PPALETTE ppalDIB = NULL;
423 HPALETTE hpalDIB = NULL;
424 ULONG DIBPaletteType;
425 BITMAPV5INFO bmiLocal ;
426
427 if (!Bits) return 0;
428
429 _SEH2_TRY
430 {
431 Status = ProbeAndConvertToBitmapV5Info(&bmiLocal, bmi, ColorUse, cjMaxInfo);
432 ProbeForRead(Bits, cjMaxBits, 1);
433 }
434 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
435 {
436 Status = _SEH2_GetExceptionCode();
437 }
438 _SEH2_END
439
440 if (!NT_SUCCESS(Status))
441 {
442 return 0;
443 }
444
445 pDC = DC_LockDc(hDC);
446 if (!pDC)
447 {
448 SetLastWin32Error(ERROR_INVALID_HANDLE);
449 return 0;
450 }
451 if (pDC->dctype == DC_TYPE_INFO)
452 {
453 DC_UnlockDc(pDC);
454 return 0;
455 }
456
457 pSurf = pDC->dclevel.pSurface;
458
459 pDestSurf = pSurf ? &pSurf->SurfObj : NULL;
460
461 ScanLines = min(ScanLines, abs(bmiLocal.bmiHeader.bV5Height) - StartScan);
462
463 rcDest.left = XDest;
464 rcDest.top = YDest;
465 if (bTransformCoordinates)
466 {
467 CoordLPtoDP(pDC, (LPPOINT)&rcDest);
468 }
469 rcDest.left += pDC->ptlDCOrig.x;
470 rcDest.top += pDC->ptlDCOrig.y;
471 rcDest.right = rcDest.left + Width;
472 rcDest.bottom = rcDest.top + Height;
473 rcDest.top += StartScan;
474
475 ptSource.x = XSrc;
476 ptSource.y = YSrc;
477
478 SourceSize.cx = bmiLocal.bmiHeader.bV5Width;
479 SourceSize.cy = ScanLines;
480
481 DIBWidth = DIB_GetDIBWidthBytes(SourceSize.cx, bmiLocal.bmiHeader.bV5BitCount);
482
483 hSourceBitmap = EngCreateBitmap(SourceSize,
484 DIBWidth,
485 BitmapFormat(bmiLocal.bmiHeader.bV5BitCount,
486 bmiLocal.bmiHeader.bV5Compression),
487 bmiLocal.bmiHeader.bV5Height < 0 ? BMF_TOPDOWN : 0,
488 (PVOID) Bits);
489 if (!hSourceBitmap)
490 {
491 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
492 Status = STATUS_NO_MEMORY;
493 goto Exit;
494 }
495
496 pSourceSurf = EngLockSurface((HSURF)hSourceBitmap);
497 if (!pSourceSurf)
498 {
499 Status = STATUS_UNSUCCESSFUL;
500 goto Exit;
501 }
502
503 ASSERT(pSurf->ppal);
504
505 /* Create a palette for the DIB */
506 hpalDIB = BuildDIBPalette((PBITMAPINFO)&bmiLocal, (PINT)&DIBPaletteType);
507 if (!hpalDIB)
508 {
509 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
510 Status = STATUS_NO_MEMORY;
511 goto Exit;
512 }
513
514 /* Lock the DIB palette */
515 ppalDIB = PALETTE_LockPalette(hpalDIB);
516 if (!ppalDIB)
517 {
518 SetLastWin32Error(ERROR_INVALID_HANDLE);
519 Status = STATUS_UNSUCCESSFUL;
520 goto Exit;
521 }
522
523 /* Initialize EXLATEOBJ */
524 EXLATEOBJ_vInitialize(&exlo, ppalDIB, pSurf->ppal, 0, 0, 0);
525
526 /* Copy the bits */
527 DPRINT("BitsToDev with dstsurf=(%d|%d) (%d|%d), src=(%d|%d) w=%d h=%d\n",
528 rcDest.left, rcDest.top, rcDest.right, rcDest.bottom,
529 ptSource.x, ptSource.y, SourceSize.cx, SourceSize.cy);
530 Status = IntEngBitBlt(pDestSurf,
531 pSourceSurf,
532 NULL,
533 pDC->rosdc.CombinedClip,
534 &exlo.xlo,
535 &rcDest,
536 &ptSource,
537 NULL,
538 NULL,
539 NULL,
540 ROP3_TO_ROP4(SRCCOPY));
541
542 /* Cleanup EXLATEOBJ */
543 EXLATEOBJ_vCleanup(&exlo);
544
545 Exit:
546 if (NT_SUCCESS(Status))
547 {
548 ret = ScanLines;
549 }
550
551 if (ppalDIB) PALETTE_UnlockPalette(ppalDIB);
552
553 if (pSourceSurf) EngUnlockSurface(pSourceSurf);
554 if (hSourceBitmap) EngDeleteSurface((HSURF)hSourceBitmap);
555 if (hpalDIB) PALETTE_FreePaletteByHandle(hpalDIB);
556 DC_UnlockDc(pDC);
557
558 return ret;
559 }
560
561
562 /* Converts a device-dependent bitmap to a DIB */
563 INT
564 APIENTRY
565 NtGdiGetDIBitsInternal(
566 HDC hDC,
567 HBITMAP hBitmap,
568 UINT StartScan,
569 UINT ScanLines,
570 LPBYTE Bits,
571 LPBITMAPINFO Info,
572 UINT Usage,
573 UINT MaxBits,
574 UINT MaxInfo)
575 {
576 PDC Dc;
577 SURFACE *psurf = NULL;
578 HBITMAP hDestBitmap = NULL;
579 HPALETTE hDestPalette = NULL;
580 BITMAPV5INFO bmiLocal ;
581 PPALETTE ppalDst = NULL;
582 NTSTATUS Status = STATUS_SUCCESS;
583 ULONG Result = 0;
584 BOOL bPaletteMatch = FALSE;
585 PBYTE ChkBits = Bits;
586 ULONG DestPaletteType;
587 ULONG Index;
588
589 DPRINT("Entered NtGdiGetDIBitsInternal()\n");
590
591 if ((Usage && Usage != DIB_PAL_COLORS) || !Info || !hBitmap)
592 return 0;
593
594 // if ScanLines == 0, no need to copy Bits.
595 if (!ScanLines)
596 ChkBits = NULL;
597
598 _SEH2_TRY
599 {
600 Status = ProbeAndConvertToBitmapV5Info(&bmiLocal, Info, Usage, MaxInfo);
601 if (ChkBits) ProbeForWrite(ChkBits, MaxBits, 1);
602 }
603 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
604 {
605 Status = _SEH2_GetExceptionCode();
606 }
607 _SEH2_END
608
609 if (!NT_SUCCESS(Status))
610 {
611 return 0;
612 }
613
614 Dc = DC_LockDc(hDC);
615 if (Dc == NULL) return 0;
616 if (Dc->dctype == DC_TYPE_INFO)
617 {
618 DC_UnlockDc(Dc);
619 return 0;
620 }
621
622 /* Get a pointer to the source bitmap object */
623 psurf = SURFACE_LockSurface(hBitmap);
624 if (psurf == NULL)
625 {
626 DC_UnlockDc(Dc);
627 return 0;
628 }
629
630 ASSERT(psurf->ppal);
631
632 DC_UnlockDc(Dc);
633
634 /* Copy palette information
635 * Always create a palette for 15 & 16 bit. */
636 if ((bmiLocal.bmiHeader.bV5BitCount == BitsPerFormat(psurf->SurfObj.iBitmapFormat) &&
637 bmiLocal.bmiHeader.bV5BitCount != 15 && bmiLocal.bmiHeader.bV5BitCount != 16) ||
638 !ChkBits)
639 {
640 ppalDst = psurf->ppal;
641 bPaletteMatch = TRUE;
642 }
643 else
644 {
645 hDestPalette = BuildDIBPalette((PBITMAPINFO)&bmiLocal, (PINT)&DestPaletteType);
646 ppalDst = PALETTE_LockPalette(hDestPalette);
647 }
648
649 DPRINT("ppalDst : %p\n", ppalDst);
650 ASSERT(ppalDst);
651
652 /* Copy palette. */
653 switch (bmiLocal.bmiHeader.bV5BitCount)
654 {
655 case 1:
656 case 4:
657 case 8:
658 bmiLocal.bmiHeader.bV5ClrUsed = 0;
659 if (psurf->hSecure &&
660 BitsPerFormat(psurf->SurfObj.iBitmapFormat) == bmiLocal.bmiHeader.bV5BitCount)
661 {
662 if (Usage == DIB_RGB_COLORS)
663 {
664 if (ppalDst->NumColors != 1 << bmiLocal.bmiHeader.bV5BitCount)
665 bmiLocal.bmiHeader.bV5ClrUsed = ppalDst->NumColors;
666 for (Index = 0;
667 Index < (1 << bmiLocal.bmiHeader.bV5BitCount) && Index < ppalDst->NumColors;
668 Index++)
669 {
670 bmiLocal.bmiColors[Index].rgbRed = ppalDst->IndexedColors[Index].peRed;
671 bmiLocal.bmiColors[Index].rgbGreen = ppalDst->IndexedColors[Index].peGreen;
672 bmiLocal.bmiColors[Index].rgbBlue = ppalDst->IndexedColors[Index].peBlue;
673 bmiLocal.bmiColors[Index].rgbReserved = 0;
674 }
675 }
676 else
677 {
678 for (Index = 0;
679 Index < (1 << bmiLocal.bmiHeader.bV5BitCount);
680 Index++)
681 {
682 ((WORD*)bmiLocal.bmiColors)[Index] = Index;
683 }
684 }
685 }
686 else
687 {
688 if (Usage == DIB_PAL_COLORS)
689 {
690 for (Index = 0;
691 Index < (1 << bmiLocal.bmiHeader.bV5BitCount);
692 Index++)
693 {
694 ((WORD*)bmiLocal.bmiColors)[Index] = (WORD)Index;
695 }
696 }
697 else if (bmiLocal.bmiHeader.bV5BitCount > 1 && bPaletteMatch)
698 {
699 for (Index = 0;
700 Index < (1 << bmiLocal.bmiHeader.bV5BitCount) && Index < ppalDst->NumColors;
701 Index++)
702 {
703 bmiLocal.bmiColors[Index].rgbRed = ppalDst->IndexedColors[Index].peRed;
704 bmiLocal.bmiColors[Index].rgbGreen = ppalDst->IndexedColors[Index].peGreen;
705 bmiLocal.bmiColors[Index].rgbBlue = ppalDst->IndexedColors[Index].peBlue;
706 bmiLocal.bmiColors[Index].rgbReserved = 0;
707 }
708 }
709 else
710 {
711 switch (bmiLocal.bmiHeader.bV5BitCount)
712 {
713 case 1:
714 bmiLocal.bmiColors[0].rgbRed =0 ;
715 bmiLocal.bmiColors[0].rgbGreen = 0;
716 bmiLocal.bmiColors[0].rgbBlue = 0;
717 bmiLocal.bmiColors[0].rgbReserved = 0;
718 bmiLocal.bmiColors[1].rgbRed =0xFF ;
719 bmiLocal.bmiColors[1].rgbGreen = 0xFF;
720 bmiLocal.bmiColors[1].rgbBlue = 0xFF;
721 bmiLocal.bmiColors[1].rgbReserved = 0;
722 break;
723 case 4:
724 RtlCopyMemory(bmiLocal.bmiColors, EGAColorsQuads, sizeof(EGAColorsQuads));
725 break;
726 case 8:
727 {
728 INT r, g, b;
729 RGBQUAD *color;
730
731 RtlCopyMemory(bmiLocal.bmiColors, DefLogPaletteQuads, 10 * sizeof(RGBQUAD));
732 RtlCopyMemory(bmiLocal.bmiColors + 246, DefLogPaletteQuads + 10, 10 * sizeof(RGBQUAD));
733 color = bmiLocal.bmiColors + 10;
734 for (r = 0; r <= 5; r++) /* FIXME */
735 for (g = 0; g <= 5; g++)
736 for (b = 0; b <= 5; b++)
737 {
738 color->rgbRed = (r * 0xff) / 5;
739 color->rgbGreen = (g * 0xff) / 5;
740 color->rgbBlue = (b * 0xff) / 5;
741 color->rgbReserved = 0;
742 color++;
743 }
744 }
745 break;
746 }
747 }
748 }
749
750 case 15:
751 if (bmiLocal.bmiHeader.bV5Compression == BI_BITFIELDS)
752 {
753 bmiLocal.bmiHeader.bV5RedMask = 0x7c00;
754 bmiLocal.bmiHeader.bV5GreenMask = 0x03e0;
755 bmiLocal.bmiHeader.bV5BlueMask = 0x001f;
756 }
757 break;
758
759 case 16:
760 if (bmiLocal.bmiHeader.bV5Compression == BI_BITFIELDS)
761 {
762 bmiLocal.bmiHeader.bV5RedMask = 0xf800;
763 bmiLocal.bmiHeader.bV5GreenMask = 0x07e0;
764 bmiLocal.bmiHeader.bV5BlueMask = 0x001f;
765 }
766 break;
767
768 case 24:
769 case 32:
770 if (bmiLocal.bmiHeader.bV5Compression == BI_BITFIELDS)
771 {
772 bmiLocal.bmiHeader.bV5RedMask = 0xff0000;
773 bmiLocal.bmiHeader.bV5GreenMask = 0x00ff00;
774 bmiLocal.bmiHeader.bV5BlueMask = 0x0000ff;
775 }
776 break;
777 }
778
779 /* fill out the BITMAPINFO struct */
780 if (!ChkBits)
781 {
782 bmiLocal.bmiHeader.bV5Width = psurf->SurfObj.sizlBitmap.cx;
783 /* Report negative height for top-down bitmaps. */
784 if (psurf->SurfObj.fjBitmap & BMF_TOPDOWN)
785 bmiLocal.bmiHeader.bV5Height = - psurf->SurfObj.sizlBitmap.cy;
786 else
787 bmiLocal.bmiHeader.bV5Height = psurf->SurfObj.sizlBitmap.cy;
788 bmiLocal.bmiHeader.bV5Planes = 1;
789 bmiLocal.bmiHeader.bV5BitCount = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
790 switch (psurf->SurfObj.iBitmapFormat)
791 {
792 /* FIXME: What about BI_BITFIELDS? */
793 case BMF_1BPP:
794 case BMF_4BPP:
795 case BMF_8BPP:
796 case BMF_16BPP:
797 case BMF_24BPP:
798 case BMF_32BPP:
799 bmiLocal.bmiHeader.bV5Compression = BI_RGB;
800 break;
801 case BMF_4RLE:
802 bmiLocal.bmiHeader.bV5Compression = BI_RLE4;
803 break;
804 case BMF_8RLE:
805 bmiLocal.bmiHeader.bV5Compression = BI_RLE8;
806 break;
807 case BMF_JPEG:
808 bmiLocal.bmiHeader.bV5Compression = BI_JPEG;
809 break;
810 case BMF_PNG:
811 bmiLocal.bmiHeader.bV5Compression = BI_PNG;
812 break;
813 }
814
815 bmiLocal.bmiHeader.bV5SizeImage = psurf->SurfObj.cjBits;
816 bmiLocal.bmiHeader.bV5XPelsPerMeter = psurf->sizlDim.cx; /* FIXME */
817 bmiLocal.bmiHeader.bV5YPelsPerMeter = psurf->sizlDim.cy; /* FIXME */
818 bmiLocal.bmiHeader.bV5ClrUsed = 0;
819 bmiLocal.bmiHeader.bV5ClrImportant = 1 << bmiLocal.bmiHeader.bV5BitCount; /* FIXME */
820 Result = psurf->SurfObj.sizlBitmap.cy;
821 }
822 else
823 {
824 SIZEL DestSize;
825 POINTL SourcePoint;
826
827 //
828 // If we have a good dib pointer, why not just copy bits from there w/o XLATE'ing them.
829 //
830 /* Create the destination bitmap too for the copy operation */
831 if (StartScan > psurf->SurfObj.sizlBitmap.cy)
832 {
833 goto cleanup;
834 }
835 else
836 {
837 ScanLines = min(ScanLines, psurf->SurfObj.sizlBitmap.cy - StartScan);
838 DestSize.cx = psurf->SurfObj.sizlBitmap.cx;
839 DestSize.cy = ScanLines;
840
841 hDestBitmap = NULL;
842
843 bmiLocal.bmiHeader.bV5SizeImage = DIB_GetDIBWidthBytes(DestSize.cx,
844 bmiLocal.bmiHeader.bV5BitCount) * DestSize.cy;
845
846 hDestBitmap = EngCreateBitmap(DestSize,
847 DIB_GetDIBWidthBytes(DestSize.cx,
848 bmiLocal.bmiHeader.bV5BitCount),
849 BitmapFormat(bmiLocal.bmiHeader.bV5BitCount,
850 bmiLocal.bmiHeader.bV5Compression),
851 bmiLocal.bmiHeader.bV5Height > 0 ? 0 : BMF_TOPDOWN,
852 Bits);
853
854 if (hDestBitmap == NULL)
855 goto cleanup;
856 }
857
858 if (NT_SUCCESS(Status))
859 {
860 EXLATEOBJ exlo;
861 SURFOBJ *DestSurfObj;
862 RECTL DestRect;
863
864 EXLATEOBJ_vInitialize(&exlo, psurf->ppal, ppalDst, 0, 0, 0);
865
866 SourcePoint.x = 0;
867 SourcePoint.y = psurf->SurfObj.sizlBitmap.cy - (StartScan + ScanLines);
868
869 /* Determine destination rectangle */
870 DestRect.top = 0;
871 DestRect.left = 0;
872 DestRect.right = DestSize.cx;
873 DestRect.bottom = DestSize.cy;
874
875 DestSurfObj = EngLockSurface((HSURF)hDestBitmap);
876
877 if (IntEngCopyBits(DestSurfObj,
878 &psurf->SurfObj,
879 NULL,
880 &exlo.xlo,
881 &DestRect,
882 &SourcePoint))
883 {
884 DPRINT("GetDIBits %d \n",abs(bmiLocal.bmiHeader.bV5Height) - StartScan);
885 Result = ScanLines;
886 }
887
888 EXLATEOBJ_vCleanup(&exlo);
889 EngUnlockSurface(DestSurfObj);
890 }
891 }
892
893 /* Now that everything is over, get back the information to caller */
894 _SEH2_TRY
895 {
896 /* Note : Info has already been probed */
897 GetBMIFromBitmapV5Info(&bmiLocal, Info, Usage);
898 }
899 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
900 {
901 /* FIXME: fail or something */
902 }
903 _SEH2_END
904
905 cleanup:
906
907 if (hDestBitmap != NULL)
908 EngDeleteSurface((HSURF)hDestBitmap);
909
910 if (hDestPalette != NULL && !bPaletteMatch)
911 {
912 PALETTE_UnlockPalette(ppalDst);
913 PALETTE_FreePaletteByHandle(hDestPalette);
914 }
915
916 SURFACE_UnlockSurface(psurf);
917
918 DPRINT("leaving NtGdiGetDIBitsInternal\n");
919
920 return Result;
921 }
922
923 INT
924 APIENTRY
925 NtGdiStretchDIBitsInternal(
926 HDC hDC,
927 INT XDest,
928 INT YDest,
929 INT DestWidth,
930 INT DestHeight,
931 INT XSrc,
932 INT YSrc,
933 INT SrcWidth,
934 INT SrcHeight,
935 LPBYTE Bits,
936 LPBITMAPINFO BitsInfo,
937 DWORD Usage,
938 DWORD ROP,
939 UINT cjMaxInfo,
940 UINT cjMaxBits,
941 HANDLE hcmXform)
942 {
943 HBITMAP hBitmap, hOldBitmap = NULL;
944 HDC hdcMem;
945 HPALETTE hPal = NULL;
946 PDC pDC;
947 NTSTATUS Status;
948 BITMAPV5INFO bmiLocal ;
949
950 if (!Bits || !BitsInfo)
951 {
952 SetLastWin32Error(ERROR_INVALID_PARAMETER);
953 return 0;
954 }
955
956 _SEH2_TRY
957 {
958 Status = ProbeAndConvertToBitmapV5Info(&bmiLocal, BitsInfo, Usage, cjMaxInfo);
959 ProbeForRead(Bits, cjMaxBits, 1);
960 }
961 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
962 {
963 Status = _SEH2_GetExceptionCode();
964 }
965 _SEH2_END
966
967 if (!NT_SUCCESS(Status))
968 {
969 DPRINT1("NtGdiStretchDIBitsInternal fail to read BitMapInfo: %x or Bits: %x\n",BitsInfo,Bits);
970 return 0;
971 }
972
973 hdcMem = NtGdiCreateCompatibleDC(hDC);
974 if (hdcMem == NULL)
975 {
976 DPRINT1("NtGdiCreateCompatibleDC fail create hdc\n");
977 return 0;
978 }
979
980 hBitmap = NtGdiCreateCompatibleBitmap(hDC,
981 abs(bmiLocal.bmiHeader.bV5Width),
982 abs(bmiLocal.bmiHeader.bV5Height));
983 if (hBitmap == NULL)
984 {
985 DPRINT1("NtGdiCreateCompatibleBitmap fail create bitmap\n");
986 DPRINT1("hDC : 0x%08x \n", hDC);
987 DPRINT1("BitsInfo->bmiHeader.biWidth : 0x%08x \n", BitsInfo->bmiHeader.biWidth);
988 DPRINT1("BitsInfo->bmiHeader.biHeight : 0x%08x \n", BitsInfo->bmiHeader.biHeight);
989 return 0;
990 }
991
992 /* Select the bitmap into hdcMem, and save a handle to the old bitmap */
993 hOldBitmap = NtGdiSelectBitmap(hdcMem, hBitmap);
994
995 if (Usage == DIB_PAL_COLORS)
996 {
997 hPal = NtGdiGetDCObject(hDC, GDI_OBJECT_TYPE_PALETTE);
998 hPal = GdiSelectPalette(hdcMem, hPal, FALSE);
999 }
1000
1001 if (bmiLocal.bmiHeader.bV5Compression == BI_RLE4 ||
1002 bmiLocal.bmiHeader.bV5Compression == BI_RLE8)
1003 {
1004 /* copy existing bitmap from destination dc */
1005 if (SrcWidth == DestWidth && SrcHeight == DestHeight)
1006 NtGdiBitBlt(hdcMem, XSrc, abs(bmiLocal.bmiHeader.bV5Height) - SrcHeight - YSrc,
1007 SrcWidth, SrcHeight, hDC, XDest, YDest, ROP, 0, 0);
1008 else
1009 NtGdiStretchBlt(hdcMem, XSrc, abs(bmiLocal.bmiHeader.bV5Height) - SrcHeight - YSrc,
1010 SrcWidth, SrcHeight, hDC, XDest, YDest, DestWidth, DestHeight,
1011 ROP, 0);
1012 }
1013
1014 pDC = DC_LockDc(hdcMem);
1015 if (pDC != NULL)
1016 {
1017 /* Note BitsInfo->bmiHeader.biHeight is the number of scanline,
1018 * if it negitve we getting to many scanline for scanline is UINT not
1019 * a INT, so we need make the negtive value to positve and that make the
1020 * count correct for negtive bitmap, TODO : we need testcase for this api */
1021 IntSetDIBits(pDC, hBitmap, 0, abs(bmiLocal.bmiHeader.bV5Height), Bits,
1022 &bmiLocal, Usage);
1023
1024 DC_UnlockDc(pDC);
1025 }
1026
1027
1028 /* Origin for DIBitmap may be bottom left (positive biHeight) or top
1029 left (negative biHeight) */
1030 if (SrcWidth == DestWidth && SrcHeight == DestHeight)
1031 NtGdiBitBlt(hDC, XDest, YDest, DestWidth, DestHeight,
1032 hdcMem, XSrc, abs(bmiLocal.bmiHeader.bV5Height) - SrcHeight - YSrc,
1033 ROP, 0, 0);
1034 else
1035 NtGdiStretchBlt(hDC, XDest, YDest, DestWidth, DestHeight,
1036 hdcMem, XSrc, abs(bmiLocal.bmiHeader.bV5Height) - SrcHeight - YSrc,
1037 SrcWidth, SrcHeight, ROP, 0);
1038
1039 /* cleanup */
1040 if (hPal)
1041 GdiSelectPalette(hdcMem, hPal, FALSE);
1042
1043 if (hOldBitmap)
1044 NtGdiSelectBitmap(hdcMem, hOldBitmap);
1045
1046 NtGdiDeleteObjectApp(hdcMem);
1047
1048 GreDeleteObject(hBitmap);
1049
1050 return SrcHeight;
1051 }
1052
1053
1054 HBITMAP
1055 FASTCALL
1056 IntCreateDIBitmap(
1057 PDC Dc,
1058 INT width,
1059 INT height,
1060 UINT bpp,
1061 DWORD init,
1062 LPBYTE bits,
1063 PBITMAPV5INFO data,
1064 DWORD coloruse)
1065 {
1066 HBITMAP handle;
1067 BOOL fColor;
1068
1069 // Check if we should create a monochrome or color bitmap. We create a monochrome bitmap only if it has exactly 2
1070 // colors, which are black followed by white, nothing else. In all other cases, we create a color bitmap.
1071
1072 if (bpp != 1) fColor = TRUE;
1073 else if ((coloruse != DIB_RGB_COLORS) || (init != CBM_INIT) || !data) fColor = FALSE;
1074 else
1075 {
1076 const RGBQUAD *rgb = data->bmiColors;
1077 DWORD col = RGB(rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue);
1078
1079 // Check if the first color of the colormap is black
1080 if ((col == RGB(0, 0, 0)))
1081 {
1082 rgb++;
1083 col = RGB(rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue);
1084
1085 // If the second color is white, create a monochrome bitmap
1086 fColor = (col != RGB(0xff,0xff,0xff));
1087 }
1088 else fColor = TRUE;
1089 }
1090
1091 // Now create the bitmap
1092 if (fColor)
1093 {
1094 handle = IntCreateCompatibleBitmap(Dc, width, height);
1095 }
1096 else
1097 {
1098 handle = GreCreateBitmap(width,
1099 height,
1100 1,
1101 1,
1102 NULL);
1103 }
1104
1105 if (height < 0)
1106 height = -height;
1107
1108 if (NULL != handle && CBM_INIT == init)
1109 {
1110 IntSetDIBits(Dc, handle, 0, height, bits, data, coloruse);
1111 }
1112
1113 return handle;
1114 }
1115
1116 // The CreateDIBitmap function creates a device-dependent bitmap (DDB) from a DIB and, optionally, sets the bitmap bits
1117 // The DDB that is created will be whatever bit depth your reference DC is
1118 HBITMAP
1119 APIENTRY
1120 NtGdiCreateDIBitmapInternal(
1121 IN HDC hDc,
1122 IN INT cx,
1123 IN INT cy,
1124 IN DWORD fInit,
1125 IN OPTIONAL LPBYTE pjInit,
1126 IN OPTIONAL LPBITMAPINFO pbmi,
1127 IN DWORD iUsage,
1128 IN UINT cjMaxInitInfo,
1129 IN UINT cjMaxBits,
1130 IN FLONG fl,
1131 IN HANDLE hcmXform)
1132 {
1133 BITMAPV5INFO bmiLocal ;
1134 NTSTATUS Status = STATUS_SUCCESS;
1135
1136 _SEH2_TRY
1137 {
1138 if(pbmi) Status = ProbeAndConvertToBitmapV5Info(&bmiLocal, pbmi, iUsage, cjMaxInitInfo);
1139 if(pjInit && (fInit == CBM_INIT)) ProbeForRead(pjInit, cjMaxBits, 1);
1140 }
1141 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1142 {
1143 Status = _SEH2_GetExceptionCode();
1144 }
1145 _SEH2_END
1146
1147 if(!NT_SUCCESS(Status))
1148 {
1149 SetLastNtError(Status);
1150 return NULL;
1151 }
1152
1153 return GreCreateDIBitmapInternal(hDc,
1154 cx,
1155 cy,
1156 fInit,
1157 pjInit,
1158 pbmi ? &bmiLocal : NULL,
1159 iUsage,
1160 fl,
1161 hcmXform);
1162 }
1163
1164 HBITMAP
1165 FASTCALL
1166 GreCreateDIBitmapInternal(
1167 IN HDC hDc,
1168 IN INT cx,
1169 IN INT cy,
1170 IN DWORD fInit,
1171 IN OPTIONAL LPBYTE pjInit,
1172 IN OPTIONAL PBITMAPV5INFO pbmi,
1173 IN DWORD iUsage,
1174 IN FLONG fl,
1175 IN HANDLE hcmXform)
1176 {
1177 PDC Dc;
1178 HBITMAP Bmp;
1179 WORD bpp;
1180 HDC hdcDest;
1181
1182 if (!hDc) /* 1bpp monochrome bitmap */
1183 { // Should use System Bitmap DC hSystemBM, with CreateCompatibleDC for this.
1184 hdcDest = IntGdiCreateDC(NULL, NULL, NULL, NULL,FALSE);
1185 if(!hdcDest)
1186 {
1187 return NULL;
1188 }
1189 }
1190 else
1191 {
1192 hdcDest = hDc;
1193 }
1194
1195 Dc = DC_LockDc(hdcDest);
1196 if (!Dc)
1197 {
1198 SetLastWin32Error(ERROR_INVALID_HANDLE);
1199 return NULL;
1200 }
1201 /* It's OK to set bpp=0 here, as IntCreateDIBitmap will create a compatible Bitmap
1202 * if bpp != 1 and ignore the real value that was passed */
1203 if (pbmi)
1204 bpp = pbmi->bmiHeader.bV5BitCount;
1205 else
1206 bpp = 0;
1207 Bmp = IntCreateDIBitmap(Dc, cx, cy, bpp, fInit, pjInit, pbmi, iUsage);
1208 DC_UnlockDc(Dc);
1209
1210 if(!hDc)
1211 {
1212 NtGdiDeleteObjectApp(hdcDest);
1213 }
1214 return Bmp;
1215 }
1216
1217
1218 HBITMAP
1219 APIENTRY
1220 NtGdiCreateDIBSection(
1221 IN HDC hDC,
1222 IN OPTIONAL HANDLE hSection,
1223 IN DWORD dwOffset,
1224 IN LPBITMAPINFO bmi,
1225 IN DWORD Usage,
1226 IN UINT cjHeader,
1227 IN FLONG fl,
1228 IN ULONG_PTR dwColorSpace,
1229 OUT PVOID *Bits)
1230 {
1231 HBITMAP hbitmap = 0;
1232 DC *dc;
1233 BOOL bDesktopDC = FALSE;
1234 BITMAPV5INFO bmiLocal;
1235 NTSTATUS Status;
1236
1237 if (!bmi) return hbitmap; // Make sure.
1238
1239 _SEH2_TRY
1240 {
1241 Status = ProbeAndConvertToBitmapV5Info(&bmiLocal, bmi, Usage, 0);
1242 }
1243 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1244 {
1245 Status = _SEH2_GetExceptionCode();
1246 }
1247 _SEH2_END
1248
1249 if(!NT_SUCCESS(Status))
1250 {
1251 SetLastNtError(Status);
1252 return NULL;
1253 }
1254
1255 // If the reference hdc is null, take the desktop dc
1256 if (hDC == 0)
1257 {
1258 hDC = NtGdiCreateCompatibleDC(0);
1259 bDesktopDC = TRUE;
1260 }
1261
1262 if ((dc = DC_LockDc(hDC)))
1263 {
1264 hbitmap = DIB_CreateDIBSection(dc,
1265 &bmiLocal,
1266 Usage,
1267 Bits,
1268 hSection,
1269 dwOffset,
1270 0);
1271 DC_UnlockDc(dc);
1272 }
1273 else
1274 {
1275 SetLastWin32Error(ERROR_INVALID_HANDLE);
1276 }
1277
1278 if (bDesktopDC)
1279 NtGdiDeleteObjectApp(hDC);
1280
1281 return hbitmap;
1282 }
1283
1284 HBITMAP
1285 APIENTRY
1286 DIB_CreateDIBSection(
1287 PDC dc,
1288 CONST BITMAPV5INFO *bmi,
1289 UINT usage,
1290 LPVOID *bits,
1291 HANDLE section,
1292 DWORD offset,
1293 DWORD ovr_pitch)
1294 {
1295 HBITMAP res = 0;
1296 SURFACE *bmp = NULL;
1297 void *mapBits = NULL;
1298 HPALETTE hpal ;
1299 ULONG palMode = PAL_INDEXED;
1300
1301 // Fill BITMAP32 structure with DIB data
1302 CONST BITMAPV5HEADER *bi = &bmi->bmiHeader;
1303 INT effHeight;
1304 ULONG totalSize;
1305 BITMAP bm;
1306 SIZEL Size;
1307 CONST RGBQUAD *lpRGB = NULL;
1308 HANDLE hSecure;
1309 DWORD dsBitfields[3] = {0};
1310 ULONG ColorCount;
1311
1312 DPRINT("format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n",
1313 bi->bV5Width, bi->bV5Height, bi->bV5Planes, bi->bV5BitCount,
1314 bi->bV5SizeImage, bi->bV5ClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1315
1316 /* CreateDIBSection should fail for compressed formats */
1317 if (bi->bV5Compression == BI_RLE4 || bi->bV5Compression == BI_RLE8)
1318 {
1319 return (HBITMAP)NULL;
1320 }
1321
1322 effHeight = bi->bV5Height >= 0 ? bi->bV5Height : -bi->bV5Height;
1323 bm.bmType = 0;
1324 bm.bmWidth = bi->bV5Width;
1325 bm.bmHeight = effHeight;
1326 bm.bmWidthBytes = ovr_pitch ? ovr_pitch : (ULONG) DIB_GetDIBWidthBytes(bm.bmWidth, bi->bV5BitCount);
1327
1328 bm.bmPlanes = bi->bV5Planes;
1329 bm.bmBitsPixel = bi->bV5BitCount;
1330 bm.bmBits = NULL;
1331
1332 // Get storage location for DIB bits. Only use biSizeImage if it's valid and
1333 // we're dealing with a compressed bitmap. Otherwise, use width * height.
1334 totalSize = bi->bV5SizeImage && bi->bV5Compression != BI_RGB
1335 ? bi->bV5SizeImage : (ULONG)(bm.bmWidthBytes * effHeight);
1336
1337 if (section)
1338 {
1339 SYSTEM_BASIC_INFORMATION Sbi;
1340 NTSTATUS Status;
1341 DWORD mapOffset;
1342 LARGE_INTEGER SectionOffset;
1343 SIZE_T mapSize;
1344
1345 Status = ZwQuerySystemInformation(SystemBasicInformation,
1346 &Sbi,
1347 sizeof Sbi,
1348 0);
1349 if (!NT_SUCCESS(Status))
1350 {
1351 return NULL;
1352 }
1353
1354 mapOffset = offset - (offset % Sbi.AllocationGranularity);
1355 mapSize = bi->bV5SizeImage + (offset - mapOffset);
1356
1357 SectionOffset.LowPart = mapOffset;
1358 SectionOffset.HighPart = 0;
1359
1360 Status = ZwMapViewOfSection(section,
1361 NtCurrentProcess(),
1362 &mapBits,
1363 0,
1364 0,
1365 &SectionOffset,
1366 &mapSize,
1367 ViewShare,
1368 0,
1369 PAGE_READWRITE);
1370 if (!NT_SUCCESS(Status))
1371 {
1372 SetLastWin32Error(ERROR_INVALID_PARAMETER);
1373 return NULL;
1374 }
1375
1376 if (mapBits) bm.bmBits = (char *)mapBits + (offset - mapOffset);
1377 }
1378 else if (ovr_pitch && offset)
1379 bm.bmBits = (LPVOID) offset;
1380 else
1381 {
1382 offset = 0;
1383 bm.bmBits = EngAllocUserMem(totalSize, 0);
1384 if(!bm.bmBits) goto cleanup;
1385 }
1386
1387 // hSecure = MmSecureVirtualMemory(bm.bmBits, totalSize, PAGE_READWRITE);
1388 hSecure = (HANDLE)0x1; // HACK OF UNIMPLEMENTED KERNEL STUFF !!!!
1389
1390 if (usage == DIB_PAL_COLORS)
1391 {
1392 lpRGB = DIB_MapPaletteColors(dc, bmi);
1393 ColorCount = bi->bV5ClrUsed;
1394 if (ColorCount == 0)
1395 {
1396 ColorCount = max(1 << bi->bV5BitCount, 256);
1397 }
1398 }
1399 else if(bi->bV5BitCount <= 8)
1400 {
1401 lpRGB = bmi->bmiColors;
1402 ColorCount = 1 << bi->bV5BitCount;
1403 }
1404 else
1405 {
1406 lpRGB = NULL;
1407 ColorCount = 0;
1408 }
1409
1410 /* Set dsBitfields values */
1411 if (usage == DIB_PAL_COLORS || bi->bV5BitCount <= 8)
1412 {
1413 dsBitfields[0] = dsBitfields[1] = dsBitfields[2] = 0;
1414 palMode = PAL_INDEXED;
1415 }
1416 else if (bi->bV5Compression == BI_RGB)
1417 {
1418 dsBitfields[0] = dsBitfields[1] = dsBitfields[2] = 0;
1419 switch (bi->bV5BitCount)
1420 {
1421 case 15:
1422 palMode = PAL_RGB16_555;
1423 break;
1424
1425 case 16:
1426 palMode = PAL_RGB16_565;
1427 break;
1428
1429 case 24:
1430 case 32:
1431 palMode = PAL_RGB;
1432 break;
1433 }
1434 }
1435 else
1436 {
1437 dsBitfields[0] = bi->bV5RedMask;
1438 dsBitfields[1] = bi->bV5GreenMask;
1439 dsBitfields[2] = bi->bV5BlueMask;
1440 palMode = PAL_BITFIELDS;
1441 }
1442
1443 // Create Device Dependent Bitmap and add DIB pointer
1444 Size.cx = bm.bmWidth;
1445 Size.cy = abs(bm.bmHeight);
1446 res = GreCreateBitmapEx(bm.bmWidth,
1447 abs(bm.bmHeight),
1448 bm.bmWidthBytes,
1449 BitmapFormat(bi->bV5BitCount * bi->bV5Planes, bi->bV5Compression),
1450 BMF_DONTCACHE | BMF_USERMEM | BMF_NOZEROINIT |
1451 (bi->bV5Height < 0 ? BMF_TOPDOWN : 0),
1452 bi->bV5SizeImage,
1453 bm.bmBits);
1454 if (!res)
1455 {
1456 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
1457 goto cleanup;
1458 }
1459 bmp = SURFACE_LockSurface(res);
1460 if (NULL == bmp)
1461 {
1462 SetLastWin32Error(ERROR_INVALID_HANDLE);
1463 goto cleanup;
1464 }
1465
1466 /* WINE NOTE: WINE makes use of a colormap, which is a color translation
1467 table between the DIB and the X physical device. Obviously,
1468 this is left out of the ReactOS implementation. Instead,
1469 we call NtGdiSetDIBColorTable. */
1470 bmp->hDIBSection = section;
1471 bmp->hSecure = hSecure;
1472 bmp->dwOffset = offset;
1473 bmp->flags = API_BITMAP;
1474 bmp->dsBitfields[0] = dsBitfields[0];
1475 bmp->dsBitfields[1] = dsBitfields[1];
1476 bmp->dsBitfields[2] = dsBitfields[2];
1477 bmp->biClrUsed = ColorCount;
1478 bmp->biClrImportant = bi->bV5ClrImportant;
1479
1480 hpal = PALETTE_AllocPalette(palMode, ColorCount, (ULONG*)lpRGB,
1481 dsBitfields[0],
1482 dsBitfields[1],
1483 dsBitfields[2]);
1484
1485 bmp->ppal = PALETTE_ShareLockPalette(hpal);
1486 /* Lazy delete hpal, it will be freed at surface release */
1487 GreDeleteObject(hpal);
1488
1489 // Clean up in case of errors
1490 cleanup:
1491 if (!res || !bmp || !bm.bmBits)
1492 {
1493 DPRINT("got an error res=%08x, bmp=%p, bm.bmBits=%p\n", res, bmp, bm.bmBits);
1494 if (bm.bmBits)
1495 {
1496 // MmUnsecureVirtualMemory(hSecure); // FIXME: Implement this!
1497 if (section)
1498 {
1499 ZwUnmapViewOfSection(NtCurrentProcess(), mapBits);
1500 bm.bmBits = NULL;
1501 }
1502 else
1503 if (!offset)
1504 EngFreeUserMem(bm.bmBits), bm.bmBits = NULL;
1505 }
1506
1507 if (bmp)
1508 bmp = NULL;
1509
1510 if (res)
1511 {
1512 SURFACE_FreeSurfaceByHandle(res);
1513 res = 0;
1514 }
1515 }
1516
1517 if (lpRGB != bmi->bmiColors && lpRGB)
1518 {
1519 ExFreePoolWithTag((PVOID)lpRGB, TAG_COLORMAP);
1520 }
1521
1522 if (bmp)
1523 {
1524 SURFACE_UnlockSurface(bmp);
1525 }
1526
1527 // Return BITMAP handle and storage location
1528 if (NULL != bm.bmBits && NULL != bits)
1529 {
1530 *bits = bm.bmBits;
1531 }
1532
1533 return res;
1534 }
1535
1536 /***********************************************************************
1537 * DIB_GetDIBWidthBytes
1538 *
1539 * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
1540 * http://www.microsoft.com/msdn/sdk/platforms/doc/sdk/win32/struc/src/str01.htm
1541 * 11/16/1999 (RJJ) lifted from wine
1542 */
1543 INT FASTCALL DIB_GetDIBWidthBytes(INT width, INT depth)
1544 {
1545 return ((width * depth + 31) & ~31) >> 3;
1546 }
1547
1548 /***********************************************************************
1549 * DIB_GetDIBImageBytes
1550 *
1551 * Return the number of bytes used to hold the image in a DIB bitmap.
1552 * 11/16/1999 (RJJ) lifted from wine
1553 */
1554
1555 INT APIENTRY DIB_GetDIBImageBytes(INT width, INT height, INT depth)
1556 {
1557 return DIB_GetDIBWidthBytes(width, depth) * (height < 0 ? -height : height);
1558 }
1559
1560 /***********************************************************************
1561 * DIB_BitmapInfoSize
1562 *
1563 * Return the size of the bitmap info structure including color table.
1564 * 11/16/1999 (RJJ) lifted from wine
1565 */
1566
1567 INT FASTCALL DIB_BitmapInfoSize(const BITMAPINFO * info, WORD coloruse)
1568 {
1569 int colors;
1570
1571 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
1572 {
1573 BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)info;
1574 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
1575 return sizeof(BITMAPCOREHEADER) + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
1576 }
1577 else /* assume BITMAPINFOHEADER */
1578 {
1579 colors = info->bmiHeader.biClrUsed;
1580 if (!colors && (info->bmiHeader.biBitCount <= 8)) colors = 1 << info->bmiHeader.biBitCount;
1581 return info->bmiHeader.biSize + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
1582 }
1583 }
1584
1585 RGBQUAD *
1586 FASTCALL
1587 DIB_MapPaletteColors(PDC dc, CONST BITMAPV5INFO* lpbmi)
1588 {
1589 RGBQUAD *lpRGB;
1590 ULONG nNumColors,i;
1591 USHORT *lpIndex;
1592 PPALETTE palGDI;
1593
1594 palGDI = PALETTE_LockPalette(dc->dclevel.hpal);
1595
1596 if (NULL == palGDI)
1597 {
1598 return NULL;
1599 }
1600
1601 if (palGDI->Mode != PAL_INDEXED)
1602 {
1603 PALETTE_UnlockPalette(palGDI);
1604 return NULL;
1605 }
1606
1607 nNumColors = 1 << lpbmi->bmiHeader.bV5BitCount;
1608 if (lpbmi->bmiHeader.bV5ClrUsed)
1609 {
1610 nNumColors = min(nNumColors, lpbmi->bmiHeader.bV5ClrUsed);
1611 }
1612
1613 lpRGB = (RGBQUAD *)ExAllocatePoolWithTag(PagedPool, sizeof(RGBQUAD) * nNumColors, TAG_COLORMAP);
1614 if (lpRGB == NULL)
1615 {
1616 PALETTE_UnlockPalette(palGDI);
1617 return NULL;
1618 }
1619
1620 lpIndex = (USHORT *)&lpbmi->bmiColors[0];
1621
1622 for (i = 0; i < nNumColors; i++)
1623 {
1624 if (*lpIndex < palGDI->NumColors)
1625 {
1626 lpRGB[i].rgbRed = palGDI->IndexedColors[*lpIndex].peRed;
1627 lpRGB[i].rgbGreen = palGDI->IndexedColors[*lpIndex].peGreen;
1628 lpRGB[i].rgbBlue = palGDI->IndexedColors[*lpIndex].peBlue;
1629 }
1630 else
1631 {
1632 lpRGB[i].rgbRed = 0;
1633 lpRGB[i].rgbGreen = 0;
1634 lpRGB[i].rgbBlue = 0;
1635 }
1636 lpRGB[i].rgbReserved = 0;
1637 lpIndex++;
1638 }
1639 PALETTE_UnlockPalette(palGDI);
1640
1641 return lpRGB;
1642 }
1643
1644 HPALETTE
1645 FASTCALL
1646 BuildDIBPalette(CONST BITMAPINFO *bmi, PINT paletteType)
1647 {
1648 BYTE bits;
1649 ULONG ColorCount;
1650 HPALETTE hPal;
1651 ULONG RedMask, GreenMask, BlueMask;
1652 PDWORD pdwColors = (PDWORD)((PBYTE)bmi + bmi->bmiHeader.biSize);
1653
1654 // Determine Bits Per Pixel
1655 bits = bmi->bmiHeader.biBitCount;
1656
1657 // Determine paletteType from Bits Per Pixel
1658 if (bits <= 8)
1659 {
1660 *paletteType = PAL_INDEXED;
1661 RedMask = GreenMask = BlueMask = 0;
1662 }
1663 else if (bmi->bmiHeader.biCompression == BI_BITFIELDS)
1664 {
1665 *paletteType = PAL_BITFIELDS;
1666 RedMask = pdwColors[0];
1667 GreenMask = pdwColors[1];
1668 BlueMask = pdwColors[2];
1669 }
1670 else if (bits == 15)
1671 {
1672 *paletteType = PAL_BITFIELDS;
1673 RedMask = 0x7c00;
1674 GreenMask = 0x03e0;
1675 BlueMask = 0x001f;
1676 }
1677 else if (bits == 16)
1678 {
1679 *paletteType = PAL_BITFIELDS;
1680 RedMask = 0xF800;
1681 GreenMask = 0x07e0;
1682 BlueMask = 0x001f;
1683 }
1684 else
1685 {
1686 *paletteType = PAL_BGR;
1687 RedMask = 0xff0000;
1688 GreenMask = 0x00ff00;
1689 BlueMask = 0x0000ff;
1690 }
1691
1692 if (bmi->bmiHeader.biClrUsed == 0)
1693 {
1694 ColorCount = 1 << bmi->bmiHeader.biBitCount;
1695 }
1696 else
1697 {
1698 ColorCount = bmi->bmiHeader.biClrUsed;
1699 }
1700
1701 if (PAL_INDEXED == *paletteType)
1702 {
1703 hPal = PALETTE_AllocPaletteIndexedRGB(ColorCount, (RGBQUAD*)pdwColors);
1704 }
1705 else
1706 {
1707 hPal = PALETTE_AllocPalette(*paletteType, ColorCount,
1708 NULL,
1709 RedMask, GreenMask, BlueMask);
1710 }
1711
1712 return hPal;
1713 }
1714
1715 FORCEINLINE
1716 DWORD
1717 GetBMIColor(CONST BITMAPINFO* pbmi, INT i)
1718 {
1719 DWORD dwRet = 0;
1720 INT size;
1721 if(pbmi->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
1722 {
1723 /* BITMAPCOREINFO holds RGBTRIPLE values */
1724 size = sizeof(RGBTRIPLE);
1725 }
1726 else
1727 {
1728 size = sizeof(RGBQUAD);
1729 }
1730 memcpy(&dwRet, (PBYTE)pbmi + pbmi->bmiHeader.biSize + i*size, size);
1731 return dwRet;
1732 }
1733
1734 FORCEINLINE
1735 VOID
1736 SetBMIColor(CONST BITMAPINFO* pbmi, DWORD* color, INT i)
1737 {
1738 PVOID pvColors = ((PBYTE)pbmi + pbmi->bmiHeader.biSize);
1739 if(pbmi->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
1740 {
1741 RGBTRIPLE *pColor = pvColors;
1742 pColor[i] = *(RGBTRIPLE*)color;
1743 }
1744 else
1745 {
1746 RGBQUAD *pColor = pvColors;
1747 pColor[i] = *(RGBQUAD*)color;
1748 }
1749 }
1750
1751 NTSTATUS
1752 FASTCALL
1753 ProbeAndConvertToBitmapV5Info(
1754 OUT PBITMAPV5INFO pbmiDst,
1755 IN CONST BITMAPINFO* pbmiUnsafe,
1756 IN DWORD dwColorUse,
1757 IN UINT MaxSize)
1758 {
1759 DWORD dwSize;
1760 ULONG ulWidthBytes;
1761 PBITMAPV5HEADER pbmhDst = &pbmiDst->bmiHeader;
1762
1763 /* Get the size and probe */
1764 ProbeForRead(&pbmiUnsafe->bmiHeader.biSize, sizeof(DWORD), 1);
1765 dwSize = pbmiUnsafe->bmiHeader.biSize;
1766 /* At least dwSize bytes must be valids */
1767 ProbeForRead(pbmiUnsafe, max(dwSize, MaxSize), 1);
1768 if(!MaxSize)
1769 ProbeForRead(pbmiUnsafe, DIB_BitmapInfoSize(pbmiUnsafe, dwColorUse), 1);
1770
1771 /* Check the size */
1772 // FIXME: are intermediate sizes allowed? As what are they interpreted?
1773 // make sure we don't use a too big dwSize later
1774 if (dwSize != sizeof(BITMAPCOREHEADER) &&
1775 dwSize != sizeof(BITMAPINFOHEADER) &&
1776 dwSize != sizeof(BITMAPV4HEADER) &&
1777 dwSize != sizeof(BITMAPV5HEADER))
1778 {
1779 return STATUS_INVALID_PARAMETER;
1780 }
1781
1782 if (dwSize == sizeof(BITMAPCOREHEADER))
1783 {
1784 PBITMAPCOREHEADER pbch = (PBITMAPCOREHEADER)pbmiUnsafe;
1785
1786 /* Manually copy the fields that are present */
1787 pbmhDst->bV5Width = pbch->bcWidth;
1788 pbmhDst->bV5Height = pbch->bcHeight;
1789 pbmhDst->bV5Planes = pbch->bcPlanes;
1790 pbmhDst->bV5BitCount = pbch->bcBitCount;
1791
1792 /* Set some default values */
1793 pbmhDst->bV5Compression = BI_RGB;
1794 pbmhDst->bV5SizeImage = DIB_GetDIBImageBytes(pbch->bcWidth,
1795 pbch->bcHeight,
1796 pbch->bcPlanes*pbch->bcBitCount) ;
1797 pbmhDst->bV5XPelsPerMeter = 72;
1798 pbmhDst->bV5YPelsPerMeter = 72;
1799 pbmhDst->bV5ClrUsed = 0;
1800 pbmhDst->bV5ClrImportant = 0;
1801 }
1802 else
1803 {
1804 /* Copy valid fields */
1805 memcpy(pbmiDst, pbmiUnsafe, dwSize);
1806 if(!pbmhDst->bV5SizeImage)
1807 pbmhDst->bV5SizeImage = DIB_GetDIBImageBytes(pbmhDst->bV5Width,
1808 pbmhDst->bV5Height,
1809 pbmhDst->bV5Planes*pbmhDst->bV5BitCount) ;
1810
1811 if(dwSize < sizeof(BITMAPV5HEADER))
1812 {
1813 /* Zero out the rest of the V5 header */
1814 memset((char*)pbmiDst + dwSize, 0, sizeof(BITMAPV5HEADER) - dwSize);
1815 }
1816 }
1817 pbmhDst->bV5Size = sizeof(BITMAPV5HEADER);
1818
1819
1820 if (dwSize < sizeof(BITMAPV4HEADER))
1821 {
1822 if (pbmhDst->bV5Compression == BI_BITFIELDS)
1823 {
1824 pbmhDst->bV5RedMask = GetBMIColor(pbmiUnsafe, 0);
1825 pbmhDst->bV5GreenMask = GetBMIColor(pbmiUnsafe, 1);
1826 pbmhDst->bV5BlueMask = GetBMIColor(pbmiUnsafe, 2);
1827 pbmhDst->bV5AlphaMask = 0;
1828 pbmhDst->bV5ClrUsed = 0;
1829 }
1830
1831 // pbmhDst->bV5CSType;
1832 // pbmhDst->bV5Endpoints;
1833 // pbmhDst->bV5GammaRed;
1834 // pbmhDst->bV5GammaGreen;
1835 // pbmhDst->bV5GammaBlue;
1836 }
1837
1838 if (dwSize < sizeof(BITMAPV5HEADER))
1839 {
1840 // pbmhDst->bV5Intent;
1841 // pbmhDst->bV5ProfileData;
1842 // pbmhDst->bV5ProfileSize;
1843 // pbmhDst->bV5Reserved;
1844 }
1845
1846 ulWidthBytes = ((pbmhDst->bV5Width * pbmhDst->bV5Planes *
1847 pbmhDst->bV5BitCount + 31) & ~31) / 8;
1848
1849 if (pbmhDst->bV5SizeImage == 0)
1850 pbmhDst->bV5SizeImage = abs(ulWidthBytes * pbmhDst->bV5Height);
1851
1852 if (pbmhDst->bV5ClrUsed == 0)
1853 {
1854 switch(pbmhDst->bV5BitCount)
1855 {
1856 case 1:
1857 pbmhDst->bV5ClrUsed = 2;
1858 break;
1859 case 4:
1860 pbmhDst->bV5ClrUsed = 16;
1861 break;
1862 case 8:
1863 pbmhDst->bV5ClrUsed = 256;
1864 break;
1865 default:
1866 pbmhDst->bV5ClrUsed = 0;
1867 break;
1868 }
1869 }
1870
1871 if (pbmhDst->bV5Planes != 1)
1872 {
1873 return STATUS_INVALID_PARAMETER;
1874 }
1875
1876 if (pbmhDst->bV5BitCount != 0 && pbmhDst->bV5BitCount != 1 &&
1877 pbmhDst->bV5BitCount != 4 && pbmhDst->bV5BitCount != 8 &&
1878 pbmhDst->bV5BitCount != 16 && pbmhDst->bV5BitCount != 24 &&
1879 pbmhDst->bV5BitCount != 32)
1880 {
1881 DPRINT("Invalid bit count: %d\n", pbmhDst->bV5BitCount);
1882 return STATUS_INVALID_PARAMETER;
1883 }
1884
1885 if ((pbmhDst->bV5BitCount == 0 &&
1886 pbmhDst->bV5Compression != BI_JPEG && pbmhDst->bV5Compression != BI_PNG))
1887 {
1888 DPRINT("Bit count 0 is invalid for compression %d.\n", pbmhDst->bV5Compression);
1889 return STATUS_INVALID_PARAMETER;
1890 }
1891
1892 if (pbmhDst->bV5Compression == BI_BITFIELDS &&
1893 pbmhDst->bV5BitCount != 16 && pbmhDst->bV5BitCount != 32)
1894 {
1895 DPRINT("Bit count %d is invalid for compression BI_BITFIELDS.\n", pbmhDst->bV5BitCount);
1896 return STATUS_INVALID_PARAMETER;
1897 }
1898
1899 /* Copy Colors */
1900 if(pbmhDst->bV5ClrUsed)
1901 {
1902 INT i;
1903 if(dwColorUse == DIB_PAL_COLORS)
1904 {
1905 RtlCopyMemory(pbmiDst->bmiColors,
1906 pbmiUnsafe->bmiColors,
1907 pbmhDst->bV5ClrUsed * sizeof(WORD));
1908 }
1909 else
1910 {
1911 for(i = 0; i < pbmhDst->bV5ClrUsed; i++)
1912 {
1913 ((DWORD*)pbmiDst->bmiColors)[i] = GetBMIColor(pbmiUnsafe, i);
1914 }
1915 }
1916 }
1917
1918 return STATUS_SUCCESS;
1919 }
1920
1921 VOID
1922 FASTCALL
1923 GetBMIFromBitmapV5Info(IN PBITMAPV5INFO pbmiSrc,
1924 OUT PBITMAPINFO pbmiDst,
1925 IN DWORD dwColorUse)
1926 {
1927 if(pbmiDst->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
1928 {
1929 /* Manually set value */
1930 BITMAPCOREHEADER* pbmhCore = (BITMAPCOREHEADER*)&pbmiDst->bmiHeader;
1931 pbmhCore->bcWidth = pbmiSrc->bmiHeader.bV5Width;
1932 pbmhCore->bcHeight = pbmiSrc->bmiHeader.bV5Height;
1933 pbmhCore->bcPlanes = pbmiSrc->bmiHeader.bV5Planes;
1934 pbmhCore->bcBitCount = pbmiSrc->bmiHeader.bV5BitCount;
1935 }
1936 else
1937 {
1938 /* Copy valid Fields, keep bmiHeader.biSize safe */
1939 RtlCopyMemory(&pbmiDst->bmiHeader.biWidth,
1940 &pbmiSrc->bmiHeader.bV5Width,
1941 pbmiDst->bmiHeader.biSize - sizeof(DWORD));
1942 }
1943 if((pbmiDst->bmiHeader.biSize < sizeof(BITMAPV4HEADER)) &&
1944 (pbmiSrc->bmiHeader.bV5Compression == BI_BITFIELDS))
1945 {
1946 /* Masks are already set in V4 and V5 headers */
1947 SetBMIColor(pbmiDst, &pbmiSrc->bmiHeader.bV5RedMask, 0);
1948 SetBMIColor(pbmiDst, &pbmiSrc->bmiHeader.bV5GreenMask, 1);
1949 SetBMIColor(pbmiDst, &pbmiSrc->bmiHeader.bV5BlueMask, 2);
1950 }
1951 else
1952 {
1953 INT i;
1954 ULONG cColorsUsed;
1955
1956 cColorsUsed = pbmiSrc->bmiHeader.bV5ClrUsed;
1957 if (cColorsUsed == 0 && pbmiSrc->bmiHeader.bV5BitCount <= 8)
1958 cColorsUsed = (1 << pbmiSrc->bmiHeader.bV5BitCount);
1959
1960 if(dwColorUse == DIB_PAL_COLORS)
1961 {
1962 RtlCopyMemory(pbmiDst->bmiColors,
1963 pbmiSrc->bmiColors,
1964 cColorsUsed * sizeof(WORD));
1965 }
1966 else
1967 {
1968 for(i = 0; i < cColorsUsed; i++)
1969 {
1970 SetBMIColor(pbmiDst, (DWORD*)pbmiSrc->bmiColors + i, i);
1971 }
1972 }
1973 }
1974 }
1975
1976 /* EOF */