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