8b6cf8e86d63d08955ae1540375dc09f68c87b9b
[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 BITMAPINFO *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.biWidth;
255 SourceSize.cy = ScanLines;
256
257 // Determine width of DIB
258 DIBWidth = DIB_GetDIBWidthBytes(SourceSize.cx, bmi->bmiHeader.biBitCount);
259
260 SourceBitmap = EngCreateBitmap(SourceSize,
261 DIBWidth,
262 BitmapFormat(bmi->bmiHeader.biBitCount, bmi->bmiHeader.biCompression),
263 bmi->bmiHeader.biHeight < 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(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.biHeight) - 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 /* Don't check Bits and hope we won't die */
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, (PBITMAPINFO)&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 (PBITMAPINFO)&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, (BITMAPINFO*)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 PDC Dc;
1134 HBITMAP Bmp;
1135 UINT bpp;
1136 BITMAPV5INFO bmiLocal ;
1137 NTSTATUS Status = STATUS_SUCCESS;
1138
1139 _SEH2_TRY
1140 {
1141 if(pbmi) Status = ProbeAndConvertToBitmapV5Info(&bmiLocal, pbmi, iUsage, cjMaxInitInfo);
1142 if(pjInit && (fInit == CBM_INIT)) ProbeForRead(pjInit, cjMaxBits, 1);
1143 }
1144 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1145 {
1146 Status = _SEH2_GetExceptionCode();
1147 }
1148 _SEH2_END
1149
1150 if(!NT_SUCCESS(Status))
1151 {
1152 SetLastNtError(Status);
1153 return NULL;
1154 }
1155
1156 if (!hDc) // CreateBitmap
1157 { // Should use System Bitmap DC hSystemBM, with CreateCompatibleDC for this.
1158 hDc = IntGdiCreateDC(NULL, NULL, NULL, NULL,FALSE);
1159 if (!hDc)
1160 {
1161 SetLastWin32Error(ERROR_INVALID_HANDLE);
1162 return NULL;
1163 }
1164
1165 Dc = DC_LockDc(hDc);
1166 if (!Dc)
1167 {
1168 NtGdiDeleteObjectApp(hDc);
1169 SetLastWin32Error(ERROR_INVALID_HANDLE);
1170 return NULL;
1171 }
1172 bpp = 1;
1173 Bmp = IntCreateDIBitmap(Dc, cx, cy, bpp, fInit, pjInit, pbmi ? &bmiLocal : NULL, iUsage);
1174
1175 DC_UnlockDc(Dc);
1176 NtGdiDeleteObjectApp(hDc);
1177 }
1178 else // CreateCompatibleBitmap
1179 {
1180 Dc = DC_LockDc(hDc);
1181 if (!Dc)
1182 {
1183 SetLastWin32Error(ERROR_INVALID_HANDLE);
1184 return NULL;
1185 }
1186 /* pbmi == null
1187 First create an un-initialised bitmap. The depth of the bitmap
1188 should match that of the hdc and not that supplied in bmih.
1189 */
1190 if (pbmi)
1191 bpp = bmiLocal.bmiHeader.bV5BitCount;
1192 else
1193 {
1194 if (Dc->dctype != DC_TYPE_MEMORY)
1195 bpp = Dc->ppdev->gdiinfo.cBitsPixel;
1196 else
1197 {
1198 DIBSECTION dibs;
1199 INT Count;
1200 SURFACE *psurf = Dc->dclevel.pSurface;
1201 Count = BITMAP_GetObject(psurf, sizeof(dibs), &dibs);
1202 if (!Count)
1203 bpp = 1;
1204 else
1205 {
1206 if (Count == sizeof(BITMAP))
1207 /* A device-dependent bitmap is selected in the DC */
1208 bpp = dibs.dsBm.bmBitsPixel;
1209 else
1210 /* A DIB section is selected in the DC */
1211 bpp = dibs.dsBmih.biBitCount;
1212 }
1213 }
1214 }
1215 Bmp = IntCreateDIBitmap(Dc, cx, cy, bpp, fInit, pjInit, pbmi ? &bmiLocal : NULL, iUsage);
1216 DC_UnlockDc(Dc);
1217 }
1218 return Bmp;
1219 }
1220
1221
1222 HBITMAP
1223 APIENTRY
1224 NtGdiCreateDIBSection(
1225 IN HDC hDC,
1226 IN OPTIONAL HANDLE hSection,
1227 IN DWORD dwOffset,
1228 IN LPBITMAPINFO bmi,
1229 IN DWORD Usage,
1230 IN UINT cjHeader,
1231 IN FLONG fl,
1232 IN ULONG_PTR dwColorSpace,
1233 OUT PVOID *Bits)
1234 {
1235 HBITMAP hbitmap = 0;
1236 DC *dc;
1237 BOOL bDesktopDC = FALSE;
1238
1239 if (!bmi) return hbitmap; // Make sure.
1240
1241 // If the reference hdc is null, take the desktop dc
1242 if (hDC == 0)
1243 {
1244 hDC = NtGdiCreateCompatibleDC(0);
1245 bDesktopDC = TRUE;
1246 }
1247
1248 if ((dc = DC_LockDc(hDC)))
1249 {
1250 hbitmap = DIB_CreateDIBSection(dc,
1251 (BITMAPINFO*)bmi,
1252 Usage,
1253 Bits,
1254 hSection,
1255 dwOffset,
1256 0);
1257 DC_UnlockDc(dc);
1258 }
1259 else
1260 {
1261 SetLastWin32Error(ERROR_INVALID_HANDLE);
1262 }
1263
1264 if (bDesktopDC)
1265 NtGdiDeleteObjectApp(hDC);
1266
1267 return hbitmap;
1268 }
1269
1270 HBITMAP
1271 APIENTRY
1272 DIB_CreateDIBSection(
1273 PDC dc,
1274 BITMAPINFO *bmi,
1275 UINT usage,
1276 LPVOID *bits,
1277 HANDLE section,
1278 DWORD offset,
1279 DWORD ovr_pitch)
1280 {
1281 HBITMAP res = 0;
1282 SURFACE *bmp = NULL;
1283 void *mapBits = NULL;
1284 PDC_ATTR pdcattr;
1285 HPALETTE hpal ;
1286
1287 // Fill BITMAP32 structure with DIB data
1288 BITMAPINFOHEADER *bi = &bmi->bmiHeader;
1289 INT effHeight;
1290 ULONG totalSize;
1291 BITMAP bm;
1292 SIZEL Size;
1293 RGBQUAD *lpRGB;
1294 HANDLE hSecure;
1295 DWORD dsBitfields[3] = {0};
1296 ULONG ColorCount;
1297
1298 DPRINT("format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n",
1299 bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
1300 bi->biSizeImage, bi->biClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1301
1302 /* CreateDIBSection should fail for compressed formats */
1303 if (bi->biCompression == BI_RLE4 || bi->biCompression == BI_RLE8)
1304 {
1305 return (HBITMAP)NULL;
1306 }
1307
1308 pdcattr = dc->pdcattr;
1309
1310 effHeight = bi->biHeight >= 0 ? bi->biHeight : -bi->biHeight;
1311 bm.bmType = 0;
1312 bm.bmWidth = bi->biWidth;
1313 bm.bmHeight = effHeight;
1314 bm.bmWidthBytes = ovr_pitch ? ovr_pitch : (ULONG) DIB_GetDIBWidthBytes(bm.bmWidth, bi->biBitCount);
1315
1316 bm.bmPlanes = bi->biPlanes;
1317 bm.bmBitsPixel = bi->biBitCount;
1318 bm.bmBits = NULL;
1319
1320 // Get storage location for DIB bits. Only use biSizeImage if it's valid and
1321 // we're dealing with a compressed bitmap. Otherwise, use width * height.
1322 totalSize = bi->biSizeImage && bi->biCompression != BI_RGB
1323 ? bi->biSizeImage : (ULONG)(bm.bmWidthBytes * effHeight);
1324
1325 if (section)
1326 {
1327 SYSTEM_BASIC_INFORMATION Sbi;
1328 NTSTATUS Status;
1329 DWORD mapOffset;
1330 LARGE_INTEGER SectionOffset;
1331 SIZE_T mapSize;
1332
1333 Status = ZwQuerySystemInformation(SystemBasicInformation,
1334 &Sbi,
1335 sizeof Sbi,
1336 0);
1337 if (!NT_SUCCESS(Status))
1338 {
1339 return NULL;
1340 }
1341
1342 mapOffset = offset - (offset % Sbi.AllocationGranularity);
1343 mapSize = bi->biSizeImage + (offset - mapOffset);
1344
1345 SectionOffset.LowPart = mapOffset;
1346 SectionOffset.HighPart = 0;
1347
1348 Status = ZwMapViewOfSection(section,
1349 NtCurrentProcess(),
1350 &mapBits,
1351 0,
1352 0,
1353 &SectionOffset,
1354 &mapSize,
1355 ViewShare,
1356 0,
1357 PAGE_READWRITE);
1358 if (!NT_SUCCESS(Status))
1359 {
1360 SetLastWin32Error(ERROR_INVALID_PARAMETER);
1361 return NULL;
1362 }
1363
1364 if (mapBits) bm.bmBits = (char *)mapBits + (offset - mapOffset);
1365 }
1366 else if (ovr_pitch && offset)
1367 bm.bmBits = (LPVOID) offset;
1368 else
1369 {
1370 offset = 0;
1371 bm.bmBits = EngAllocUserMem(totalSize, 0);
1372 }
1373
1374 // hSecure = MmSecureVirtualMemory(bm.bmBits, totalSize, PAGE_READWRITE);
1375 hSecure = (HANDLE)0x1; // HACK OF UNIMPLEMENTED KERNEL STUFF !!!!
1376
1377 if (usage == DIB_PAL_COLORS)
1378 {
1379 lpRGB = DIB_MapPaletteColors(dc, bmi);
1380 ColorCount = bi->biClrUsed;
1381 if (ColorCount == 0)
1382 {
1383 ColorCount = 1 << bi->biBitCount;
1384 }
1385 }
1386 else
1387 {
1388 lpRGB = bmi->bmiColors;
1389 ColorCount = 1 << bi->biBitCount;
1390 }
1391
1392 /* Set dsBitfields values */
1393 if (usage == DIB_PAL_COLORS || bi->biBitCount <= 8)
1394 {
1395 dsBitfields[0] = dsBitfields[1] = dsBitfields[2] = 0;
1396 }
1397 else if (bi->biCompression == BI_RGB)
1398 {
1399 switch (bi->biBitCount)
1400 {
1401 case 15:
1402 dsBitfields[0] = 0x7c00;
1403 dsBitfields[1] = 0x03e0;
1404 dsBitfields[2] = 0x001f;
1405 break;
1406
1407 case 16:
1408 dsBitfields[0] = 0xF800;
1409 dsBitfields[1] = 0x07e0;
1410 dsBitfields[2] = 0x001f;
1411 break;
1412
1413 case 24:
1414 case 32:
1415 dsBitfields[0] = 0xff0000;
1416 dsBitfields[1] = 0x00ff00;
1417 dsBitfields[2] = 0x0000ff;
1418 break;
1419 }
1420 }
1421 else
1422 {
1423 dsBitfields[0] = ((DWORD*)bmi->bmiColors)[0];
1424 dsBitfields[1] = ((DWORD*)bmi->bmiColors)[1];
1425 dsBitfields[2] = ((DWORD*)bmi->bmiColors)[2];
1426 }
1427
1428 // Create Device Dependent Bitmap and add DIB pointer
1429 Size.cx = bm.bmWidth;
1430 Size.cy = abs(bm.bmHeight);
1431 res = GreCreateBitmapEx(bm.bmWidth,
1432 abs(bm.bmHeight),
1433 bm.bmWidthBytes,
1434 BitmapFormat(bi->biBitCount * bi->biPlanes, bi->biCompression),
1435 BMF_DONTCACHE | BMF_USERMEM | BMF_NOZEROINIT |
1436 (bi->biHeight < 0 ? BMF_TOPDOWN : 0),
1437 bi->biSizeImage,
1438 bm.bmBits);
1439 if (!res)
1440 {
1441 if (lpRGB != bmi->bmiColors)
1442 {
1443 ExFreePoolWithTag(lpRGB, TAG_COLORMAP);
1444 }
1445 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
1446 return NULL;
1447 }
1448 bmp = SURFACE_LockSurface(res);
1449 if (NULL == bmp)
1450 {
1451 if (lpRGB != bmi->bmiColors)
1452 {
1453 ExFreePoolWithTag(lpRGB, TAG_COLORMAP);
1454 }
1455 SetLastWin32Error(ERROR_INVALID_HANDLE);
1456 GreDeleteObject(res);
1457 return NULL;
1458 }
1459
1460 /* WINE NOTE: WINE makes use of a colormap, which is a color translation
1461 table between the DIB and the X physical device. Obviously,
1462 this is left out of the ReactOS implementation. Instead,
1463 we call NtGdiSetDIBColorTable. */
1464 if (bi->biBitCount <= 8)
1465 {
1466 bi->biClrUsed = 1 << bi->biBitCount;
1467 }
1468 else
1469 {
1470 bi->biClrUsed = 0;
1471 }
1472
1473 bmp->hDIBSection = section;
1474 bmp->hSecure = hSecure;
1475 bmp->dwOffset = offset;
1476 bmp->flags = API_BITMAP;
1477 bmp->dsBitfields[0] = dsBitfields[0];
1478 bmp->dsBitfields[1] = dsBitfields[1];
1479 bmp->dsBitfields[2] = dsBitfields[2];
1480 bmp->biClrUsed = bi->biClrUsed;
1481 bmp->biClrImportant = bi->biClrImportant;
1482
1483 if (bi->biClrUsed != 0)
1484 {
1485 hpal = PALETTE_AllocPaletteIndexedRGB(ColorCount, lpRGB);
1486 }
1487 else
1488 {
1489 hpal = PALETTE_AllocPalette(PAL_BITFIELDS, 0, NULL,
1490 dsBitfields[0],
1491 dsBitfields[1],
1492 dsBitfields[2]);
1493 }
1494
1495 bmp->ppal = PALETTE_ShareLockPalette(hpal);
1496 /* Lazy delete hpal, it will be freed at surface release */
1497 GreDeleteObject(hpal);
1498
1499 // Clean up in case of errors
1500 if (!res || !bmp || !bm.bmBits)
1501 {
1502 DPRINT("got an error res=%08x, bmp=%p, bm.bmBits=%p\n", res, bmp, bm.bmBits);
1503 if (bm.bmBits)
1504 {
1505 // MmUnsecureVirtualMemory(hSecure); // FIXME: Implement this!
1506 if (section)
1507 {
1508 ZwUnmapViewOfSection(NtCurrentProcess(), mapBits);
1509 bm.bmBits = NULL;
1510 }
1511 else
1512 if (!offset)
1513 EngFreeUserMem(bm.bmBits), bm.bmBits = NULL;
1514 }
1515
1516 if (bmp)
1517 bmp = NULL;
1518
1519 if (res)
1520 {
1521 SURFACE_FreeSurfaceByHandle(res);
1522 res = 0;
1523 }
1524 }
1525
1526 if (lpRGB != bmi->bmiColors)
1527 {
1528 ExFreePoolWithTag(lpRGB, TAG_COLORMAP);
1529 }
1530
1531 if (bmp)
1532 {
1533 SURFACE_UnlockSurface(bmp);
1534 }
1535
1536 // Return BITMAP handle and storage location
1537 if (NULL != bm.bmBits && NULL != bits)
1538 {
1539 *bits = bm.bmBits;
1540 }
1541
1542 if (res) pdcattr->ulDirty_ |= DC_DIBSECTION;
1543
1544 return res;
1545 }
1546
1547 /***********************************************************************
1548 * DIB_GetDIBWidthBytes
1549 *
1550 * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
1551 * http://www.microsoft.com/msdn/sdk/platforms/doc/sdk/win32/struc/src/str01.htm
1552 * 11/16/1999 (RJJ) lifted from wine
1553 */
1554 INT FASTCALL DIB_GetDIBWidthBytes(INT width, INT depth)
1555 {
1556 return ((width * depth + 31) & ~31) >> 3;
1557 }
1558
1559 /***********************************************************************
1560 * DIB_GetDIBImageBytes
1561 *
1562 * Return the number of bytes used to hold the image in a DIB bitmap.
1563 * 11/16/1999 (RJJ) lifted from wine
1564 */
1565
1566 INT APIENTRY DIB_GetDIBImageBytes(INT width, INT height, INT depth)
1567 {
1568 return DIB_GetDIBWidthBytes(width, depth) * (height < 0 ? -height : height);
1569 }
1570
1571 /***********************************************************************
1572 * DIB_BitmapInfoSize
1573 *
1574 * Return the size of the bitmap info structure including color table.
1575 * 11/16/1999 (RJJ) lifted from wine
1576 */
1577
1578 INT FASTCALL DIB_BitmapInfoSize(const BITMAPINFO * info, WORD coloruse)
1579 {
1580 int colors;
1581
1582 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
1583 {
1584 BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)info;
1585 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
1586 return sizeof(BITMAPCOREHEADER) + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
1587 }
1588 else /* assume BITMAPINFOHEADER */
1589 {
1590 colors = info->bmiHeader.biClrUsed;
1591 if (!colors && (info->bmiHeader.biBitCount <= 8)) colors = 1 << info->bmiHeader.biBitCount;
1592 return info->bmiHeader.biSize + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
1593 }
1594 }
1595
1596 RGBQUAD *
1597 FASTCALL
1598 DIB_MapPaletteColors(PDC dc, CONST BITMAPINFO* lpbmi)
1599 {
1600 RGBQUAD *lpRGB;
1601 ULONG nNumColors,i;
1602 USHORT *lpIndex;
1603 PPALETTE palGDI;
1604
1605 palGDI = PALETTE_LockPalette(dc->dclevel.hpal);
1606
1607 if (NULL == palGDI)
1608 {
1609 return NULL;
1610 }
1611
1612 if (palGDI->Mode != PAL_INDEXED)
1613 {
1614 PALETTE_UnlockPalette(palGDI);
1615 return NULL;
1616 }
1617
1618 nNumColors = 1 << lpbmi->bmiHeader.biBitCount;
1619 if (lpbmi->bmiHeader.biClrUsed)
1620 {
1621 nNumColors = min(nNumColors, lpbmi->bmiHeader.biClrUsed);
1622 }
1623
1624 lpRGB = (RGBQUAD *)ExAllocatePoolWithTag(PagedPool, sizeof(RGBQUAD) * nNumColors, TAG_COLORMAP);
1625 if (lpRGB == NULL)
1626 {
1627 PALETTE_UnlockPalette(palGDI);
1628 return NULL;
1629 }
1630
1631 lpIndex = (USHORT *)&lpbmi->bmiColors[0];
1632
1633 for (i = 0; i < nNumColors; i++)
1634 {
1635 if (*lpIndex < palGDI->NumColors)
1636 {
1637 lpRGB[i].rgbRed = palGDI->IndexedColors[*lpIndex].peRed;
1638 lpRGB[i].rgbGreen = palGDI->IndexedColors[*lpIndex].peGreen;
1639 lpRGB[i].rgbBlue = palGDI->IndexedColors[*lpIndex].peBlue;
1640 }
1641 else
1642 {
1643 lpRGB[i].rgbRed = 0;
1644 lpRGB[i].rgbGreen = 0;
1645 lpRGB[i].rgbBlue = 0;
1646 }
1647 lpRGB[i].rgbReserved = 0;
1648 lpIndex++;
1649 }
1650 PALETTE_UnlockPalette(palGDI);
1651
1652 return lpRGB;
1653 }
1654
1655 HPALETTE
1656 FASTCALL
1657 BuildDIBPalette(CONST BITMAPINFO *bmi, PINT paletteType)
1658 {
1659 BYTE bits;
1660 ULONG ColorCount;
1661 HPALETTE hPal;
1662 ULONG RedMask, GreenMask, BlueMask;
1663 PDWORD pdwColors = (PDWORD)((PBYTE)bmi + bmi->bmiHeader.biSize);
1664
1665 // Determine Bits Per Pixel
1666 bits = bmi->bmiHeader.biBitCount;
1667
1668 // Determine paletteType from Bits Per Pixel
1669 if (bits <= 8)
1670 {
1671 *paletteType = PAL_INDEXED;
1672 RedMask = GreenMask = BlueMask = 0;
1673 }
1674 else if (bmi->bmiHeader.biCompression == BI_BITFIELDS)
1675 {
1676 *paletteType = PAL_BITFIELDS;
1677 RedMask = pdwColors[0];
1678 GreenMask = pdwColors[1];
1679 BlueMask = pdwColors[2];
1680 }
1681 else if (bits == 15)
1682 {
1683 *paletteType = PAL_BITFIELDS;
1684 RedMask = 0x7c00;
1685 GreenMask = 0x03e0;
1686 BlueMask = 0x001f;
1687 }
1688 else if (bits == 16)
1689 {
1690 *paletteType = PAL_BITFIELDS;
1691 RedMask = 0xF800;
1692 GreenMask = 0x07e0;
1693 BlueMask = 0x001f;
1694 }
1695 else
1696 {
1697 *paletteType = PAL_BGR;
1698 RedMask = 0xff0000;
1699 GreenMask = 0x00ff00;
1700 BlueMask = 0x0000ff;
1701 }
1702
1703 if (bmi->bmiHeader.biClrUsed == 0)
1704 {
1705 ColorCount = 1 << bmi->bmiHeader.biBitCount;
1706 }
1707 else
1708 {
1709 ColorCount = bmi->bmiHeader.biClrUsed;
1710 }
1711
1712 if (PAL_INDEXED == *paletteType)
1713 {
1714 hPal = PALETTE_AllocPaletteIndexedRGB(ColorCount, (RGBQUAD*)pdwColors);
1715 }
1716 else
1717 {
1718 hPal = PALETTE_AllocPalette(*paletteType, ColorCount,
1719 NULL,
1720 RedMask, GreenMask, BlueMask);
1721 }
1722
1723 return hPal;
1724 }
1725
1726 FORCEINLINE
1727 DWORD
1728 GetBMIColor(CONST BITMAPINFO* pbmi, INT i)
1729 {
1730 DWORD dwRet = 0;
1731 INT size;
1732 if(pbmi->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
1733 {
1734 /* BITMAPCOREINFO holds RGBTRIPLE values */
1735 size = sizeof(RGBTRIPLE);
1736 }
1737 else
1738 {
1739 size = sizeof(RGBQUAD);
1740 }
1741 memcpy(&dwRet, (PBYTE)pbmi + pbmi->bmiHeader.biSize + i*size, size);
1742 return dwRet;
1743 }
1744
1745 FORCEINLINE
1746 VOID
1747 SetBMIColor(CONST BITMAPINFO* pbmi, DWORD* color, INT i)
1748 {
1749 PVOID pvColors = ((PBYTE)pbmi + pbmi->bmiHeader.biSize);
1750 if(pbmi->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
1751 {
1752 RGBTRIPLE *pColor = pvColors;
1753 pColor[i] = *(RGBTRIPLE*)color;
1754 }
1755 else
1756 {
1757 RGBQUAD *pColor = pvColors;
1758 pColor[i] = *(RGBQUAD*)color;
1759 }
1760 }
1761
1762 NTSTATUS
1763 FASTCALL
1764 ProbeAndConvertToBitmapV5Info(
1765 OUT PBITMAPV5INFO pbmiDst,
1766 IN CONST BITMAPINFO* pbmiUnsafe,
1767 IN DWORD dwColorUse,
1768 IN UINT MaxSize)
1769 {
1770 DWORD dwSize;
1771 ULONG ulWidthBytes;
1772 PBITMAPV5HEADER pbmhDst = &pbmiDst->bmiHeader;
1773
1774 /* Get the size and probe */
1775 ProbeForRead(&pbmiUnsafe->bmiHeader.biSize, sizeof(DWORD), 1);
1776 dwSize = pbmiUnsafe->bmiHeader.biSize;
1777 /* At least dwSize bytes must be valids */
1778 ProbeForRead(pbmiUnsafe, max(dwSize, MaxSize), 1);
1779
1780 /* Check the size */
1781 // FIXME: are intermediate sizes allowed? As what are they interpreted?
1782 // make sure we don't use a too big dwSize later
1783 if (dwSize != sizeof(BITMAPCOREHEADER) &&
1784 dwSize != sizeof(BITMAPINFOHEADER) &&
1785 dwSize != sizeof(BITMAPV4HEADER) &&
1786 dwSize != sizeof(BITMAPV5HEADER))
1787 {
1788 return STATUS_INVALID_PARAMETER;
1789 }
1790
1791 if (dwSize == sizeof(BITMAPCOREHEADER))
1792 {
1793 PBITMAPCOREHEADER pbch = (PBITMAPCOREHEADER)pbmiUnsafe;
1794
1795 /* Manually copy the fields that are present */
1796 pbmhDst->bV5Width = pbch->bcWidth;
1797 pbmhDst->bV5Height = pbch->bcHeight;
1798 pbmhDst->bV5Planes = pbch->bcPlanes;
1799 pbmhDst->bV5BitCount = pbch->bcBitCount;
1800
1801 /* Set some default values */
1802 pbmhDst->bV5Compression = BI_RGB;
1803 pbmhDst->bV5SizeImage = 0;
1804 pbmhDst->bV5XPelsPerMeter = 72;
1805 pbmhDst->bV5YPelsPerMeter = 72;
1806 pbmhDst->bV5ClrUsed = 0;
1807 pbmhDst->bV5ClrImportant = 0;
1808 }
1809 else
1810 {
1811 /* Copy valid fields */
1812 memcpy(pbmiDst, pbmiUnsafe, dwSize);
1813
1814 if(dwSize < sizeof(BITMAPV5HEADER))
1815 {
1816 /* Zero out the rest of the V5 header */
1817 memset((char*)pbmiDst + dwSize, 0, sizeof(BITMAPV5HEADER) - dwSize);
1818 }
1819 }
1820 pbmhDst->bV5Size = sizeof(BITMAPV5HEADER);
1821
1822
1823 if (dwSize < sizeof(BITMAPV4HEADER))
1824 {
1825 if (pbmhDst->bV5Compression == BI_BITFIELDS)
1826 {
1827 pbmhDst->bV5RedMask = GetBMIColor(pbmiUnsafe, 0);
1828 pbmhDst->bV5GreenMask = GetBMIColor(pbmiUnsafe, 1);
1829 pbmhDst->bV5BlueMask = GetBMIColor(pbmiUnsafe, 2);
1830 pbmhDst->bV5AlphaMask = 0;
1831 pbmhDst->bV5ClrUsed = 0;
1832 }
1833
1834 // pbmhDst->bV5CSType;
1835 // pbmhDst->bV5Endpoints;
1836 // pbmhDst->bV5GammaRed;
1837 // pbmhDst->bV5GammaGreen;
1838 // pbmhDst->bV5GammaBlue;
1839 }
1840
1841 if (dwSize < sizeof(BITMAPV5HEADER))
1842 {
1843 // pbmhDst->bV5Intent;
1844 // pbmhDst->bV5ProfileData;
1845 // pbmhDst->bV5ProfileSize;
1846 // pbmhDst->bV5Reserved;
1847 }
1848
1849 ulWidthBytes = ((pbmhDst->bV5Width * pbmhDst->bV5Planes *
1850 pbmhDst->bV5BitCount + 31) & ~31) / 8;
1851
1852 if (pbmhDst->bV5SizeImage == 0)
1853 pbmhDst->bV5SizeImage = abs(ulWidthBytes * pbmhDst->bV5Height);
1854
1855 if (pbmhDst->bV5ClrUsed == 0)
1856 {
1857 switch(pbmhDst->bV5BitCount)
1858 {
1859 case 1:
1860 pbmhDst->bV5ClrUsed = 2;
1861 break;
1862 case 4:
1863 pbmhDst->bV5ClrUsed = 16;
1864 break;
1865 case 8:
1866 pbmhDst->bV5ClrUsed = 256;
1867 break;
1868 default:
1869 pbmhDst->bV5ClrUsed = 0;
1870 break;
1871 }
1872 }
1873
1874 if (pbmhDst->bV5Planes != 1)
1875 {
1876 return STATUS_INVALID_PARAMETER;
1877 }
1878
1879 if (pbmhDst->bV5BitCount != 0 && pbmhDst->bV5BitCount != 1 &&
1880 pbmhDst->bV5BitCount != 4 && pbmhDst->bV5BitCount != 8 &&
1881 pbmhDst->bV5BitCount != 16 && pbmhDst->bV5BitCount != 24 &&
1882 pbmhDst->bV5BitCount != 32)
1883 {
1884 DPRINT("Invalid bit count: %d\n", pbmhDst->bV5BitCount);
1885 return STATUS_INVALID_PARAMETER;
1886 }
1887
1888 if ((pbmhDst->bV5BitCount == 0 &&
1889 pbmhDst->bV5Compression != BI_JPEG && pbmhDst->bV5Compression != BI_PNG))
1890 {
1891 DPRINT("Bit count 0 is invalid for compression %d.\n", pbmhDst->bV5Compression);
1892 return STATUS_INVALID_PARAMETER;
1893 }
1894
1895 if (pbmhDst->bV5Compression == BI_BITFIELDS &&
1896 pbmhDst->bV5BitCount != 16 && pbmhDst->bV5BitCount != 32)
1897 {
1898 DPRINT("Bit count %d is invalid for compression BI_BITFIELDS.\n", pbmhDst->bV5BitCount);
1899 return STATUS_INVALID_PARAMETER;
1900 }
1901
1902 /* Copy Colors */
1903 if(pbmhDst->bV5ClrUsed)
1904 {
1905 INT i;
1906 if(dwColorUse == DIB_PAL_COLORS)
1907 {
1908 RtlCopyMemory(pbmiDst->bmiColors,
1909 pbmiUnsafe->bmiColors,
1910 pbmhDst->bV5ClrUsed * sizeof(WORD));
1911 }
1912 else
1913 {
1914 for(i = 0; i < pbmhDst->bV5ClrUsed; i++)
1915 {
1916 ((DWORD*)pbmiDst->bmiColors)[i] = GetBMIColor(pbmiUnsafe, i);
1917 }
1918 }
1919 }
1920
1921 return STATUS_SUCCESS;
1922 }
1923
1924 VOID
1925 FASTCALL
1926 GetBMIFromBitmapV5Info(IN PBITMAPV5INFO pbmiSrc,
1927 OUT PBITMAPINFO pbmiDst,
1928 IN DWORD dwColorUse)
1929 {
1930 if(pbmiDst->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
1931 {
1932 /* Manually set value */
1933 BITMAPCOREHEADER* pbmhCore = (BITMAPCOREHEADER*)&pbmiDst->bmiHeader;
1934 pbmhCore->bcWidth = pbmiSrc->bmiHeader.bV5Width;
1935 pbmhCore->bcHeight = pbmiSrc->bmiHeader.bV5Height;
1936 pbmhCore->bcPlanes = pbmiSrc->bmiHeader.bV5Planes;
1937 pbmhCore->bcBitCount = pbmiSrc->bmiHeader.bV5BitCount;
1938 }
1939 else
1940 {
1941 /* Copy valid Fields, keep bmiHeader.biSize safe */
1942 RtlCopyMemory(&pbmiDst->bmiHeader.biWidth,
1943 &pbmiSrc->bmiHeader.bV5Width,
1944 pbmiDst->bmiHeader.biSize - sizeof(DWORD));
1945 }
1946 if((pbmiDst->bmiHeader.biSize < sizeof(BITMAPV4HEADER)) &&
1947 (pbmiSrc->bmiHeader.bV5Compression == BI_BITFIELDS))
1948 {
1949 /* Masks are already set in V4 and V5 headers */
1950 SetBMIColor(pbmiDst, &pbmiSrc->bmiHeader.bV5RedMask, 0);
1951 SetBMIColor(pbmiDst, &pbmiSrc->bmiHeader.bV5GreenMask, 1);
1952 SetBMIColor(pbmiDst, &pbmiSrc->bmiHeader.bV5BlueMask, 2);
1953 }
1954 else
1955 {
1956 INT i;
1957 ULONG cColorsUsed;
1958
1959 cColorsUsed = pbmiSrc->bmiHeader.bV5ClrUsed;
1960 if (cColorsUsed == 0 && pbmiSrc->bmiHeader.bV5BitCount <= 8)
1961 cColorsUsed = (1 << pbmiSrc->bmiHeader.bV5BitCount);
1962
1963 if(dwColorUse == DIB_PAL_COLORS)
1964 {
1965 RtlCopyMemory(pbmiDst->bmiColors,
1966 pbmiSrc->bmiColors,
1967 cColorsUsed * sizeof(WORD));
1968 }
1969 else
1970 {
1971 for(i = 0; i < cColorsUsed; i++)
1972 {
1973 SetBMIColor(pbmiDst, (DWORD*)pbmiSrc->bmiColors + i, i);
1974 }
1975 }
1976 }
1977 }
1978
1979 /* EOF */