49b0129a89d4f9ee787fda7a944534639e037d6e
[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 = DIB_ConvertBitmapInfo((BITMAPINFO*)pbmci, Usage);
678 if(Info == NULL)
679 {
680 DPRINT1("Error, could not convert the BITMAPCOREINFO!\n");
681 return 0;
682 }
683 rgbQuads = Info->bmiColors;
684 }
685
686 pDC = DC_LockDc(hDC);
687 if (pDC == NULL || pDC->dctype == DC_TYPE_INFO)
688 {
689 ScanLines = 0;
690 goto done;
691 }
692
693 /* Get a pointer to the source bitmap object */
694 psurf = SURFACE_LockSurface(hBitmap);
695 if (psurf == NULL)
696 {
697 ScanLines = 0;
698 goto done;
699 }
700 /* Must not be selected */
701 if(psurf->hdc != NULL)
702 {
703 ScanLines = 0;
704 SetLastWin32Error(ERROR_INVALID_PARAMETER);
705 goto done;
706 }
707
708 /* Fill in the structure */
709 switch(bpp)
710 {
711 case 0: /* Only info */
712 if(pbmci)
713 {
714 pbmci->bmciHeader.bcWidth = psurf->SurfObj.sizlBitmap.cx;
715 pbmci->bmciHeader.bcHeight = (psurf->SurfObj.fjBitmap & BMF_TOPDOWN) ?
716 -psurf->SurfObj.sizlBitmap.cy :
717 psurf->SurfObj.sizlBitmap.cy;
718 pbmci->bmciHeader.bcPlanes = 1;
719 pbmci->bmciHeader.bcBitCount = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
720 }
721 Info->bmiHeader.biWidth = psurf->SurfObj.sizlBitmap.cx;
722 Info->bmiHeader.biHeight = (psurf->SurfObj.fjBitmap & BMF_TOPDOWN) ?
723 -psurf->SurfObj.sizlBitmap.cy :
724 psurf->SurfObj.sizlBitmap.cy;;
725 Info->bmiHeader.biPlanes = 1;
726 Info->bmiHeader.biBitCount = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
727 Info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes( Info->bmiHeader.biWidth,
728 Info->bmiHeader.biHeight,
729 Info->bmiHeader.biBitCount);
730 if(psurf->hSecure)
731 {
732 switch(Info->bmiHeader.biBitCount)
733 {
734 case 16:
735 case 32:
736 Info->bmiHeader.biCompression = BI_BITFIELDS;
737 break;
738 default:
739 Info->bmiHeader.biCompression = BI_RGB;
740 break;
741 }
742 }
743 else if(Info->bmiHeader.biBitCount > 8)
744 {
745 Info->bmiHeader.biCompression = BI_BITFIELDS;
746 }
747 else
748 {
749 Info->bmiHeader.biCompression = BI_RGB;
750 }
751 Info->bmiHeader.biXPelsPerMeter = 0;
752 Info->bmiHeader.biYPelsPerMeter = 0;
753 Info->bmiHeader.biClrUsed = 0;
754 Info->bmiHeader.biClrImportant = 0;
755 ScanLines = psurf->SurfObj.sizlBitmap.cy;
756 /* Get Complete info now */
757 goto done;
758
759 case 1:
760 case 4:
761 case 8:
762 Info->bmiHeader.biClrUsed = 0;
763
764 /* If the bitmap if a DIB section and has the same format than what
765 * we're asked, go ahead! */
766 if((psurf->hSecure) &&
767 (BitsPerFormat(psurf->SurfObj.iBitmapFormat) == bpp))
768 {
769 if(Usage == DIB_RGB_COLORS)
770 {
771 unsigned int colors = min(psurf->ppal->NumColors, 1 << bpp);
772
773 if(pbmci)
774 {
775 for(i=0; i < colors; i++)
776 {
777 rgbTriples[i].rgbtRed = psurf->ppal->IndexedColors[i].peRed;
778 rgbTriples[i].rgbtGreen = psurf->ppal->IndexedColors[i].peGreen;
779 rgbTriples[i].rgbtBlue = psurf->ppal->IndexedColors[i].peBlue;
780 }
781 }
782 if(colors != 1 << bpp) Info->bmiHeader.biClrUsed = colors;
783 RtlCopyMemory(rgbQuads, psurf->ppal->IndexedColors, colors * sizeof(RGBQUAD));
784 }
785 else
786 {
787 for(i=0; i < 1 << bpp; i++)
788 {
789 if(pbmci) ((WORD*)rgbTriples)[i] = i;
790 ((WORD*)rgbQuads)[i] = i;
791 }
792 }
793 }
794 else
795 {
796 if(Usage == DIB_PAL_COLORS)
797 {
798 for(i=0; i < 1 << bpp; i++)
799 {
800 if(pbmci) ((WORD*)rgbTriples)[i] = i;
801 ((WORD*)rgbQuads)[i] = i;
802 }
803 }
804 else if(bpp > 1 && bpp == BitsPerFormat(psurf->SurfObj.iBitmapFormat)) {
805 /* For color DDBs in native depth (mono DDBs always have
806 a black/white palette):
807 Generate the color map from the selected palette */
808 PPALETTE pDcPal = PALETTE_LockPalette(pDC->dclevel.hpal);
809 if(!pDcPal)
810 {
811 ScanLines = 0 ;
812 goto done ;
813 }
814 for (i = 0; i < pDcPal->NumColors; i++) {
815 if (pbmci)
816 {
817 rgbTriples[i].rgbtRed = pDcPal->IndexedColors[i].peRed;
818 rgbTriples[i].rgbtGreen = pDcPal->IndexedColors[i].peGreen;
819 rgbTriples[i].rgbtBlue = pDcPal->IndexedColors[i].peBlue;
820 }
821
822 rgbQuads[i].rgbRed = pDcPal->IndexedColors[i].peRed;
823 rgbQuads[i].rgbGreen = pDcPal->IndexedColors[i].peGreen;
824 rgbQuads[i].rgbBlue = pDcPal->IndexedColors[i].peBlue;
825 rgbQuads[i].rgbReserved = 0;
826 }
827 PALETTE_UnlockPalette(pDcPal);
828 } else {
829 switch (bpp) {
830 case 1:
831 if (pbmci)
832 {
833 rgbTriples[0].rgbtRed = rgbTriples[0].rgbtGreen =
834 rgbTriples[0].rgbtBlue = 0;
835 rgbTriples[1].rgbtRed = rgbTriples[1].rgbtGreen =
836 rgbTriples[1].rgbtBlue = 0xff;
837 }
838 rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen =
839 rgbQuads[0].rgbBlue = 0;
840 rgbQuads[0].rgbReserved = 0;
841 rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen =
842 rgbQuads[1].rgbBlue = 0xff;
843 rgbQuads[1].rgbReserved = 0;
844 break;
845
846 case 4:
847 if (pbmci)
848 RtlCopyMemory(rgbTriples, EGAColorsTriples, sizeof(EGAColorsTriples));
849 RtlCopyMemory(rgbQuads, EGAColorsQuads, sizeof(EGAColorsQuads));
850
851 break;
852
853 case 8:
854 {
855 INT r, g, b;
856 RGBQUAD *color;
857 if (pbmci)
858 {
859 RGBTRIPLE *colorTriple;
860
861 RtlCopyMemory(rgbTriples, DefLogPaletteTriples,
862 10 * sizeof(RGBTRIPLE));
863 RtlCopyMemory(rgbTriples + 246, DefLogPaletteTriples + 10,
864 10 * sizeof(RGBTRIPLE));
865 colorTriple = rgbTriples + 10;
866 for(r = 0; r <= 5; r++) /* FIXME */
867 {
868 for(g = 0; g <= 5; g++)
869 {
870 for(b = 0; b <= 5; b++)
871 {
872 colorTriple->rgbtRed = (r * 0xff) / 5;
873 colorTriple->rgbtGreen = (g * 0xff) / 5;
874 colorTriple->rgbtBlue = (b * 0xff) / 5;
875 color++;
876 }
877 }
878 }
879 }
880 memcpy(rgbQuads, DefLogPaletteQuads,
881 10 * sizeof(RGBQUAD));
882 memcpy(rgbQuads + 246, DefLogPaletteQuads + 10,
883 10 * sizeof(RGBQUAD));
884 color = rgbQuads + 10;
885 for(r = 0; r <= 5; r++) /* FIXME */
886 {
887 for(g = 0; g <= 5; g++)
888 {
889 for(b = 0; b <= 5; b++)
890 {
891 color->rgbRed = (r * 0xff) / 5;
892 color->rgbGreen = (g * 0xff) / 5;
893 color->rgbBlue = (b * 0xff) / 5;
894 color->rgbReserved = 0;
895 color++;
896 }
897 }
898 }
899 }
900 }
901 }
902 }
903 break;
904
905 case 15:
906 if (Info->bmiHeader.biCompression == BI_BITFIELDS)
907 {
908 ((PDWORD)Info->bmiColors)[0] = 0x7c00;
909 ((PDWORD)Info->bmiColors)[1] = 0x03e0;
910 ((PDWORD)Info->bmiColors)[2] = 0x001f;
911 }
912 break;
913
914 case 16:
915 if (Info->bmiHeader.biCompression == BI_BITFIELDS)
916 {
917 if (psurf->hSecure)
918 {
919 ((PDWORD)Info->bmiColors)[0] = psurf->ppal->RedMask;
920 ((PDWORD)Info->bmiColors)[1] = psurf->ppal->GreenMask;
921 ((PDWORD)Info->bmiColors)[2] = psurf->ppal->BlueMask;
922 }
923 else
924 {
925 ((PDWORD)Info->bmiColors)[0] = 0xf800;
926 ((PDWORD)Info->bmiColors)[1] = 0x07e0;
927 ((PDWORD)Info->bmiColors)[2] = 0x001f;
928 }
929 }
930 break;
931
932 case 24:
933 case 32:
934 if (Info->bmiHeader.biCompression == BI_BITFIELDS)
935 {
936 if (psurf->hSecure)
937 {
938 ((PDWORD)Info->bmiColors)[0] = psurf->ppal->RedMask;
939 ((PDWORD)Info->bmiColors)[1] = psurf->ppal->GreenMask;
940 ((PDWORD)Info->bmiColors)[2] = psurf->ppal->BlueMask;
941 }
942 else
943 {
944 ((PDWORD)Info->bmiColors)[0] = 0xff0000;
945 ((PDWORD)Info->bmiColors)[1] = 0x00ff00;
946 ((PDWORD)Info->bmiColors)[2] = 0x0000ff;
947 }
948 }
949 break;
950 }
951
952 if(Bits && ScanLines)
953 {
954 /* Create a DIBSECTION, blt it, profit */
955 PVOID pDIBits ;
956 HBITMAP hBmpDest, hOldDest = NULL, hOldSrc = NULL;
957 HDC hdcDest, hdcSrc;
958 BOOL ret ;
959
960 if (StartScan > psurf->SurfObj.sizlBitmap.cy)
961 {
962 ScanLines = 0;
963 goto done;
964 }
965 else
966 {
967 ScanLines = min(ScanLines, psurf->SurfObj.sizlBitmap.cy - StartScan);
968 }
969
970 hBmpDest = DIB_CreateDIBSection(pDC, Info, Usage, &pDIBits, NULL, 0, 0);
971
972 if(!hBmpDest)
973 {
974 DPRINT1("Unable to create a DIB Section!\n");
975 SetLastWin32Error(ERROR_INVALID_PARAMETER);
976 ScanLines = 0;
977 goto done ;
978 }
979
980 hdcDest = NtGdiCreateCompatibleDC(0);
981 hdcSrc = NtGdiCreateCompatibleDC(0);
982
983 if(!(hdcSrc && hdcDest))
984 {
985 DPRINT1("Error: could not create HDCs!\n");
986 ScanLines = 0;
987 goto cleanup_blt;
988 }
989
990 hOldDest = NtGdiSelectBitmap(hdcDest, hBmpDest);
991 hOldSrc = NtGdiSelectBitmap(hdcSrc, hBitmap);
992
993 if(!(hOldDest && hOldSrc))
994 {
995 DPRINT1("Error : Could not Select bitmaps\n");
996 goto cleanup_blt;
997 }
998
999 ret = GreStretchBltMask(hdcDest,
1000 0,
1001 0,
1002 width,
1003 height,
1004 hdcSrc,
1005 0,
1006 StartScan,
1007 psurf->SurfObj.sizlBitmap.cx,
1008 ScanLines,
1009 SRCCOPY,
1010 0,
1011 NULL,
1012 0,
1013 0);
1014
1015 if(!ret)
1016 ScanLines = 0;
1017 else
1018 {
1019 Status = STATUS_SUCCESS;
1020 _SEH2_TRY
1021 {
1022 RtlCopyMemory(Bits, pDIBits, DIB_GetDIBImageBytes (width, height, bpp));
1023 }
1024 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1025 {
1026 Status = _SEH2_GetExceptionCode();
1027 }
1028 _SEH2_END
1029
1030 if(!NT_SUCCESS(Status))
1031 {
1032 DPRINT1("Unable to copy bits to the user provided pointer\n");
1033 ScanLines = 0;
1034 }
1035 }
1036
1037 cleanup_blt:
1038 if(hdcSrc)
1039 {
1040 if(hOldSrc) NtGdiSelectBitmap(hdcSrc, hOldSrc);
1041 NtGdiDeleteObjectApp(hdcSrc);
1042 }
1043 if(hdcSrc)
1044 {
1045 if(hOldDest) NtGdiSelectBitmap(hdcDest, hOldDest);
1046 NtGdiDeleteObjectApp(hdcDest);
1047 }
1048 GreDeleteObject(hBmpDest);
1049 }
1050
1051 done:
1052
1053 if(pDC) DC_UnlockDc(pDC);
1054 if(psurf) SURFACE_UnlockSurface(psurf);
1055 if(pbmci) DIB_FreeConvertedBitmapInfo(Info, (BITMAPINFO*)pbmci);
1056
1057 return ScanLines;
1058 }
1059
1060
1061 INT
1062 APIENTRY
1063 NtGdiStretchDIBitsInternal(
1064 HDC hDC,
1065 INT XDest,
1066 INT YDest,
1067 INT DestWidth,
1068 INT DestHeight,
1069 INT XSrc,
1070 INT YSrc,
1071 INT SrcWidth,
1072 INT SrcHeight,
1073 LPBYTE Bits,
1074 LPBITMAPINFO BitsInfo,
1075 DWORD Usage,
1076 DWORD ROP,
1077 UINT cjMaxInfo,
1078 UINT cjMaxBits,
1079 HANDLE hcmXform)
1080 {
1081 HBITMAP hBitmap, hOldBitmap = NULL;
1082 HDC hdcMem;
1083 HPALETTE hPal = NULL;
1084 PDC pDC;
1085 NTSTATUS Status;
1086 BITMAPV5INFO bmiLocal ;
1087
1088 if (!Bits || !BitsInfo)
1089 {
1090 SetLastWin32Error(ERROR_INVALID_PARAMETER);
1091 return 0;
1092 }
1093
1094 _SEH2_TRY
1095 {
1096 Status = ProbeAndConvertToBitmapV5Info(&bmiLocal, BitsInfo, Usage, cjMaxInfo);
1097 ProbeForRead(Bits, cjMaxBits, 1);
1098 }
1099 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1100 {
1101 Status = _SEH2_GetExceptionCode();
1102 }
1103 _SEH2_END
1104
1105 if (!NT_SUCCESS(Status))
1106 {
1107 DPRINT1("NtGdiStretchDIBitsInternal fail to read BitMapInfo: %x or Bits: %x\n",BitsInfo,Bits);
1108 return 0;
1109 }
1110
1111 hdcMem = NtGdiCreateCompatibleDC(hDC);
1112 if (hdcMem == NULL)
1113 {
1114 DPRINT1("NtGdiCreateCompatibleDC fail create hdc\n");
1115 return 0;
1116 }
1117
1118 hBitmap = NtGdiCreateCompatibleBitmap(hDC,
1119 abs(bmiLocal.bmiHeader.bV5Width),
1120 abs(bmiLocal.bmiHeader.bV5Height));
1121 if (hBitmap == NULL)
1122 {
1123 DPRINT1("NtGdiCreateCompatibleBitmap fail create bitmap\n");
1124 DPRINT1("hDC : 0x%08x \n", hDC);
1125 DPRINT1("BitsInfo->bmiHeader.biWidth : 0x%08x \n", BitsInfo->bmiHeader.biWidth);
1126 DPRINT1("BitsInfo->bmiHeader.biHeight : 0x%08x \n", BitsInfo->bmiHeader.biHeight);
1127 return 0;
1128 }
1129
1130 /* Select the bitmap into hdcMem, and save a handle to the old bitmap */
1131 hOldBitmap = NtGdiSelectBitmap(hdcMem, hBitmap);
1132
1133 if (Usage == DIB_PAL_COLORS)
1134 {
1135 hPal = NtGdiGetDCObject(hDC, GDI_OBJECT_TYPE_PALETTE);
1136 hPal = GdiSelectPalette(hdcMem, hPal, FALSE);
1137 }
1138
1139 if (bmiLocal.bmiHeader.bV5Compression == BI_RLE4 ||
1140 bmiLocal.bmiHeader.bV5Compression == BI_RLE8)
1141 {
1142 /* copy existing bitmap from destination dc */
1143 if (SrcWidth == DestWidth && SrcHeight == DestHeight)
1144 NtGdiBitBlt(hdcMem, XSrc, abs(bmiLocal.bmiHeader.bV5Height) - SrcHeight - YSrc,
1145 SrcWidth, SrcHeight, hDC, XDest, YDest, ROP, 0, 0);
1146 else
1147 NtGdiStretchBlt(hdcMem, XSrc, abs(bmiLocal.bmiHeader.bV5Height) - SrcHeight - YSrc,
1148 SrcWidth, SrcHeight, hDC, XDest, YDest, DestWidth, DestHeight,
1149 ROP, 0);
1150 }
1151
1152 pDC = DC_LockDc(hdcMem);
1153 if (pDC != NULL)
1154 {
1155 /* Note BitsInfo->bmiHeader.biHeight is the number of scanline,
1156 * if it negitve we getting to many scanline for scanline is UINT not
1157 * a INT, so we need make the negtive value to positve and that make the
1158 * count correct for negtive bitmap, TODO : we need testcase for this api */
1159 IntSetDIBits(pDC, hBitmap, 0, abs(bmiLocal.bmiHeader.bV5Height), Bits,
1160 &bmiLocal, Usage);
1161
1162 DC_UnlockDc(pDC);
1163 }
1164
1165
1166 /* Origin for DIBitmap may be bottom left (positive biHeight) or top
1167 left (negative biHeight) */
1168 if (SrcWidth == DestWidth && SrcHeight == DestHeight)
1169 NtGdiBitBlt(hDC, XDest, YDest, DestWidth, DestHeight,
1170 hdcMem, XSrc, abs(bmiLocal.bmiHeader.bV5Height) - SrcHeight - YSrc,
1171 ROP, 0, 0);
1172 else
1173 NtGdiStretchBlt(hDC, XDest, YDest, DestWidth, DestHeight,
1174 hdcMem, XSrc, abs(bmiLocal.bmiHeader.bV5Height) - SrcHeight - YSrc,
1175 SrcWidth, SrcHeight, ROP, 0);
1176
1177 /* cleanup */
1178 if (hPal)
1179 GdiSelectPalette(hdcMem, hPal, FALSE);
1180
1181 if (hOldBitmap)
1182 NtGdiSelectBitmap(hdcMem, hOldBitmap);
1183
1184 NtGdiDeleteObjectApp(hdcMem);
1185
1186 GreDeleteObject(hBitmap);
1187
1188 return SrcHeight;
1189 }
1190
1191
1192 HBITMAP
1193 FASTCALL
1194 IntCreateDIBitmap(
1195 PDC Dc,
1196 INT width,
1197 INT height,
1198 UINT bpp,
1199 DWORD init,
1200 LPBYTE bits,
1201 PBITMAPV5INFO data,
1202 DWORD coloruse)
1203 {
1204 HBITMAP handle;
1205 BOOL fColor;
1206
1207 // Check if we should create a monochrome or color bitmap. We create a monochrome bitmap only if it has exactly 2
1208 // colors, which are black followed by white, nothing else. In all other cases, we create a color bitmap.
1209
1210 if (bpp != 1) fColor = TRUE;
1211 else if ((coloruse != DIB_RGB_COLORS) || (init != CBM_INIT) || !data) fColor = FALSE;
1212 else
1213 {
1214 const RGBQUAD *rgb = data->bmiColors;
1215 DWORD col = RGB(rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue);
1216
1217 // Check if the first color of the colormap is black
1218 if ((col == RGB(0, 0, 0)))
1219 {
1220 rgb++;
1221 col = RGB(rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue);
1222
1223 // If the second color is white, create a monochrome bitmap
1224 fColor = (col != RGB(0xff,0xff,0xff));
1225 }
1226 else fColor = TRUE;
1227 }
1228
1229 // Now create the bitmap
1230 if (fColor)
1231 {
1232 handle = IntCreateCompatibleBitmap(Dc, width, height);
1233 }
1234 else
1235 {
1236 handle = GreCreateBitmap(width,
1237 height,
1238 1,
1239 1,
1240 NULL);
1241 }
1242
1243 if (height < 0)
1244 height = -height;
1245
1246 if (NULL != handle && CBM_INIT == init)
1247 {
1248 IntSetDIBits(Dc, handle, 0, height, bits, data, coloruse);
1249 }
1250
1251 return handle;
1252 }
1253
1254 // The CreateDIBitmap function creates a device-dependent bitmap (DDB) from a DIB and, optionally, sets the bitmap bits
1255 // The DDB that is created will be whatever bit depth your reference DC is
1256 HBITMAP
1257 APIENTRY
1258 NtGdiCreateDIBitmapInternal(
1259 IN HDC hDc,
1260 IN INT cx,
1261 IN INT cy,
1262 IN DWORD fInit,
1263 IN OPTIONAL LPBYTE pjInit,
1264 IN OPTIONAL LPBITMAPINFO pbmi,
1265 IN DWORD iUsage,
1266 IN UINT cjMaxInitInfo,
1267 IN UINT cjMaxBits,
1268 IN FLONG fl,
1269 IN HANDLE hcmXform)
1270 {
1271 BITMAPV5INFO bmiLocal ;
1272 NTSTATUS Status = STATUS_SUCCESS;
1273
1274 _SEH2_TRY
1275 {
1276 if(pbmi) Status = ProbeAndConvertToBitmapV5Info(&bmiLocal, pbmi, iUsage, cjMaxInitInfo);
1277 if(pjInit && (fInit == CBM_INIT)) ProbeForRead(pjInit, cjMaxBits, 1);
1278 }
1279 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1280 {
1281 Status = _SEH2_GetExceptionCode();
1282 }
1283 _SEH2_END
1284
1285 if(!NT_SUCCESS(Status))
1286 {
1287 SetLastNtError(Status);
1288 return NULL;
1289 }
1290
1291 return GreCreateDIBitmapInternal(hDc,
1292 cx,
1293 cy,
1294 fInit,
1295 pjInit,
1296 pbmi ? &bmiLocal : NULL,
1297 iUsage,
1298 fl,
1299 hcmXform);
1300 }
1301
1302 HBITMAP
1303 FASTCALL
1304 GreCreateDIBitmapInternal(
1305 IN HDC hDc,
1306 IN INT cx,
1307 IN INT cy,
1308 IN DWORD fInit,
1309 IN OPTIONAL LPBYTE pjInit,
1310 IN OPTIONAL PBITMAPV5INFO pbmi,
1311 IN DWORD iUsage,
1312 IN FLONG fl,
1313 IN HANDLE hcmXform)
1314 {
1315 PDC Dc;
1316 HBITMAP Bmp;
1317 WORD bpp;
1318 HDC hdcDest;
1319
1320 if (!hDc) /* 1bpp monochrome bitmap */
1321 { // Should use System Bitmap DC hSystemBM, with CreateCompatibleDC for this.
1322 hdcDest = IntGdiCreateDC(NULL, NULL, NULL, NULL,FALSE);
1323 if(!hdcDest)
1324 {
1325 return NULL;
1326 }
1327 }
1328 else
1329 {
1330 hdcDest = hDc;
1331 }
1332
1333 Dc = DC_LockDc(hdcDest);
1334 if (!Dc)
1335 {
1336 SetLastWin32Error(ERROR_INVALID_HANDLE);
1337 return NULL;
1338 }
1339 /* It's OK to set bpp=0 here, as IntCreateDIBitmap will create a compatible Bitmap
1340 * if bpp != 1 and ignore the real value that was passed */
1341 if (pbmi)
1342 bpp = pbmi->bmiHeader.bV5BitCount;
1343 else
1344 bpp = 0;
1345 Bmp = IntCreateDIBitmap(Dc, cx, cy, bpp, fInit, pjInit, pbmi, iUsage);
1346 DC_UnlockDc(Dc);
1347
1348 if(!hDc)
1349 {
1350 NtGdiDeleteObjectApp(hdcDest);
1351 }
1352 return Bmp;
1353 }
1354
1355
1356 HBITMAP
1357 APIENTRY
1358 NtGdiCreateDIBSection(
1359 IN HDC hDC,
1360 IN OPTIONAL HANDLE hSection,
1361 IN DWORD dwOffset,
1362 IN BITMAPINFO* bmi,
1363 IN DWORD Usage,
1364 IN UINT cjHeader,
1365 IN FLONG fl,
1366 IN ULONG_PTR dwColorSpace,
1367 OUT PVOID *Bits)
1368 {
1369 HBITMAP hbitmap = 0;
1370 DC *dc;
1371 BOOL bDesktopDC = FALSE;
1372 NTSTATUS Status = STATUS_SUCCESS;
1373
1374 if (!bmi) return hbitmap; // Make sure.
1375
1376 _SEH2_TRY
1377 {
1378 ProbeForRead(&bmi->bmiHeader.biSize, sizeof(DWORD), 1);
1379 ProbeForRead(bmi, bmi->bmiHeader.biSize, 1);
1380 ProbeForRead(bmi, DIB_BitmapInfoSize(bmi, Usage), 1);
1381 }
1382 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1383 {
1384 Status = _SEH2_GetExceptionCode();
1385 }
1386 _SEH2_END
1387
1388 if(!NT_SUCCESS(Status))
1389 {
1390 SetLastNtError(Status);
1391 return NULL;
1392 }
1393
1394 // If the reference hdc is null, take the desktop dc
1395 if (hDC == 0)
1396 {
1397 hDC = NtGdiCreateCompatibleDC(0);
1398 bDesktopDC = TRUE;
1399 }
1400
1401 if ((dc = DC_LockDc(hDC)))
1402 {
1403 hbitmap = DIB_CreateDIBSection(dc,
1404 bmi,
1405 Usage,
1406 Bits,
1407 hSection,
1408 dwOffset,
1409 0);
1410 DC_UnlockDc(dc);
1411 }
1412 else
1413 {
1414 SetLastWin32Error(ERROR_INVALID_HANDLE);
1415 }
1416
1417 if (bDesktopDC)
1418 NtGdiDeleteObjectApp(hDC);
1419
1420 return hbitmap;
1421 }
1422
1423 HBITMAP
1424 APIENTRY
1425 DIB_CreateDIBSection(
1426 PDC dc,
1427 CONST BITMAPINFO *bmi,
1428 UINT usage,
1429 LPVOID *bits,
1430 HANDLE section,
1431 DWORD offset,
1432 DWORD ovr_pitch)
1433 {
1434 HBITMAP res = 0;
1435 SURFACE *bmp = NULL;
1436 void *mapBits = NULL;
1437 HPALETTE hpal ;
1438 INT palMode = PAL_INDEXED;
1439
1440 // Fill BITMAP32 structure with DIB data
1441 CONST BITMAPINFOHEADER *bi = &bmi->bmiHeader;
1442 INT effHeight;
1443 ULONG totalSize;
1444 BITMAP bm;
1445 SIZEL Size;
1446 HANDLE hSecure;
1447
1448 DPRINT("format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n",
1449 bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
1450 bi->biSizeImage, bi->biClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1451
1452 /* CreateDIBSection should fail for compressed formats */
1453 if (bi->biCompression == BI_RLE4 || bi->biCompression == BI_RLE8)
1454 {
1455 return (HBITMAP)NULL;
1456 }
1457
1458 effHeight = bi->biHeight >= 0 ? bi->biHeight : -bi->biHeight;
1459 bm.bmType = 0;
1460 bm.bmWidth = bi->biWidth;
1461 bm.bmHeight = effHeight;
1462 bm.bmWidthBytes = ovr_pitch ? ovr_pitch : (ULONG) DIB_GetDIBWidthBytes(bm.bmWidth, bi->biBitCount);
1463
1464 bm.bmPlanes = bi->biPlanes;
1465 bm.bmBitsPixel = bi->biBitCount;
1466 bm.bmBits = NULL;
1467
1468 // Get storage location for DIB bits. Only use biSizeImage if it's valid and
1469 // we're dealing with a compressed bitmap. Otherwise, use width * height.
1470 totalSize = bi->biSizeImage && bi->biCompression != BI_RGB
1471 ? bi->biSizeImage : (ULONG)(bm.bmWidthBytes * effHeight);
1472
1473 if (section)
1474 {
1475 SYSTEM_BASIC_INFORMATION Sbi;
1476 NTSTATUS Status;
1477 DWORD mapOffset;
1478 LARGE_INTEGER SectionOffset;
1479 SIZE_T mapSize;
1480
1481 Status = ZwQuerySystemInformation(SystemBasicInformation,
1482 &Sbi,
1483 sizeof Sbi,
1484 0);
1485 if (!NT_SUCCESS(Status))
1486 {
1487 return NULL;
1488 }
1489
1490 mapOffset = offset - (offset % Sbi.AllocationGranularity);
1491 mapSize = bi->biSizeImage + (offset - mapOffset);
1492
1493 SectionOffset.LowPart = mapOffset;
1494 SectionOffset.HighPart = 0;
1495
1496 Status = ZwMapViewOfSection(section,
1497 NtCurrentProcess(),
1498 &mapBits,
1499 0,
1500 0,
1501 &SectionOffset,
1502 &mapSize,
1503 ViewShare,
1504 0,
1505 PAGE_READWRITE);
1506 if (!NT_SUCCESS(Status))
1507 {
1508 SetLastWin32Error(ERROR_INVALID_PARAMETER);
1509 return NULL;
1510 }
1511
1512 if (mapBits) bm.bmBits = (char *)mapBits + (offset - mapOffset);
1513 }
1514 else if (ovr_pitch && offset)
1515 bm.bmBits = (LPVOID) offset;
1516 else
1517 {
1518 offset = 0;
1519 bm.bmBits = EngAllocUserMem(totalSize, 0);
1520 if(!bm.bmBits) goto cleanup;
1521 }
1522
1523 // hSecure = MmSecureVirtualMemory(bm.bmBits, totalSize, PAGE_READWRITE);
1524 hSecure = (HANDLE)0x1; // HACK OF UNIMPLEMENTED KERNEL STUFF !!!!
1525
1526 if (usage == DIB_PAL_COLORS)
1527 {
1528 PPALETTE pdcPal ;
1529 pdcPal = PALETTE_LockPalette(dc->dclevel.hpal);
1530 if(!pdcPal)
1531 {
1532 DPRINT1("Unable to lock DC palette?!\n");
1533 goto cleanup;
1534 }
1535 if(pdcPal->Mode != PAL_INDEXED)
1536 {
1537 DPRINT1("Not indexed palette selected in the DC?!\n");
1538 PALETTE_UnlockPalette(pdcPal);
1539 }
1540 hpal = PALETTE_AllocPalette(PAL_INDEXED,
1541 pdcPal->NumColors,
1542 (ULONG*)pdcPal->IndexedColors, 0, 0, 0);
1543 PALETTE_UnlockPalette(pdcPal);
1544 }
1545 else
1546 {
1547 hpal = BuildDIBPalette(bmi, &palMode);
1548 }
1549
1550 // Create Device Dependent Bitmap and add DIB pointer
1551 Size.cx = bm.bmWidth;
1552 Size.cy = abs(bm.bmHeight);
1553 res = GreCreateBitmapEx(bm.bmWidth,
1554 abs(bm.bmHeight),
1555 bm.bmWidthBytes,
1556 BitmapFormat(bi->biBitCount * bi->biPlanes, bi->biCompression),
1557 BMF_DONTCACHE | BMF_USERMEM | BMF_NOZEROINIT |
1558 (bi->biHeight < 0 ? BMF_TOPDOWN : 0),
1559 bi->biSizeImage,
1560 bm.bmBits);
1561 if (!res)
1562 {
1563 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
1564 goto cleanup;
1565 }
1566 bmp = SURFACE_LockSurface(res);
1567 if (NULL == bmp)
1568 {
1569 SetLastWin32Error(ERROR_INVALID_HANDLE);
1570 goto cleanup;
1571 }
1572
1573 /* WINE NOTE: WINE makes use of a colormap, which is a color translation
1574 table between the DIB and the X physical device. Obviously,
1575 this is left out of the ReactOS implementation. Instead,
1576 we call NtGdiSetDIBColorTable. */
1577 bmp->hDIBSection = section;
1578 bmp->hSecure = hSecure;
1579 bmp->dwOffset = offset;
1580 bmp->flags = API_BITMAP;
1581 bmp->biClrImportant = bi->biClrImportant;
1582
1583 bmp->ppal = PALETTE_ShareLockPalette(hpal);
1584 /* Lazy delete hpal, it will be freed at surface release */
1585 GreDeleteObject(hpal);
1586
1587 // Clean up in case of errors
1588 cleanup:
1589 if (!res || !bmp || !bm.bmBits)
1590 {
1591 DPRINT("got an error res=%08x, bmp=%p, bm.bmBits=%p\n", res, bmp, bm.bmBits);
1592 if (bm.bmBits)
1593 {
1594 // MmUnsecureVirtualMemory(hSecure); // FIXME: Implement this!
1595 if (section)
1596 {
1597 ZwUnmapViewOfSection(NtCurrentProcess(), mapBits);
1598 bm.bmBits = NULL;
1599 }
1600 else
1601 if (!offset)
1602 EngFreeUserMem(bm.bmBits), bm.bmBits = NULL;
1603 }
1604
1605 if (bmp)
1606 bmp = NULL;
1607
1608 if (res)
1609 {
1610 SURFACE_FreeSurfaceByHandle(res);
1611 res = 0;
1612 }
1613 }
1614
1615 if (bmp)
1616 {
1617 SURFACE_UnlockSurface(bmp);
1618 }
1619
1620 // Return BITMAP handle and storage location
1621 if (NULL != bm.bmBits && NULL != bits)
1622 {
1623 *bits = bm.bmBits;
1624 }
1625
1626 return res;
1627 }
1628
1629 /***********************************************************************
1630 * DIB_GetBitmapInfo
1631 *
1632 * Get the info from a bitmap header.
1633 * Return 0 for COREHEADER, 1 for INFOHEADER, -1 for error.
1634 */
1635 int
1636 FASTCALL
1637 DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
1638 LONG *height, WORD *planes, WORD *bpp, DWORD *compr, DWORD *size )
1639 {
1640 if (header->biSize == sizeof(BITMAPCOREHEADER))
1641 {
1642 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)header;
1643 *width = core->bcWidth;
1644 *height = core->bcHeight;
1645 *planes = core->bcPlanes;
1646 *bpp = core->bcBitCount;
1647 *compr = 0;
1648 *size = 0;
1649 return 0;
1650 }
1651 if (header->biSize >= sizeof(BITMAPINFOHEADER)) /* assume BITMAPINFOHEADER */
1652 {
1653 *width = header->biWidth;
1654 *height = header->biHeight;
1655 *planes = header->biPlanes;
1656 *bpp = header->biBitCount;
1657 *compr = header->biCompression;
1658 *size = header->biSizeImage;
1659 return 1;
1660 }
1661 DPRINT1("(%d): unknown/wrong size for header\n", header->biSize );
1662 return -1;
1663 }
1664
1665 /***********************************************************************
1666 * DIB_GetDIBWidthBytes
1667 *
1668 * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
1669 * http://www.microsoft.com/msdn/sdk/platforms/doc/sdk/win32/struc/src/str01.htm
1670 * 11/16/1999 (RJJ) lifted from wine
1671 */
1672 INT FASTCALL DIB_GetDIBWidthBytes(INT width, INT depth)
1673 {
1674 return ((width * depth + 31) & ~31) >> 3;
1675 }
1676
1677 /***********************************************************************
1678 * DIB_GetDIBImageBytes
1679 *
1680 * Return the number of bytes used to hold the image in a DIB bitmap.
1681 * 11/16/1999 (RJJ) lifted from wine
1682 */
1683
1684 INT APIENTRY DIB_GetDIBImageBytes(INT width, INT height, INT depth)
1685 {
1686 return DIB_GetDIBWidthBytes(width, depth) * (height < 0 ? -height : height);
1687 }
1688
1689 /***********************************************************************
1690 * DIB_BitmapInfoSize
1691 *
1692 * Return the size of the bitmap info structure including color table.
1693 * 11/16/1999 (RJJ) lifted from wine
1694 */
1695
1696 INT FASTCALL DIB_BitmapInfoSize(const BITMAPINFO * info, WORD coloruse)
1697 {
1698 unsigned int colors, size, masks = 0;
1699
1700 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
1701 {
1702 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
1703 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
1704 return sizeof(BITMAPCOREHEADER) + colors *
1705 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
1706 }
1707 else /* assume BITMAPINFOHEADER */
1708 {
1709 colors = info->bmiHeader.biClrUsed;
1710 if (colors > 256) colors = 256;
1711 if (!colors && (info->bmiHeader.biBitCount <= 8))
1712 colors = 1 << info->bmiHeader.biBitCount;
1713 if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3;
1714 size = max( info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD) );
1715 return size + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
1716 }
1717 }
1718
1719 RGBQUAD *
1720 FASTCALL
1721 DIB_MapPaletteColors(PDC dc, CONST BITMAPINFO* lpbmi)
1722 {
1723 RGBQUAD *lpRGB;
1724 ULONG nNumColors,i;
1725 USHORT *lpIndex;
1726 PPALETTE palGDI;
1727
1728 palGDI = PALETTE_LockPalette(dc->dclevel.hpal);
1729
1730 if (NULL == palGDI)
1731 {
1732 return NULL;
1733 }
1734
1735 if (palGDI->Mode != PAL_INDEXED)
1736 {
1737 PALETTE_UnlockPalette(palGDI);
1738 return NULL;
1739 }
1740
1741 nNumColors = 1 << lpbmi->bmiHeader.biBitCount;
1742 if (lpbmi->bmiHeader.biClrUsed)
1743 {
1744 nNumColors = min(nNumColors, lpbmi->bmiHeader.biClrUsed);
1745 }
1746
1747 lpRGB = (RGBQUAD *)ExAllocatePoolWithTag(PagedPool, sizeof(RGBQUAD) * nNumColors, TAG_COLORMAP);
1748 if (lpRGB == NULL)
1749 {
1750 PALETTE_UnlockPalette(palGDI);
1751 return NULL;
1752 }
1753
1754 lpIndex = (USHORT *)&lpbmi->bmiColors[0];
1755
1756 for (i = 0; i < nNumColors; i++)
1757 {
1758 if (*lpIndex < palGDI->NumColors)
1759 {
1760 lpRGB[i].rgbRed = palGDI->IndexedColors[*lpIndex].peRed;
1761 lpRGB[i].rgbGreen = palGDI->IndexedColors[*lpIndex].peGreen;
1762 lpRGB[i].rgbBlue = palGDI->IndexedColors[*lpIndex].peBlue;
1763 }
1764 else
1765 {
1766 lpRGB[i].rgbRed = 0;
1767 lpRGB[i].rgbGreen = 0;
1768 lpRGB[i].rgbBlue = 0;
1769 }
1770 lpRGB[i].rgbReserved = 0;
1771 lpIndex++;
1772 }
1773 PALETTE_UnlockPalette(palGDI);
1774
1775 return lpRGB;
1776 }
1777
1778 HPALETTE
1779 FASTCALL
1780 BuildDIBPalette(CONST BITMAPINFO *bmi, PINT paletteType)
1781 {
1782 BYTE bits;
1783 ULONG ColorCount;
1784 HPALETTE hPal;
1785 ULONG RedMask, GreenMask, BlueMask;
1786 PDWORD pdwColors = (PDWORD)((PBYTE)bmi + bmi->bmiHeader.biSize);
1787
1788 // Determine Bits Per Pixel
1789 bits = bmi->bmiHeader.biBitCount;
1790
1791 // Determine paletteType from Bits Per Pixel
1792 if (bits <= 8)
1793 {
1794 *paletteType = PAL_INDEXED;
1795 RedMask = GreenMask = BlueMask = 0;
1796 }
1797 else if (bmi->bmiHeader.biCompression == BI_BITFIELDS)
1798 {
1799 *paletteType = PAL_BITFIELDS;
1800 RedMask = pdwColors[0];
1801 GreenMask = pdwColors[1];
1802 BlueMask = pdwColors[2];
1803 }
1804 else if (bits == 15)
1805 {
1806 *paletteType = PAL_BITFIELDS;
1807 RedMask = 0x7c00;
1808 GreenMask = 0x03e0;
1809 BlueMask = 0x001f;
1810 }
1811 else if (bits == 16)
1812 {
1813 *paletteType = PAL_BITFIELDS;
1814 RedMask = 0xF800;
1815 GreenMask = 0x07e0;
1816 BlueMask = 0x001f;
1817 }
1818 else
1819 {
1820 *paletteType = PAL_RGB;
1821 RedMask = 0xff0000;
1822 GreenMask = 0x00ff00;
1823 BlueMask = 0x0000ff;
1824 }
1825
1826 if (bmi->bmiHeader.biClrUsed == 0)
1827 {
1828 ColorCount = 1 << bmi->bmiHeader.biBitCount;
1829 }
1830 else
1831 {
1832 ColorCount = bmi->bmiHeader.biClrUsed;
1833 }
1834
1835 if (PAL_INDEXED == *paletteType)
1836 {
1837 hPal = PALETTE_AllocPaletteIndexedRGB(ColorCount, (RGBQUAD*)pdwColors);
1838 }
1839 else
1840 {
1841 hPal = PALETTE_AllocPalette(*paletteType, 0,
1842 NULL,
1843 RedMask, GreenMask, BlueMask);
1844 }
1845
1846 return hPal;
1847 }
1848
1849 FORCEINLINE
1850 DWORD
1851 GetBMIColor(CONST BITMAPINFO* pbmi, INT i)
1852 {
1853 DWORD dwRet = 0;
1854 INT size;
1855 if(pbmi->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
1856 {
1857 /* BITMAPCOREINFO holds RGBTRIPLE values */
1858 size = sizeof(RGBTRIPLE);
1859 }
1860 else
1861 {
1862 size = sizeof(RGBQUAD);
1863 }
1864 memcpy(&dwRet, (PBYTE)pbmi + pbmi->bmiHeader.biSize + i*size, size);
1865 return dwRet;
1866 }
1867
1868 NTSTATUS
1869 FASTCALL
1870 ProbeAndConvertToBitmapV5Info(
1871 OUT PBITMAPV5INFO pbmiDst,
1872 IN CONST BITMAPINFO* pbmiUnsafe,
1873 IN DWORD dwColorUse,
1874 IN UINT MaxSize)
1875 {
1876 DWORD dwSize;
1877 ULONG ulWidthBytes;
1878 PBITMAPV5HEADER pbmhDst = &pbmiDst->bmiHeader;
1879
1880 /* Get the size and probe */
1881 ProbeForRead(&pbmiUnsafe->bmiHeader.biSize, sizeof(DWORD), 1);
1882 dwSize = pbmiUnsafe->bmiHeader.biSize;
1883 /* At least dwSize bytes must be valids */
1884 ProbeForRead(pbmiUnsafe, max(dwSize, MaxSize), 1);
1885 if(!MaxSize)
1886 ProbeForRead(pbmiUnsafe, DIB_BitmapInfoSize(pbmiUnsafe, dwColorUse), 1);
1887
1888 /* Check the size */
1889 // FIXME: are intermediate sizes allowed? As what are they interpreted?
1890 // make sure we don't use a too big dwSize later
1891 if (dwSize != sizeof(BITMAPCOREHEADER) &&
1892 dwSize != sizeof(BITMAPINFOHEADER) &&
1893 dwSize != sizeof(BITMAPV4HEADER) &&
1894 dwSize != sizeof(BITMAPV5HEADER))
1895 {
1896 return STATUS_INVALID_PARAMETER;
1897 }
1898
1899 if (dwSize == sizeof(BITMAPCOREHEADER))
1900 {
1901 PBITMAPCOREHEADER pbch = (PBITMAPCOREHEADER)pbmiUnsafe;
1902
1903 /* Manually copy the fields that are present */
1904 pbmhDst->bV5Width = pbch->bcWidth;
1905 pbmhDst->bV5Height = pbch->bcHeight;
1906 pbmhDst->bV5Planes = pbch->bcPlanes;
1907 pbmhDst->bV5BitCount = pbch->bcBitCount;
1908
1909 /* Set some default values */
1910 pbmhDst->bV5Compression = BI_RGB;
1911 pbmhDst->bV5SizeImage = DIB_GetDIBImageBytes(pbch->bcWidth,
1912 pbch->bcHeight,
1913 pbch->bcPlanes*pbch->bcBitCount) ;
1914 pbmhDst->bV5XPelsPerMeter = 72;
1915 pbmhDst->bV5YPelsPerMeter = 72;
1916 pbmhDst->bV5ClrUsed = 0;
1917 pbmhDst->bV5ClrImportant = 0;
1918 }
1919 else
1920 {
1921 /* Copy valid fields */
1922 memcpy(pbmiDst, pbmiUnsafe, dwSize);
1923 if(!pbmhDst->bV5SizeImage)
1924 pbmhDst->bV5SizeImage = DIB_GetDIBImageBytes(pbmhDst->bV5Width,
1925 pbmhDst->bV5Height,
1926 pbmhDst->bV5Planes*pbmhDst->bV5BitCount) ;
1927
1928 if(dwSize < sizeof(BITMAPV5HEADER))
1929 {
1930 /* Zero out the rest of the V5 header */
1931 memset((char*)pbmiDst + dwSize, 0, sizeof(BITMAPV5HEADER) - dwSize);
1932 }
1933 }
1934 pbmhDst->bV5Size = sizeof(BITMAPV5HEADER);
1935
1936
1937 if (dwSize < sizeof(BITMAPV4HEADER))
1938 {
1939 if (pbmhDst->bV5Compression == BI_BITFIELDS)
1940 {
1941 pbmhDst->bV5RedMask = GetBMIColor(pbmiUnsafe, 0);
1942 pbmhDst->bV5GreenMask = GetBMIColor(pbmiUnsafe, 1);
1943 pbmhDst->bV5BlueMask = GetBMIColor(pbmiUnsafe, 2);
1944 pbmhDst->bV5AlphaMask = 0;
1945 pbmhDst->bV5ClrUsed = 0;
1946 }
1947
1948 // pbmhDst->bV5CSType;
1949 // pbmhDst->bV5Endpoints;
1950 // pbmhDst->bV5GammaRed;
1951 // pbmhDst->bV5GammaGreen;
1952 // pbmhDst->bV5GammaBlue;
1953 }
1954
1955 if (dwSize < sizeof(BITMAPV5HEADER))
1956 {
1957 // pbmhDst->bV5Intent;
1958 // pbmhDst->bV5ProfileData;
1959 // pbmhDst->bV5ProfileSize;
1960 // pbmhDst->bV5Reserved;
1961 }
1962
1963 ulWidthBytes = ((pbmhDst->bV5Width * pbmhDst->bV5Planes *
1964 pbmhDst->bV5BitCount + 31) & ~31) / 8;
1965
1966 if (pbmhDst->bV5SizeImage == 0)
1967 pbmhDst->bV5SizeImage = abs(ulWidthBytes * pbmhDst->bV5Height);
1968
1969 if (pbmhDst->bV5ClrUsed == 0)
1970 {
1971 switch(pbmhDst->bV5BitCount)
1972 {
1973 case 1:
1974 pbmhDst->bV5ClrUsed = 2;
1975 break;
1976 case 4:
1977 pbmhDst->bV5ClrUsed = 16;
1978 break;
1979 case 8:
1980 pbmhDst->bV5ClrUsed = 256;
1981 break;
1982 default:
1983 pbmhDst->bV5ClrUsed = 0;
1984 break;
1985 }
1986 }
1987
1988 if (pbmhDst->bV5Planes != 1)
1989 {
1990 return STATUS_INVALID_PARAMETER;
1991 }
1992
1993 if (pbmhDst->bV5BitCount != 0 && pbmhDst->bV5BitCount != 1 &&
1994 pbmhDst->bV5BitCount != 4 && pbmhDst->bV5BitCount != 8 &&
1995 pbmhDst->bV5BitCount != 16 && pbmhDst->bV5BitCount != 24 &&
1996 pbmhDst->bV5BitCount != 32)
1997 {
1998 DPRINT("Invalid bit count: %d\n", pbmhDst->bV5BitCount);
1999 return STATUS_INVALID_PARAMETER;
2000 }
2001
2002 if ((pbmhDst->bV5BitCount == 0 &&
2003 pbmhDst->bV5Compression != BI_JPEG && pbmhDst->bV5Compression != BI_PNG))
2004 {
2005 DPRINT("Bit count 0 is invalid for compression %d.\n", pbmhDst->bV5Compression);
2006 return STATUS_INVALID_PARAMETER;
2007 }
2008
2009 if (pbmhDst->bV5Compression == BI_BITFIELDS &&
2010 pbmhDst->bV5BitCount != 16 && pbmhDst->bV5BitCount != 32)
2011 {
2012 DPRINT("Bit count %d is invalid for compression BI_BITFIELDS.\n", pbmhDst->bV5BitCount);
2013 return STATUS_INVALID_PARAMETER;
2014 }
2015
2016 /* Copy Colors */
2017 if(pbmhDst->bV5ClrUsed)
2018 {
2019 INT i;
2020 if(dwColorUse == DIB_PAL_COLORS)
2021 {
2022 RtlCopyMemory(pbmiDst->bmiColors,
2023 pbmiUnsafe->bmiColors,
2024 pbmhDst->bV5ClrUsed * sizeof(WORD));
2025 }
2026 else
2027 {
2028 for(i = 0; i < pbmhDst->bV5ClrUsed; i++)
2029 {
2030 ((DWORD*)pbmiDst->bmiColors)[i] = GetBMIColor(pbmiUnsafe, i);
2031 }
2032 }
2033 }
2034
2035 return STATUS_SUCCESS;
2036 }
2037
2038 /* Converts a BITMAPCOREINFO to a BITMAPINFO structure,
2039 * or does nothing if it's already a BITMAPINFO (or V4 or V5) */
2040 BITMAPINFO*
2041 FASTCALL
2042 DIB_ConvertBitmapInfo (CONST BITMAPINFO* pbmi, DWORD Usage)
2043 {
2044 CONST BITMAPCOREINFO* pbmci = (BITMAPCOREINFO*)pbmi;
2045 BITMAPINFO* pNewBmi ;
2046 UINT numColors = 0, ColorsSize = 0;
2047
2048 if(pbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) return (BITMAPINFO*)pbmi;
2049 if(pbmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) return NULL;
2050
2051 if(pbmci->bmciHeader.bcBitCount <= 8)
2052 {
2053 numColors = 1 << pbmci->bmciHeader.bcBitCount;
2054 if(Usage == DIB_PAL_COLORS)
2055 {
2056 ColorsSize = numColors * sizeof(WORD);
2057 }
2058 else
2059 {
2060 ColorsSize = numColors * sizeof(RGBQUAD);
2061 }
2062 }
2063 else if (Usage == DIB_PAL_COLORS)
2064 {
2065 /* Invalid at high Res */
2066 return NULL;
2067 }
2068
2069 pNewBmi = ExAllocatePoolWithTag(PagedPool, sizeof(BITMAPINFOHEADER) + ColorsSize, TAG_DIB);
2070 if(!pNewBmi) return NULL;
2071
2072 RtlZeroMemory(pNewBmi, sizeof(BITMAPINFOHEADER) + ColorsSize);
2073
2074 pNewBmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
2075 pNewBmi->bmiHeader.biBitCount = pbmci->bmciHeader.bcBitCount;
2076 pNewBmi->bmiHeader.biWidth = pbmci->bmciHeader.bcWidth;
2077 pNewBmi->bmiHeader.biHeight = pbmci->bmciHeader.bcHeight;
2078 pNewBmi->bmiHeader.biPlanes = pbmci->bmciHeader.bcPlanes;
2079 pNewBmi->bmiHeader.biCompression = BI_RGB ;
2080 pNewBmi->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(pNewBmi->bmiHeader.biWidth,
2081 pNewBmi->bmiHeader.biHeight,
2082 pNewBmi->bmiHeader.biBitCount);
2083
2084 if(Usage == DIB_PAL_COLORS)
2085 {
2086 RtlCopyMemory(pNewBmi->bmiColors, pbmci->bmciColors, ColorsSize);
2087 }
2088 else
2089 {
2090 UINT i;
2091 for(i=0; i<numColors; i++)
2092 {
2093 pNewBmi->bmiColors[i].rgbRed = pbmci->bmciColors[i].rgbtRed;
2094 pNewBmi->bmiColors[i].rgbGreen = pbmci->bmciColors[i].rgbtGreen;
2095 pNewBmi->bmiColors[i].rgbBlue = pbmci->bmciColors[i].rgbtBlue;
2096 }
2097 }
2098
2099 return pNewBmi ;
2100 }
2101
2102 /* Frees a BITMAPINFO created with DIB_ConvertBitmapInfo */
2103 VOID
2104 FASTCALL
2105 DIB_FreeConvertedBitmapInfo(BITMAPINFO* converted, BITMAPINFO* orig)
2106 {
2107 if(converted != orig)
2108 ExFreePoolWithTag(converted, TAG_DIB);
2109 }
2110
2111
2112
2113
2114
2115
2116 /* EOF */