Sync with trunk (r48123)
[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 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, (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 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
1235 if (!bmi) return hbitmap; // Make sure.
1236
1237 // If the reference hdc is null, take the desktop dc
1238 if (hDC == 0)
1239 {
1240 hDC = NtGdiCreateCompatibleDC(0);
1241 bDesktopDC = TRUE;
1242 }
1243
1244 if ((dc = DC_LockDc(hDC)))
1245 {
1246 hbitmap = DIB_CreateDIBSection(dc,
1247 (BITMAPINFO*)bmi,
1248 Usage,
1249 Bits,
1250 hSection,
1251 dwOffset,
1252 0);
1253 DC_UnlockDc(dc);
1254 }
1255 else
1256 {
1257 SetLastWin32Error(ERROR_INVALID_HANDLE);
1258 }
1259
1260 if (bDesktopDC)
1261 NtGdiDeleteObjectApp(hDC);
1262
1263 return hbitmap;
1264 }
1265
1266 HBITMAP
1267 APIENTRY
1268 DIB_CreateDIBSection(
1269 PDC dc,
1270 BITMAPINFO *bmi,
1271 UINT usage,
1272 LPVOID *bits,
1273 HANDLE section,
1274 DWORD offset,
1275 DWORD ovr_pitch)
1276 {
1277 HBITMAP res = 0;
1278 SURFACE *bmp = NULL;
1279 void *mapBits = NULL;
1280 HPALETTE hpal ;
1281
1282 // Fill BITMAP32 structure with DIB data
1283 BITMAPINFOHEADER *bi = &bmi->bmiHeader;
1284 INT effHeight;
1285 ULONG totalSize;
1286 BITMAP bm;
1287 SIZEL Size;
1288 RGBQUAD *lpRGB;
1289 HANDLE hSecure;
1290 DWORD dsBitfields[3] = {0};
1291 ULONG ColorCount;
1292
1293 DPRINT("format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n",
1294 bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
1295 bi->biSizeImage, bi->biClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1296
1297 /* CreateDIBSection should fail for compressed formats */
1298 if (bi->biCompression == BI_RLE4 || bi->biCompression == BI_RLE8)
1299 {
1300 return (HBITMAP)NULL;
1301 }
1302
1303 effHeight = bi->biHeight >= 0 ? bi->biHeight : -bi->biHeight;
1304 bm.bmType = 0;
1305 bm.bmWidth = bi->biWidth;
1306 bm.bmHeight = effHeight;
1307 bm.bmWidthBytes = ovr_pitch ? ovr_pitch : (ULONG) DIB_GetDIBWidthBytes(bm.bmWidth, bi->biBitCount);
1308
1309 bm.bmPlanes = bi->biPlanes;
1310 bm.bmBitsPixel = bi->biBitCount;
1311 bm.bmBits = NULL;
1312
1313 // Get storage location for DIB bits. Only use biSizeImage if it's valid and
1314 // we're dealing with a compressed bitmap. Otherwise, use width * height.
1315 totalSize = bi->biSizeImage && bi->biCompression != BI_RGB
1316 ? bi->biSizeImage : (ULONG)(bm.bmWidthBytes * effHeight);
1317
1318 if (section)
1319 {
1320 SYSTEM_BASIC_INFORMATION Sbi;
1321 NTSTATUS Status;
1322 DWORD mapOffset;
1323 LARGE_INTEGER SectionOffset;
1324 SIZE_T mapSize;
1325
1326 Status = ZwQuerySystemInformation(SystemBasicInformation,
1327 &Sbi,
1328 sizeof Sbi,
1329 0);
1330 if (!NT_SUCCESS(Status))
1331 {
1332 return NULL;
1333 }
1334
1335 mapOffset = offset - (offset % Sbi.AllocationGranularity);
1336 mapSize = bi->biSizeImage + (offset - mapOffset);
1337
1338 SectionOffset.LowPart = mapOffset;
1339 SectionOffset.HighPart = 0;
1340
1341 Status = ZwMapViewOfSection(section,
1342 NtCurrentProcess(),
1343 &mapBits,
1344 0,
1345 0,
1346 &SectionOffset,
1347 &mapSize,
1348 ViewShare,
1349 0,
1350 PAGE_READWRITE);
1351 if (!NT_SUCCESS(Status))
1352 {
1353 SetLastWin32Error(ERROR_INVALID_PARAMETER);
1354 return NULL;
1355 }
1356
1357 if (mapBits) bm.bmBits = (char *)mapBits + (offset - mapOffset);
1358 }
1359 else if (ovr_pitch && offset)
1360 bm.bmBits = (LPVOID) offset;
1361 else
1362 {
1363 offset = 0;
1364 bm.bmBits = EngAllocUserMem(totalSize, 0);
1365 }
1366
1367 // hSecure = MmSecureVirtualMemory(bm.bmBits, totalSize, PAGE_READWRITE);
1368 hSecure = (HANDLE)0x1; // HACK OF UNIMPLEMENTED KERNEL STUFF !!!!
1369
1370 if (usage == DIB_PAL_COLORS)
1371 {
1372 lpRGB = DIB_MapPaletteColors(dc, bmi);
1373 ColorCount = bi->biClrUsed;
1374 if (ColorCount == 0)
1375 {
1376 ColorCount = 1 << bi->biBitCount;
1377 }
1378 }
1379 else
1380 {
1381 lpRGB = bmi->bmiColors;
1382 ColorCount = 1 << bi->biBitCount;
1383 }
1384
1385 /* Set dsBitfields values */
1386 if (usage == DIB_PAL_COLORS || bi->biBitCount <= 8)
1387 {
1388 dsBitfields[0] = dsBitfields[1] = dsBitfields[2] = 0;
1389 }
1390 else if (bi->biCompression == BI_RGB)
1391 {
1392 switch (bi->biBitCount)
1393 {
1394 case 15:
1395 dsBitfields[0] = 0x7c00;
1396 dsBitfields[1] = 0x03e0;
1397 dsBitfields[2] = 0x001f;
1398 break;
1399
1400 case 16:
1401 dsBitfields[0] = 0xF800;
1402 dsBitfields[1] = 0x07e0;
1403 dsBitfields[2] = 0x001f;
1404 break;
1405
1406 case 24:
1407 case 32:
1408 dsBitfields[0] = 0xff0000;
1409 dsBitfields[1] = 0x00ff00;
1410 dsBitfields[2] = 0x0000ff;
1411 break;
1412 }
1413 }
1414 else
1415 {
1416 dsBitfields[0] = ((DWORD*)bmi->bmiColors)[0];
1417 dsBitfields[1] = ((DWORD*)bmi->bmiColors)[1];
1418 dsBitfields[2] = ((DWORD*)bmi->bmiColors)[2];
1419 }
1420
1421 // Create Device Dependent Bitmap and add DIB pointer
1422 Size.cx = bm.bmWidth;
1423 Size.cy = abs(bm.bmHeight);
1424 res = GreCreateBitmapEx(bm.bmWidth,
1425 abs(bm.bmHeight),
1426 bm.bmWidthBytes,
1427 BitmapFormat(bi->biBitCount * bi->biPlanes, bi->biCompression),
1428 BMF_DONTCACHE | BMF_USERMEM | BMF_NOZEROINIT |
1429 (bi->biHeight < 0 ? BMF_TOPDOWN : 0),
1430 bi->biSizeImage,
1431 bm.bmBits);
1432 if (!res)
1433 {
1434 if (lpRGB != bmi->bmiColors)
1435 {
1436 ExFreePoolWithTag(lpRGB, TAG_COLORMAP);
1437 }
1438 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
1439 return NULL;
1440 }
1441 bmp = SURFACE_LockSurface(res);
1442 if (NULL == bmp)
1443 {
1444 if (lpRGB != bmi->bmiColors)
1445 {
1446 ExFreePoolWithTag(lpRGB, TAG_COLORMAP);
1447 }
1448 SetLastWin32Error(ERROR_INVALID_HANDLE);
1449 GreDeleteObject(res);
1450 return NULL;
1451 }
1452
1453 /* WINE NOTE: WINE makes use of a colormap, which is a color translation
1454 table between the DIB and the X physical device. Obviously,
1455 this is left out of the ReactOS implementation. Instead,
1456 we call NtGdiSetDIBColorTable. */
1457 if (bi->biBitCount <= 8)
1458 {
1459 bi->biClrUsed = 1 << bi->biBitCount;
1460 }
1461 else
1462 {
1463 bi->biClrUsed = 0;
1464 }
1465
1466 bmp->hDIBSection = section;
1467 bmp->hSecure = hSecure;
1468 bmp->dwOffset = offset;
1469 bmp->flags = API_BITMAP;
1470 bmp->dsBitfields[0] = dsBitfields[0];
1471 bmp->dsBitfields[1] = dsBitfields[1];
1472 bmp->dsBitfields[2] = dsBitfields[2];
1473 bmp->biClrUsed = bi->biClrUsed;
1474 bmp->biClrImportant = bi->biClrImportant;
1475
1476 if (bi->biClrUsed != 0)
1477 {
1478 hpal = PALETTE_AllocPaletteIndexedRGB(ColorCount, lpRGB);
1479 }
1480 else
1481 {
1482 hpal = PALETTE_AllocPalette(PAL_BITFIELDS, 0, NULL,
1483 dsBitfields[0],
1484 dsBitfields[1],
1485 dsBitfields[2]);
1486 }
1487
1488 bmp->ppal = PALETTE_ShareLockPalette(hpal);
1489 /* Lazy delete hpal, it will be freed at surface release */
1490 GreDeleteObject(hpal);
1491
1492 // Clean up in case of errors
1493 if (!res || !bmp || !bm.bmBits)
1494 {
1495 DPRINT("got an error res=%08x, bmp=%p, bm.bmBits=%p\n", res, bmp, bm.bmBits);
1496 if (bm.bmBits)
1497 {
1498 // MmUnsecureVirtualMemory(hSecure); // FIXME: Implement this!
1499 if (section)
1500 {
1501 ZwUnmapViewOfSection(NtCurrentProcess(), mapBits);
1502 bm.bmBits = NULL;
1503 }
1504 else
1505 if (!offset)
1506 EngFreeUserMem(bm.bmBits), bm.bmBits = NULL;
1507 }
1508
1509 if (bmp)
1510 bmp = NULL;
1511
1512 if (res)
1513 {
1514 SURFACE_FreeSurfaceByHandle(res);
1515 res = 0;
1516 }
1517 }
1518
1519 if (lpRGB != bmi->bmiColors)
1520 {
1521 ExFreePoolWithTag(lpRGB, TAG_COLORMAP);
1522 }
1523
1524 if (bmp)
1525 {
1526 SURFACE_UnlockSurface(bmp);
1527 }
1528
1529 // Return BITMAP handle and storage location
1530 if (NULL != bm.bmBits && NULL != bits)
1531 {
1532 *bits = bm.bmBits;
1533 }
1534
1535 return res;
1536 }
1537
1538 /***********************************************************************
1539 * DIB_GetDIBWidthBytes
1540 *
1541 * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
1542 * http://www.microsoft.com/msdn/sdk/platforms/doc/sdk/win32/struc/src/str01.htm
1543 * 11/16/1999 (RJJ) lifted from wine
1544 */
1545 INT FASTCALL DIB_GetDIBWidthBytes(INT width, INT depth)
1546 {
1547 return ((width * depth + 31) & ~31) >> 3;
1548 }
1549
1550 /***********************************************************************
1551 * DIB_GetDIBImageBytes
1552 *
1553 * Return the number of bytes used to hold the image in a DIB bitmap.
1554 * 11/16/1999 (RJJ) lifted from wine
1555 */
1556
1557 INT APIENTRY DIB_GetDIBImageBytes(INT width, INT height, INT depth)
1558 {
1559 return DIB_GetDIBWidthBytes(width, depth) * (height < 0 ? -height : height);
1560 }
1561
1562 /***********************************************************************
1563 * DIB_BitmapInfoSize
1564 *
1565 * Return the size of the bitmap info structure including color table.
1566 * 11/16/1999 (RJJ) lifted from wine
1567 */
1568
1569 INT FASTCALL DIB_BitmapInfoSize(const BITMAPINFO * info, WORD coloruse)
1570 {
1571 int colors;
1572
1573 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
1574 {
1575 BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)info;
1576 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
1577 return sizeof(BITMAPCOREHEADER) + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
1578 }
1579 else /* assume BITMAPINFOHEADER */
1580 {
1581 colors = info->bmiHeader.biClrUsed;
1582 if (!colors && (info->bmiHeader.biBitCount <= 8)) colors = 1 << info->bmiHeader.biBitCount;
1583 return info->bmiHeader.biSize + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
1584 }
1585 }
1586
1587 RGBQUAD *
1588 FASTCALL
1589 DIB_MapPaletteColors(PDC dc, CONST BITMAPINFO* lpbmi)
1590 {
1591 RGBQUAD *lpRGB;
1592 ULONG nNumColors,i;
1593 USHORT *lpIndex;
1594 PPALETTE palGDI;
1595
1596 palGDI = PALETTE_LockPalette(dc->dclevel.hpal);
1597
1598 if (NULL == palGDI)
1599 {
1600 return NULL;
1601 }
1602
1603 if (palGDI->Mode != PAL_INDEXED)
1604 {
1605 PALETTE_UnlockPalette(palGDI);
1606 return NULL;
1607 }
1608
1609 nNumColors = 1 << lpbmi->bmiHeader.biBitCount;
1610 if (lpbmi->bmiHeader.biClrUsed)
1611 {
1612 nNumColors = min(nNumColors, lpbmi->bmiHeader.biClrUsed);
1613 }
1614
1615 lpRGB = (RGBQUAD *)ExAllocatePoolWithTag(PagedPool, sizeof(RGBQUAD) * nNumColors, TAG_COLORMAP);
1616 if (lpRGB == NULL)
1617 {
1618 PALETTE_UnlockPalette(palGDI);
1619 return NULL;
1620 }
1621
1622 lpIndex = (USHORT *)&lpbmi->bmiColors[0];
1623
1624 for (i = 0; i < nNumColors; i++)
1625 {
1626 if (*lpIndex < palGDI->NumColors)
1627 {
1628 lpRGB[i].rgbRed = palGDI->IndexedColors[*lpIndex].peRed;
1629 lpRGB[i].rgbGreen = palGDI->IndexedColors[*lpIndex].peGreen;
1630 lpRGB[i].rgbBlue = palGDI->IndexedColors[*lpIndex].peBlue;
1631 }
1632 else
1633 {
1634 lpRGB[i].rgbRed = 0;
1635 lpRGB[i].rgbGreen = 0;
1636 lpRGB[i].rgbBlue = 0;
1637 }
1638 lpRGB[i].rgbReserved = 0;
1639 lpIndex++;
1640 }
1641 PALETTE_UnlockPalette(palGDI);
1642
1643 return lpRGB;
1644 }
1645
1646 HPALETTE
1647 FASTCALL
1648 BuildDIBPalette(CONST BITMAPINFO *bmi, PINT paletteType)
1649 {
1650 BYTE bits;
1651 ULONG ColorCount;
1652 HPALETTE hPal;
1653 ULONG RedMask, GreenMask, BlueMask;
1654 PDWORD pdwColors = (PDWORD)((PBYTE)bmi + bmi->bmiHeader.biSize);
1655
1656 // Determine Bits Per Pixel
1657 bits = bmi->bmiHeader.biBitCount;
1658
1659 // Determine paletteType from Bits Per Pixel
1660 if (bits <= 8)
1661 {
1662 *paletteType = PAL_INDEXED;
1663 RedMask = GreenMask = BlueMask = 0;
1664 }
1665 else if (bmi->bmiHeader.biCompression == BI_BITFIELDS)
1666 {
1667 *paletteType = PAL_BITFIELDS;
1668 RedMask = pdwColors[0];
1669 GreenMask = pdwColors[1];
1670 BlueMask = pdwColors[2];
1671 }
1672 else if (bits == 15)
1673 {
1674 *paletteType = PAL_BITFIELDS;
1675 RedMask = 0x7c00;
1676 GreenMask = 0x03e0;
1677 BlueMask = 0x001f;
1678 }
1679 else if (bits == 16)
1680 {
1681 *paletteType = PAL_BITFIELDS;
1682 RedMask = 0xF800;
1683 GreenMask = 0x07e0;
1684 BlueMask = 0x001f;
1685 }
1686 else
1687 {
1688 *paletteType = PAL_BGR;
1689 RedMask = 0xff0000;
1690 GreenMask = 0x00ff00;
1691 BlueMask = 0x0000ff;
1692 }
1693
1694 if (bmi->bmiHeader.biClrUsed == 0)
1695 {
1696 ColorCount = 1 << bmi->bmiHeader.biBitCount;
1697 }
1698 else
1699 {
1700 ColorCount = bmi->bmiHeader.biClrUsed;
1701 }
1702
1703 if (PAL_INDEXED == *paletteType)
1704 {
1705 hPal = PALETTE_AllocPaletteIndexedRGB(ColorCount, (RGBQUAD*)pdwColors);
1706 }
1707 else
1708 {
1709 hPal = PALETTE_AllocPalette(*paletteType, ColorCount,
1710 NULL,
1711 RedMask, GreenMask, BlueMask);
1712 }
1713
1714 return hPal;
1715 }
1716
1717 FORCEINLINE
1718 DWORD
1719 GetBMIColor(CONST BITMAPINFO* pbmi, INT i)
1720 {
1721 DWORD dwRet = 0;
1722 INT size;
1723 if(pbmi->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
1724 {
1725 /* BITMAPCOREINFO holds RGBTRIPLE values */
1726 size = sizeof(RGBTRIPLE);
1727 }
1728 else
1729 {
1730 size = sizeof(RGBQUAD);
1731 }
1732 memcpy(&dwRet, (PBYTE)pbmi + pbmi->bmiHeader.biSize + i*size, size);
1733 return dwRet;
1734 }
1735
1736 FORCEINLINE
1737 VOID
1738 SetBMIColor(CONST BITMAPINFO* pbmi, DWORD* color, INT i)
1739 {
1740 PVOID pvColors = ((PBYTE)pbmi + pbmi->bmiHeader.biSize);
1741 if(pbmi->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
1742 {
1743 RGBTRIPLE *pColor = pvColors;
1744 pColor[i] = *(RGBTRIPLE*)color;
1745 }
1746 else
1747 {
1748 RGBQUAD *pColor = pvColors;
1749 pColor[i] = *(RGBQUAD*)color;
1750 }
1751 }
1752
1753 NTSTATUS
1754 FASTCALL
1755 ProbeAndConvertToBitmapV5Info(
1756 OUT PBITMAPV5INFO pbmiDst,
1757 IN CONST BITMAPINFO* pbmiUnsafe,
1758 IN DWORD dwColorUse,
1759 IN UINT MaxSize)
1760 {
1761 DWORD dwSize;
1762 ULONG ulWidthBytes;
1763 PBITMAPV5HEADER pbmhDst = &pbmiDst->bmiHeader;
1764
1765 /* Get the size and probe */
1766 ProbeForRead(&pbmiUnsafe->bmiHeader.biSize, sizeof(DWORD), 1);
1767 dwSize = pbmiUnsafe->bmiHeader.biSize;
1768 /* At least dwSize bytes must be valids */
1769 ProbeForRead(pbmiUnsafe, max(dwSize, MaxSize), 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 */