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