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