fix a mem leak in win32k bitmap code
[reactos.git] / reactos / subsystems / win32 / win32k / objects / dibobj.c
1 /*
2 * $Id$
3 *
4 * ReactOS W32 Subsystem
5 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include <w32k.h>
23
24 #define NDEBUG
25 #include <debug.h>
26
27 UINT STDCALL
28 IntSetDIBColorTable(HDC hDC, UINT StartIndex, UINT Entries, CONST RGBQUAD *Colors)
29 {
30 PDC dc;
31 PBITMAPOBJ BitmapObj;
32 PPALGDI PalGDI;
33 UINT Index;
34
35 if (!(dc = DC_LockDc(hDC))) return 0;
36 if (dc->DC_Type == DC_TYPE_INFO)
37 {
38 DC_UnlockDc(dc);
39 return 0;
40 }
41
42 BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap);
43 if (BitmapObj == NULL)
44 {
45 DC_UnlockDc(dc);
46 SetLastWin32Error(ERROR_INVALID_PARAMETER);
47 return 0;
48 }
49
50 if (BitmapObj->dib == NULL)
51 {
52 BITMAPOBJ_UnlockBitmap(BitmapObj);
53 DC_UnlockDc(dc);
54 SetLastWin32Error(ERROR_INVALID_PARAMETER);
55 return 0;
56 }
57
58 if (BitmapObj->dib->dsBmih.biBitCount <= 8 &&
59 StartIndex < (1 << BitmapObj->dib->dsBmih.biBitCount))
60 {
61 if (StartIndex + Entries > (1 << BitmapObj->dib->dsBmih.biBitCount))
62 Entries = (1 << BitmapObj->dib->dsBmih.biBitCount) - StartIndex;
63
64 PalGDI = PALETTE_LockPalette(BitmapObj->hDIBPalette);
65
66 for (Index = StartIndex;
67 Index < StartIndex + Entries && Index < PalGDI->NumColors;
68 Index++)
69 {
70 PalGDI->IndexedColors[Index].peRed = Colors[Index - StartIndex].rgbRed;
71 PalGDI->IndexedColors[Index].peGreen = Colors[Index - StartIndex].rgbGreen;
72 PalGDI->IndexedColors[Index].peBlue = Colors[Index - StartIndex].rgbBlue;
73 }
74 PALETTE_UnlockPalette(PalGDI);
75 }
76 else
77 Entries = 0;
78
79 BITMAPOBJ_UnlockBitmap(BitmapObj);
80 DC_UnlockDc(dc);
81
82 return Entries;
83 }
84
85 UINT STDCALL
86 IntGetDIBColorTable(HDC hDC, UINT StartIndex, UINT Entries, RGBQUAD *Colors)
87 {
88 PDC dc;
89 PBITMAPOBJ BitmapObj;
90 PPALGDI PalGDI;
91 UINT Index;
92
93 if (!(dc = DC_LockDc(hDC))) return 0;
94 if (dc->DC_Type == DC_TYPE_INFO)
95 {
96 DC_UnlockDc(dc);
97 return 0;
98 }
99
100 BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap);
101 if (BitmapObj == NULL)
102 {
103 DC_UnlockDc(dc);
104 SetLastWin32Error(ERROR_INVALID_PARAMETER);
105 return 0;
106 }
107
108 if (BitmapObj->dib == NULL)
109 {
110 BITMAPOBJ_UnlockBitmap(BitmapObj);
111 DC_UnlockDc(dc);
112 SetLastWin32Error(ERROR_INVALID_PARAMETER);
113 return 0;
114 }
115
116 if (BitmapObj->dib->dsBmih.biBitCount <= 8 &&
117 StartIndex < (1 << BitmapObj->dib->dsBmih.biBitCount))
118 {
119 if (StartIndex + Entries > (1 << BitmapObj->dib->dsBmih.biBitCount))
120 Entries = (1 << BitmapObj->dib->dsBmih.biBitCount) - StartIndex;
121
122 PalGDI = PALETTE_LockPalette(BitmapObj->hDIBPalette);
123
124 for (Index = StartIndex;
125 Index < StartIndex + Entries && Index < PalGDI->NumColors;
126 Index++)
127 {
128 Colors[Index - StartIndex].rgbRed = PalGDI->IndexedColors[Index].peRed;
129 Colors[Index - StartIndex].rgbGreen = PalGDI->IndexedColors[Index].peGreen;
130 Colors[Index - StartIndex].rgbBlue = PalGDI->IndexedColors[Index].peBlue;
131 }
132 PALETTE_UnlockPalette(PalGDI);
133 }
134 else
135 Entries = 0;
136
137 BITMAPOBJ_UnlockBitmap(BitmapObj);
138 DC_UnlockDc(dc);
139
140 return Entries;
141 }
142
143 // Converts a DIB to a device-dependent bitmap
144 static INT FASTCALL
145 IntSetDIBits(
146 PDC DC,
147 HBITMAP hBitmap,
148 UINT StartScan,
149 UINT ScanLines,
150 CONST VOID *Bits,
151 CONST BITMAPINFO *bmi,
152 UINT ColorUse)
153 {
154 BITMAPOBJ *bitmap;
155 HBITMAP SourceBitmap;
156 INT result = 0;
157 BOOL copyBitsResult;
158 SURFOBJ *DestSurf, *SourceSurf;
159 SIZEL SourceSize;
160 POINTL ZeroPoint;
161 RECTL DestRect;
162 XLATEOBJ *XlateObj;
163 PPALGDI hDCPalette;
164 //RGBQUAD *lpRGB;
165 HPALETTE DDB_Palette, DIB_Palette;
166 ULONG DDB_Palette_Type, DIB_Palette_Type;
167 INT DIBWidth;
168
169 // Check parameters
170 if (!(bitmap = BITMAPOBJ_LockBitmap(hBitmap)))
171 {
172 return 0;
173 }
174
175 // Get RGB values
176 //if (ColorUse == DIB_PAL_COLORS)
177 // lpRGB = DIB_MapPaletteColors(hDC, bmi);
178 //else
179 // lpRGB = &bmi->bmiColors;
180
181 DestSurf = &bitmap->SurfObj;
182
183 // Create source surface
184 SourceSize.cx = bmi->bmiHeader.biWidth;
185 SourceSize.cy = ScanLines;
186
187 // Determine width of DIB
188 DIBWidth = DIB_GetDIBWidthBytes(SourceSize.cx, bmi->bmiHeader.biBitCount);
189
190 SourceBitmap = EngCreateBitmap(SourceSize,
191 DIBWidth,
192 BitmapFormat(bmi->bmiHeader.biBitCount, bmi->bmiHeader.biCompression),
193 bmi->bmiHeader.biHeight < 0 ? BMF_TOPDOWN : 0,
194 (PVOID) Bits);
195 if (0 == SourceBitmap)
196 {
197 BITMAPOBJ_UnlockBitmap(bitmap);
198 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
199 return 0;
200 }
201
202 SourceSurf = EngLockSurface((HSURF)SourceBitmap);
203 if (NULL == SourceSurf)
204 {
205 EngDeleteSurface((HSURF)SourceBitmap);
206 BITMAPOBJ_UnlockBitmap(bitmap);
207 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
208 return 0;
209 }
210
211 // Destination palette obtained from the hDC
212 hDCPalette = PALETTE_LockPalette(((GDIDEVICE *)DC->pPDev)->DevInfo.hpalDefault);
213 if (NULL == hDCPalette)
214 {
215 EngUnlockSurface(SourceSurf);
216 EngDeleteSurface((HSURF)SourceBitmap);
217 BITMAPOBJ_UnlockBitmap(bitmap);
218 SetLastWin32Error(ERROR_INVALID_HANDLE);
219 return 0;
220 }
221 DDB_Palette_Type = hDCPalette->Mode;
222 DDB_Palette = ((GDIDEVICE *)DC->pPDev)->DevInfo.hpalDefault;
223 PALETTE_UnlockPalette(hDCPalette);
224
225 // Source palette obtained from the BITMAPINFO
226 DIB_Palette = BuildDIBPalette ( (PBITMAPINFO)bmi, (PINT)&DIB_Palette_Type );
227 if (NULL == DIB_Palette)
228 {
229 EngUnlockSurface(SourceSurf);
230 EngDeleteSurface((HSURF)SourceBitmap);
231 BITMAPOBJ_UnlockBitmap(bitmap);
232 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
233 return 0;
234 }
235
236 // Determine XLATEOBJ for color translation
237 XlateObj = IntEngCreateXlate(DDB_Palette_Type, DIB_Palette_Type, DDB_Palette, DIB_Palette);
238 if (NULL == XlateObj)
239 {
240 PALETTE_FreePalette(DIB_Palette);
241 EngUnlockSurface(SourceSurf);
242 EngDeleteSurface((HSURF)SourceBitmap);
243 BITMAPOBJ_UnlockBitmap(bitmap);
244 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
245 return 0;
246 }
247
248 // Zero point
249 ZeroPoint.x = 0;
250 ZeroPoint.y = 0;
251
252 // Determine destination rectangle
253 DestRect.left = 0;
254 DestRect.top = abs(bmi->bmiHeader.biHeight) - StartScan - ScanLines;
255 DestRect.right = SourceSize.cx;
256 DestRect.bottom = DestRect.top + ScanLines;
257
258 copyBitsResult = EngCopyBits(DestSurf, SourceSurf, NULL, XlateObj, &DestRect, &ZeroPoint);
259
260 // If it succeeded, return number of scanlines copies
261 if(copyBitsResult == TRUE)
262 {
263 result = SourceSize.cy - 1;
264 }
265
266 // Clean up
267 EngDeleteXlate(XlateObj);
268 PALETTE_FreePalette(DIB_Palette);
269 EngUnlockSurface(SourceSurf);
270 EngDeleteSurface((HSURF)SourceBitmap);
271
272 // if (ColorUse == DIB_PAL_COLORS)
273 // WinFree((LPSTR)lpRGB);
274
275 BITMAPOBJ_UnlockBitmap(bitmap);
276
277 return result;
278 }
279
280 // Converts a DIB to a device-dependent bitmap
281 INT STDCALL
282 NtGdiSetDIBits(
283 HDC hDC,
284 HBITMAP hBitmap,
285 UINT StartScan,
286 UINT ScanLines,
287 CONST VOID *Bits,
288 CONST BITMAPINFO *bmi,
289 UINT ColorUse)
290 {
291 PDC Dc;
292 INT Ret;
293
294 Dc = DC_LockDc(hDC);
295 if (NULL == Dc)
296 {
297 SetLastWin32Error(ERROR_INVALID_HANDLE);
298 return 0;
299 }
300 if (Dc->DC_Type == DC_TYPE_INFO)
301 {
302 DC_UnlockDc(Dc);
303 return 0;
304 }
305
306 Ret = IntSetDIBits(Dc, hBitmap, StartScan, ScanLines, Bits, bmi, ColorUse);
307
308 DC_UnlockDc(Dc);
309
310 return Ret;
311 }
312
313 W32KAPI
314 INT
315 APIENTRY
316 NtGdiSetDIBitsToDeviceInternal(
317 IN HDC hDC,
318 IN INT XDest,
319 IN INT YDest,
320 IN DWORD Width,
321 IN DWORD Height,
322 IN INT XSrc,
323 IN INT YSrc,
324 IN DWORD StartScan,
325 IN DWORD ScanLines,
326 IN LPBYTE Bits,
327 IN LPBITMAPINFO bmi,
328 IN DWORD ColorUse,
329 IN UINT cjMaxBits,
330 IN UINT cjMaxInfo,
331 IN BOOL bTransformCoordinates,
332 IN OPTIONAL HANDLE hcmXform
333 )
334 {
335 INT ret = 0;
336 NTSTATUS Status = STATUS_SUCCESS;
337 PDC pDC;
338 HBITMAP hSourceBitmap;
339 SURFOBJ *pDestSurf, *pSourceSurf;
340 RECTL rcDest;
341 POINTL ptSource;
342 INT DIBWidth;
343 SIZEL SourceSize;
344 XLATEOBJ *XlateObj = NULL;
345
346 if (!Bits) return 0;
347
348 pDC = DC_LockDc(hDC);
349 if (!pDC)
350 {
351 SetLastWin32Error(ERROR_INVALID_HANDLE);
352 return 0;
353 }
354 if (pDC->DC_Type == DC_TYPE_INFO)
355 {
356 DC_UnlockDc(pDC);
357 return 0;
358 }
359
360 pDestSurf = EngLockSurface((HSURF)pDC->w.hBitmap);
361 if (!pDestSurf)
362 {
363 /* FIXME: SetLastError ? */
364 DC_UnlockDc(pDC);
365 return 0;
366 }
367
368 SourceSize.cx = bmi->bmiHeader.biWidth;
369 SourceSize.cy = ScanLines;
370 DIBWidth = DIB_GetDIBWidthBytes(SourceSize.cx, bmi->bmiHeader.biBitCount);
371
372 rcDest.left = XDest;
373 rcDest.top = YDest;
374 rcDest.right = XDest + Width;
375 rcDest.bottom = YDest + Height;
376 ptSource.x = XSrc;
377 ptSource.y = YSrc;
378
379 /* Enter SEH, as the bits are user mode */
380 _SEH_TRY
381 {
382 ProbeForRead(Bits, DIBWidth * abs(bmi->bmiHeader.biHeight), 1);
383 hSourceBitmap = EngCreateBitmap(SourceSize,
384 DIBWidth,
385 BitmapFormat(bmi->bmiHeader.biBitCount, bmi->bmiHeader.biCompression),
386 bmi->bmiHeader.biHeight < 0 ? BMF_TOPDOWN : 0,
387 (PVOID) Bits);
388 if (!hSourceBitmap)
389 {
390 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
391 Status = STATUS_NO_MEMORY;
392 _SEH_LEAVE;
393 }
394
395 pSourceSurf = EngLockSurface((HSURF)hSourceBitmap);
396 if (!pSourceSurf)
397 {
398 EngDeleteSurface((HSURF)hSourceBitmap);
399 Status = STATUS_UNSUCCESSFUL;
400 _SEH_LEAVE;
401 }
402
403 /* FIXME: handle XlateObj */
404 XlateObj = NULL;
405
406 /* Copy the bits */
407 Status = IntEngBitBlt(pDestSurf,
408 pSourceSurf,
409 NULL,
410 pDC->CombinedClip,
411 XlateObj,
412 &rcDest,
413 &ptSource,
414 NULL,
415 NULL,
416 NULL,
417 ROP3_TO_ROP4(SRCCOPY));
418
419 EngUnlockSurface(pSourceSurf);
420 EngDeleteSurface((HSURF)hSourceBitmap);
421 }
422 _SEH_HANDLE
423 {
424 Status = _SEH_GetExceptionCode();
425 }
426 _SEH_END
427
428 if (NT_SUCCESS(Status))
429 {
430 /* FIXME: Should probably be only the number of lines actually copied */
431 ret = ScanLines;
432 }
433
434 EngUnlockSurface(pDestSurf);
435 DC_UnlockDc(pDC);
436
437 return ret;
438 }
439
440
441 /* Converts a device-dependent bitmap to a DIB */
442 INT STDCALL
443 NtGdiGetDIBitsInternal(HDC hDC,
444 HBITMAP hBitmap,
445 UINT StartScan,
446 UINT ScanLines,
447 LPBYTE Bits,
448 LPBITMAPINFO Info,
449 UINT Usage,
450 UINT MaxBits,
451 UINT MaxInfo)
452 {
453 PDC Dc;
454 BITMAPOBJ *BitmapObj = NULL;
455 HBITMAP hDestBitmap = NULL;
456 HPALETTE hSourcePalette = NULL;
457 HPALETTE hDestPalette = NULL;
458 PPALGDI SourcePalette = NULL;
459 PPALGDI DestPalette = NULL;
460 NTSTATUS Status = STATUS_SUCCESS;
461 ULONG Result = 0;
462 BOOL bPaletteMatch = FALSE;
463
464 DPRINT("Entered NtGdiGetDIBitsInternal()\n");
465
466 /* Get handle for the palette in DC. */
467 Dc = DC_LockDc(hDC);
468 if (Dc == NULL) return 0;
469 if (Dc->DC_Type == DC_TYPE_INFO)
470 {
471 DC_UnlockDc(Dc);
472 return 0;
473 }
474 /* Source palette obtained from the windows hdc */
475 hSourcePalette = Dc->w.hPalette;
476 DC_UnlockDc(Dc);
477
478 /* don't do anything if we fail this */
479 if (Usage != DIB_RGB_COLORS && Usage != DIB_PAL_COLORS)
480 return 0;
481
482 /* Get a pointer to the source bitmap object */
483 BitmapObj = BITMAPOBJ_LockBitmap(hBitmap);
484 if (BitmapObj == NULL)
485 return 0;
486
487 /* fill out the BITMAPINFO struct */
488 if (Bits == NULL)
489 {
490 _SEH_TRY
491 {
492 if (Info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
493 {
494 BITMAPCOREHEADER* coreheader;
495
496 ProbeForWrite(Info, sizeof(BITMAPINFO), 1);
497
498 coreheader = (BITMAPCOREHEADER*) Info;
499 coreheader->bcWidth =BitmapObj->SurfObj.sizlBitmap.cx;
500 coreheader->bcPlanes = 1;
501 coreheader->bcBitCount = BitsPerFormat(BitmapObj->SurfObj.iBitmapFormat);
502 coreheader->bcHeight = BitmapObj->SurfObj.sizlBitmap.cy;
503
504 if (BitmapObj->SurfObj.lDelta > 0)
505 coreheader->bcHeight = -coreheader->bcHeight;
506 }
507
508 if (Info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
509 {
510 ProbeForWrite(Info, sizeof(BITMAPINFO), 1);
511
512 Info->bmiHeader.biWidth = BitmapObj->SurfObj.sizlBitmap.cx;
513 Info->bmiHeader.biHeight = BitmapObj->SurfObj.sizlBitmap.cy;
514 /* Report negtive height for top-down bitmaps. */
515 if (BitmapObj->SurfObj.lDelta > 0)
516 Info->bmiHeader.biHeight = -Info->bmiHeader.biHeight;
517 Info->bmiHeader.biPlanes = 1;
518 Info->bmiHeader.biBitCount = BitsPerFormat(BitmapObj->SurfObj.iBitmapFormat);
519 if (Info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
520 {
521 switch (BitmapObj->SurfObj.iBitmapFormat)
522 {
523 case BMF_1BPP:
524 case BMF_4BPP:
525 case BMF_8BPP:
526 case BMF_16BPP:
527 case BMF_24BPP:
528 case BMF_32BPP:
529 Info->bmiHeader.biCompression = BI_RGB;
530 break;
531 case BMF_4RLE:
532 Info->bmiHeader.biCompression = BI_RLE4;
533 break;
534 case BMF_8RLE:
535 Info->bmiHeader.biCompression = BI_RLE8;
536 break;
537 case BMF_JPEG:
538 Info->bmiHeader.biCompression = BI_JPEG;
539 break;
540 case BMF_PNG:
541 Info->bmiHeader.biCompression = BI_PNG;
542 break;
543 }
544
545 Info->bmiHeader.biSizeImage = BitmapObj->SurfObj.cjBits;
546 Info->bmiHeader.biXPelsPerMeter = 0; /* FIXME */
547 Info->bmiHeader.biYPelsPerMeter = 0; /* FIXME */
548 Info->bmiHeader.biClrUsed = 0;
549 Info->bmiHeader.biClrImportant = 1 << Info->bmiHeader.biBitCount; /* FIXME */
550 }
551 }
552 }
553 _SEH_HANDLE
554 {
555 Status = _SEH_GetExceptionCode();
556 }
557 _SEH_END
558
559 if (NT_SUCCESS(Status))
560 {
561 Result = BitmapObj->SurfObj.sizlBitmap.cy;
562 }
563 }
564 else
565 {
566 SIZEL DestSize;
567 ULONG SourcePaletteType = 0;
568 ULONG DestPaletteType;
569 POINTL SourcePoint;
570 ULONG Index;
571
572 _SEH_TRY
573 {
574 ProbeForRead(Info, sizeof(BITMAPINFO), 1);
575
576 if (Info->bmiHeader.biBitCount == BitsPerFormat(BitmapObj->SurfObj.iBitmapFormat))
577 {
578 hDestPalette = hSourcePalette;
579 bPaletteMatch = TRUE;
580 }
581 else
582 hDestPalette = BuildDIBPalette(Info, (PINT)&DestPaletteType); //hDestPalette = Dc->DevInfo->hpalDefault;
583
584 SourcePalette = PALETTE_LockPalette(hSourcePalette);
585 /* FIXME - SourcePalette can be NULL!!! Don't assert here! */
586 ASSERT(SourcePalette);
587 SourcePaletteType = SourcePalette->Mode;
588 PALETTE_UnlockPalette(SourcePalette);
589
590 if (bPaletteMatch)
591 {
592 DestPalette = PALETTE_LockPalette(hDestPalette);
593 /* FIXME - DestPalette can be NULL!!!! Don't assert here!!! */
594 DPRINT("DestPalette : %p\n", DestPalette);
595 ASSERT(DestPalette);
596 DestPaletteType = DestPalette->Mode;
597 }
598 else
599 {
600 DestPalette = SourcePalette;
601 }
602
603 /* Copy palette. */
604 /* FIXME: This is largely incomplete. */
605 if (Info->bmiHeader.biBitCount <= 8)
606 {
607 if (Usage == DIB_RGB_COLORS)
608 {
609 for (Index = 0;
610 Index < (1 << Info->bmiHeader.biBitCount) && Index < DestPalette->NumColors;
611 Index++)
612 {
613 Info->bmiColors[Index].rgbRed = DestPalette->IndexedColors[Index].peRed;
614 Info->bmiColors[Index].rgbGreen = DestPalette->IndexedColors[Index].peGreen;
615 Info->bmiColors[Index].rgbBlue = DestPalette->IndexedColors[Index].peBlue;
616 }
617 }
618
619 if (Usage == DIB_PAL_COLORS)
620 {
621 DPRINT1("GetDIBits with DIB_PAL_COLORS isn't implemented yet\n");
622 }
623 }
624
625 if (bPaletteMatch)
626 PALETTE_UnlockPalette(DestPalette);
627
628 /* Create the destination bitmap to for the copy operation */
629 if (StartScan > BitmapObj->SurfObj.sizlBitmap.cy)
630 {
631 _SEH_YIELD(goto cleanup);
632 }
633 else
634 {
635 ScanLines = min(ScanLines, BitmapObj->SurfObj.sizlBitmap.cy - StartScan);
636 DestSize.cx = BitmapObj->SurfObj.sizlBitmap.cx;
637 DestSize.cy = ScanLines;
638
639 hDestBitmap = NULL;
640
641 ProbeForWrite(Bits, sizeof(BitmapObj->SurfObj.cjBits), 1);
642
643 if (Info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
644 {
645 BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) Info;
646
647 hDestBitmap = EngCreateBitmap(DestSize,
648 DIB_GetDIBWidthBytes(DestSize.cx, coreheader->bcBitCount),
649 BitmapFormat(coreheader->bcBitCount, BI_RGB),
650 0 < coreheader->bcHeight ? 0 : BMF_TOPDOWN,
651 Bits);
652 }
653
654 if (Info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
655 {
656 hDestBitmap = EngCreateBitmap(DestSize,
657 /* DIB_GetDIBWidthBytes(DestSize.cx, Info->bmiHeader.biBitCount), */
658 DestSize.cx * (Info->bmiHeader.biBitCount >> 3), /* HACK */
659 BitmapFormat(Info->bmiHeader.biBitCount, Info->bmiHeader.biCompression),
660 0 < Info->bmiHeader.biHeight ? 0 : BMF_TOPDOWN,
661 Bits);
662 }
663
664 if (hDestBitmap == NULL)
665 _SEH_YIELD(goto cleanup);
666 }
667 }
668 _SEH_HANDLE
669 {
670 Status = _SEH_GetExceptionCode();
671 }
672 _SEH_END
673
674 if (NT_SUCCESS(Status))
675 {
676 XLATEOBJ *XlateObj;
677 SURFOBJ *DestSurfObj;
678 RECTL DestRect;
679
680 XlateObj = IntEngCreateXlate(DestPaletteType,
681 SourcePaletteType,
682 hDestPalette,
683 hSourcePalette);
684
685 SourcePoint.x = 0;
686 SourcePoint.y = BitmapObj->SurfObj.sizlBitmap.cy - (StartScan + ScanLines);
687
688 /* Determine destination rectangle */
689 DestRect.top = 0;
690 DestRect.left = 0;
691 DestRect.right = DestSize.cx;
692 DestRect.bottom = DestSize.cy;
693
694 DestSurfObj = EngLockSurface((HSURF)hDestBitmap);
695
696 if (EngCopyBits(DestSurfObj,
697 &BitmapObj->SurfObj,
698 NULL,
699 XlateObj,
700 &DestRect,
701 &SourcePoint))
702 {
703 Result = ScanLines;
704 }
705
706 EngDeleteXlate(XlateObj);
707 EngUnlockSurface(DestSurfObj);
708 }
709 }
710
711 cleanup:
712 if (hDestBitmap != NULL)
713 EngDeleteSurface((HSURF)hDestBitmap);
714
715 if (hDestPalette != NULL && bPaletteMatch == FALSE)
716 PALETTE_FreePalette(hDestPalette);
717
718 BITMAPOBJ_UnlockBitmap(BitmapObj);
719
720 DPRINT("leaving NtGdiGetDIBitsInternal\n");
721
722 return Result;
723 }
724
725 INT STDCALL NtGdiStretchDIBits(HDC hDC,
726 INT XDest,
727 INT YDest,
728 INT DestWidth,
729 INT DestHeight,
730 INT XSrc,
731 INT YSrc,
732 INT SrcWidth,
733 INT SrcHeight,
734 CONST VOID *Bits,
735 CONST BITMAPINFO *BitsInfo,
736 UINT Usage,
737 DWORD ROP)
738 {
739 HBITMAP hBitmap, hOldBitmap;
740 HDC hdcMem;
741 HPALETTE hPal = NULL;
742
743 if (!Bits || !BitsInfo)
744 {
745 SetLastWin32Error(ERROR_INVALID_PARAMETER);
746 return 0;
747 }
748
749 hdcMem = NtGdiCreateCompatibleDC(hDC);
750 hBitmap = NtGdiCreateCompatibleBitmap(hDC, BitsInfo->bmiHeader.biWidth,
751 BitsInfo->bmiHeader.biHeight);
752 hOldBitmap = NtGdiSelectBitmap(hdcMem, hBitmap);
753
754 if(Usage == DIB_PAL_COLORS)
755 {
756 hPal = NtGdiGetDCObject(hDC, GDI_OBJECT_TYPE_PALETTE);
757 hPal = NtUserSelectPalette(hdcMem, hPal, FALSE);
758 }
759
760 if (BitsInfo->bmiHeader.biCompression == BI_RLE4 ||
761 BitsInfo->bmiHeader.biCompression == BI_RLE8)
762 {
763 /* copy existing bitmap from destination dc */
764 if (SrcWidth == DestWidth && SrcHeight == DestHeight)
765 NtGdiBitBlt(hdcMem, XSrc, abs(BitsInfo->bmiHeader.biHeight) - SrcHeight - YSrc,
766 SrcWidth, SrcHeight, hDC, XDest, YDest, ROP, 0, 0);
767 else
768 NtGdiStretchBlt(hdcMem, XSrc, abs(BitsInfo->bmiHeader.biHeight) - SrcHeight - YSrc,
769 SrcWidth, SrcHeight, hDC, XDest, YDest, DestWidth, DestHeight,
770 ROP, 0);
771 }
772
773 NtGdiSetDIBits(hdcMem, hBitmap, 0, BitsInfo->bmiHeader.biHeight, Bits,
774 BitsInfo, Usage);
775
776 /* Origin for DIBitmap may be bottom left (positive biHeight) or top
777 left (negative biHeight) */
778 if (SrcWidth == DestWidth && SrcHeight == DestHeight)
779 NtGdiBitBlt(hDC, XDest, YDest, DestWidth, DestHeight,
780 hdcMem, XSrc, abs(BitsInfo->bmiHeader.biHeight) - SrcHeight - YSrc,
781 ROP, 0, 0);
782 else
783 NtGdiStretchBlt(hDC, XDest, YDest, DestWidth, DestHeight,
784 hdcMem, XSrc, abs(BitsInfo->bmiHeader.biHeight) - SrcHeight - YSrc,
785 SrcWidth, SrcHeight, ROP, 0);
786
787 if(hPal)
788 NtUserSelectPalette(hdcMem, hPal, FALSE);
789
790 NtGdiSelectBitmap(hdcMem, hOldBitmap);
791 NtGdiDeleteObjectApp(hdcMem);
792 NtGdiDeleteObject(hBitmap);
793
794 return SrcHeight;
795 }
796
797
798 HBITMAP FASTCALL
799 IntCreateDIBitmap(PDC Dc, const BITMAPINFOHEADER *header,
800 DWORD init, LPCVOID bits, const BITMAPINFO *data,
801 UINT coloruse)
802 {
803 HBITMAP handle;
804
805 LONG width;
806 LONG height;
807 WORD planes;
808 WORD bpp;
809 LONG compr;
810 LONG dibsize;
811 BOOL fColor;
812
813 if (DIB_GetBitmapInfo( header, &width, &height, &planes, &bpp, &compr, &dibsize ) == -1) return 0;
814
815 // Check if we should create a monochrome or color bitmap. We create a monochrome bitmap only if it has exactly 2
816 // colors, which are black followed by white, nothing else. In all other cases, we create a color bitmap.
817
818 if (bpp != 1) fColor = TRUE;
819 else if ((coloruse != DIB_RGB_COLORS) ||
820 (init != CBM_INIT) || !data) fColor = FALSE;
821 else
822 {
823 if (data->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
824 {
825 const RGBQUAD *rgb = data->bmiColors;
826 DWORD col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
827
828 // Check if the first color of the colormap is black
829 if ((col == RGB(0, 0, 0)))
830 {
831 rgb++;
832 col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
833
834 // If the second color is white, create a monochrome bitmap
835 fColor = (col != RGB(0xff,0xff,0xff));
836 }
837 else fColor = TRUE;
838 }
839 else if (data->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
840 {
841 RGBTRIPLE *rgb = ((BITMAPCOREINFO *)data)->bmciColors;
842 DWORD col = RGB( rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue);
843
844 if ((col == RGB(0,0,0)))
845 {
846 rgb++;
847 col = RGB( rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue );
848 fColor = (col != RGB(0xff,0xff,0xff));
849 }
850 else fColor = TRUE;
851 }
852 else
853 {
854 DPRINT("(%ld): wrong size for data\n", data->bmiHeader.biSize );
855 return 0;
856 }
857 }
858
859 // Now create the bitmap
860 if (fColor)
861 {
862 handle = IntCreateCompatibleBitmap(Dc, width, height);
863 }
864 else
865 {
866 handle = IntGdiCreateBitmap(width,
867 height,
868 1,
869 1,
870 NULL);
871 }
872
873 if (height < 0)
874 height = -height;
875
876 if (NULL != handle && CBM_INIT == init)
877 {
878 IntSetDIBits(Dc, handle, 0, height, bits, data, coloruse);
879 }
880
881 return handle;
882 }
883
884 // The CreateDIBitmap function creates a device-dependent bitmap (DDB) from a DIB and, optionally, sets the bitmap bits
885 // The DDB that is created will be whatever bit depth your reference DC is
886 HBITMAP STDCALL NtGdiCreateDIBitmap(HDC hDc, const BITMAPINFOHEADER *Header,
887 DWORD Init, LPCVOID Bits, const BITMAPINFO *Data,
888 UINT ColorUse)
889 {
890 PDC Dc;
891 HBITMAP Bmp;
892
893 if (Header == NULL)
894 {
895 return NULL;
896 }
897
898 if (Header->biSize == 0)
899 {
900 return NULL;
901 }
902
903 if (NULL == hDc)
904 {
905 BITMAPINFOHEADER *change_Header = (BITMAPINFOHEADER *)Header;
906 hDc = IntGdiCreateDC(NULL, NULL, NULL, NULL,FALSE);
907 if (hDc == NULL)
908 {
909 SetLastWin32Error(ERROR_INVALID_HANDLE);
910 return NULL;
911 }
912 Dc = DC_LockDc(hDc);
913 if (Dc == NULL)
914 {
915 NtGdiDeleteObjectApp(hDc);
916 SetLastWin32Error(ERROR_INVALID_HANDLE);
917 return NULL;
918 }
919
920 change_Header->biBitCount = 1;
921 change_Header->biPlanes = 1;
922
923 Bmp = IntCreateDIBitmap(Dc, Header, Init, Bits, Data, ColorUse);
924 DC_UnlockDc(Dc);
925 NtGdiDeleteObjectApp(hDc);
926 }
927 else
928 {
929 Dc = DC_LockDc(hDc);
930 if (Dc == NULL)
931 {
932 SetLastWin32Error(ERROR_INVALID_HANDLE);
933 return NULL;
934 }
935 Bmp = IntCreateDIBitmap(Dc, Header, Init, Bits, Data, ColorUse);
936 DC_UnlockDc(Dc);
937 }
938
939
940
941 return Bmp;
942 }
943
944 HBITMAP STDCALL NtGdiCreateDIBSection(HDC hDC,
945 IN OPTIONAL HANDLE hSection,
946 IN DWORD dwOffset,
947 IN LPBITMAPINFO bmi,
948 DWORD Usage,
949 IN UINT cjHeader,
950 IN FLONG fl,
951 IN ULONG_PTR dwColorSpace,
952 PVOID *Bits)
953 {
954 HBITMAP hbitmap = 0;
955 DC *dc;
956 BOOL bDesktopDC = FALSE;
957
958 // If the reference hdc is null, take the desktop dc
959 if (hDC == 0)
960 {
961 hDC = NtGdiCreateCompatibleDC(0);
962 bDesktopDC = TRUE;
963 }
964
965 if ((dc = DC_LockDc(hDC)))
966 {
967 hbitmap = DIB_CreateDIBSection ( dc, (BITMAPINFO*)bmi, Usage, Bits,
968 hSection, dwOffset, 0);
969 DC_UnlockDc(dc);
970 }
971 else
972 {
973 SetLastWin32Error(ERROR_INVALID_HANDLE);
974 }
975
976 if (bDesktopDC)
977 NtGdiDeleteObjectApp(hDC);
978
979 return hbitmap;
980 }
981
982 HBITMAP STDCALL
983 DIB_CreateDIBSection(
984 PDC dc, BITMAPINFO *bmi, UINT usage,
985 LPVOID *bits, HANDLE section,
986 DWORD offset, DWORD ovr_pitch)
987 {
988 HBITMAP res = 0;
989 BITMAPOBJ *bmp = NULL;
990 DIBSECTION *dib = NULL;
991
992 // Fill BITMAP32 structure with DIB data
993 BITMAPINFOHEADER *bi = &bmi->bmiHeader;
994 INT effHeight;
995 ULONG totalSize;
996 UINT Entries = 0;
997 BITMAP bm;
998 SIZEL Size;
999 RGBQUAD *lpRGB;
1000
1001 DPRINT("format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n",
1002 bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
1003 bi->biSizeImage, bi->biClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1004
1005 effHeight = bi->biHeight >= 0 ? bi->biHeight : -bi->biHeight;
1006 bm.bmType = 0;
1007 bm.bmWidth = bi->biWidth;
1008 bm.bmHeight = effHeight;
1009 bm.bmWidthBytes = ovr_pitch ? ovr_pitch : (ULONG) DIB_GetDIBWidthBytes(bm.bmWidth, bi->biBitCount);
1010
1011 bm.bmPlanes = bi->biPlanes;
1012 bm.bmBitsPixel = bi->biBitCount;
1013 bm.bmBits = NULL;
1014
1015 // Get storage location for DIB bits. Only use biSizeImage if it's valid and
1016 // we're dealing with a compressed bitmap. Otherwise, use width * height.
1017 totalSize = bi->biSizeImage && bi->biCompression != BI_RGB
1018 ? bi->biSizeImage : (ULONG) (bm.bmWidthBytes * effHeight);
1019
1020 if (section)
1021 {
1022 /* bm.bmBits = MapViewOfFile(section, FILE_MAP_ALL_ACCESS,
1023 0L, offset, totalSize); */
1024 DbgPrint("DIB_CreateDIBSection: Cannot yet handle section DIBs\n");
1025 SetLastWin32Error(ERROR_CALL_NOT_IMPLEMENTED);
1026 return 0;
1027 }
1028 else if (ovr_pitch && offset)
1029 bm.bmBits = (LPVOID) offset;
1030 else {
1031 offset = 0;
1032 bm.bmBits = EngAllocUserMem(totalSize, 0);
1033 }
1034
1035 if(usage == DIB_PAL_COLORS)
1036 lpRGB = DIB_MapPaletteColors(dc, bmi);
1037 else
1038 lpRGB = bmi->bmiColors;
1039
1040 // Allocate Memory for DIB and fill structure
1041 if (bm.bmBits)
1042 {
1043 dib = ExAllocatePoolWithTag(PagedPool, sizeof(DIBSECTION), TAG_DIB);
1044 if (dib != NULL) RtlZeroMemory(dib, sizeof(DIBSECTION));
1045 }
1046
1047 if (dib)
1048 {
1049 dib->dsBm = bm;
1050 dib->dsBmih = *bi;
1051 dib->dsBmih.biSizeImage = totalSize;
1052
1053 /* Set dsBitfields values */
1054 if ( usage == DIB_PAL_COLORS || bi->biBitCount <= 8)
1055 {
1056 dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
1057 }
1058 else switch(bi->biBitCount)
1059 {
1060 case 16:
1061 dib->dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)lpRGB : 0x7c00;
1062 dib->dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)lpRGB + 1) : 0x03e0;
1063 dib->dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)lpRGB + 2) : 0x001f; break;
1064
1065 case 24:
1066 dib->dsBitfields[0] = 0xff0000;
1067 dib->dsBitfields[1] = 0x00ff00;
1068 dib->dsBitfields[2] = 0x0000ff;
1069 break;
1070
1071 case 32:
1072 dib->dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)lpRGB : 0xff0000;
1073 dib->dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)lpRGB + 1) : 0x00ff00;
1074 dib->dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)lpRGB + 2) : 0x0000ff;
1075 break;
1076 }
1077 dib->dshSection = section;
1078 dib->dsOffset = offset;
1079 }
1080
1081 // Create Device Dependent Bitmap and add DIB pointer
1082 if (dib)
1083 {
1084 Size.cx = bm.bmWidth;
1085 Size.cy = abs(bm.bmHeight);
1086 res = IntCreateBitmap(Size, bm.bmWidthBytes,
1087 BitmapFormat(bi->biBitCount * bi->biPlanes, bi->biCompression),
1088 BMF_DONTCACHE | BMF_USERMEM | BMF_NOZEROINIT |
1089 (bi->biHeight < 0 ? BMF_TOPDOWN : 0),
1090 bm.bmBits);
1091 if (! res)
1092 {
1093 if (lpRGB != bmi->bmiColors)
1094 {
1095 ExFreePool(lpRGB);
1096 }
1097 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
1098 return NULL;
1099 }
1100 bmp = BITMAPOBJ_LockBitmap(res);
1101 if (NULL == bmp)
1102 {
1103 if (lpRGB != bmi->bmiColors)
1104 {
1105 ExFreePool(lpRGB);
1106 }
1107 SetLastWin32Error(ERROR_INVALID_HANDLE);
1108 NtGdiDeleteObject(bmp);
1109 return NULL;
1110 }
1111 bmp->dib = (DIBSECTION *) dib;
1112 bmp->flFlags = BITMAPOBJ_IS_APIBITMAP;
1113
1114 /* WINE NOTE: WINE makes use of a colormap, which is a color translation table between the DIB and the X physical
1115 device. Obviously, this is left out of the ReactOS implementation. Instead, we call
1116 NtGdiSetDIBColorTable. */
1117 if(bi->biBitCount == 1) { Entries = 2; } else
1118 if(bi->biBitCount == 4) { Entries = 16; } else
1119 if(bi->biBitCount == 8) { Entries = 256; }
1120
1121 if (Entries)
1122 bmp->hDIBPalette = PALETTE_AllocPaletteIndexedRGB(Entries, lpRGB);
1123 else
1124 bmp->hDIBPalette = PALETTE_AllocPalette(PAL_BITFIELDS, 0, NULL,
1125 dib->dsBitfields[0],
1126 dib->dsBitfields[1],
1127 dib->dsBitfields[2]);
1128 }
1129
1130 // Clean up in case of errors
1131 if (!res || !bmp || !dib || !bm.bmBits)
1132 {
1133 DPRINT("got an error res=%08x, bmp=%p, dib=%p, bm.bmBits=%p\n", res, bmp, dib, bm.bmBits);
1134 /* if (bm.bmBits)
1135 {
1136 if (section)
1137 UnmapViewOfFile(bm.bmBits), bm.bmBits = NULL;
1138 else if (!offset)
1139 VirtualFree(bm.bmBits, 0L, MEM_RELEASE), bm.bmBits = NULL;
1140 } */
1141
1142 if (dib) { ExFreePool(dib); dib = NULL; }
1143 if (bmp) { bmp = NULL; }
1144 if (res) { BITMAPOBJ_FreeBitmap(res); res = 0; }
1145 }
1146
1147 if (lpRGB != bmi->bmiColors)
1148 {
1149 ExFreePool(lpRGB);
1150 }
1151
1152 if (bmp)
1153 {
1154 BITMAPOBJ_UnlockBitmap(bmp);
1155 }
1156
1157 // Return BITMAP handle and storage location
1158 if (NULL != bm.bmBits && NULL != bits)
1159 {
1160 *bits = bm.bmBits;
1161 }
1162
1163 return res;
1164 }
1165
1166 /***********************************************************************
1167 * DIB_GetDIBWidthBytes
1168 *
1169 * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
1170 * http://www.microsoft.com/msdn/sdk/platforms/doc/sdk/win32/struc/src/str01.htm
1171 * 11/16/1999 (RJJ) lifted from wine
1172 */
1173 INT FASTCALL DIB_GetDIBWidthBytes (INT width, INT depth)
1174 {
1175 return ((width * depth + 31) & ~31) >> 3;
1176 }
1177
1178 /***********************************************************************
1179 * DIB_GetDIBImageBytes
1180 *
1181 * Return the number of bytes used to hold the image in a DIB bitmap.
1182 * 11/16/1999 (RJJ) lifted from wine
1183 */
1184
1185 INT STDCALL DIB_GetDIBImageBytes (INT width, INT height, INT depth)
1186 {
1187 return DIB_GetDIBWidthBytes( width, depth ) * (height < 0 ? -height : height);
1188 }
1189
1190 /***********************************************************************
1191 * DIB_BitmapInfoSize
1192 *
1193 * Return the size of the bitmap info structure including color table.
1194 * 11/16/1999 (RJJ) lifted from wine
1195 */
1196
1197 INT FASTCALL DIB_BitmapInfoSize (const BITMAPINFO * info, WORD coloruse)
1198 {
1199 int colors;
1200
1201 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
1202 {
1203 BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)info;
1204 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
1205 return sizeof(BITMAPCOREHEADER) + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
1206 }
1207 else /* assume BITMAPINFOHEADER */
1208 {
1209 colors = info->bmiHeader.biClrUsed;
1210 if (!colors && (info->bmiHeader.biBitCount <= 8)) colors = 1 << info->bmiHeader.biBitCount;
1211 return sizeof(BITMAPINFOHEADER) + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
1212 }
1213 }
1214
1215 /*
1216 * DIB_GetBitmapInfo is complete copy of wine cvs 2/9-2006
1217 * from file dib.c from gdi32.dll or orginal version
1218 * did not calc the info right for some headers.
1219 */
1220
1221 INT STDCALL
1222 DIB_GetBitmapInfo( const BITMAPINFOHEADER *header,
1223 PLONG width,
1224 PLONG height,
1225 PWORD planes,
1226 PWORD bpp,
1227 PLONG compr,
1228 PLONG size )
1229 {
1230
1231 if (header->biSize == sizeof(BITMAPCOREHEADER))
1232 {
1233 BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)header;
1234 *width = core->bcWidth;
1235 *height = core->bcHeight;
1236 *planes = core->bcPlanes;
1237 *bpp = core->bcBitCount;
1238 *compr = 0;
1239 *size = 0;
1240 return 0;
1241 }
1242
1243 if (header->biSize == sizeof(BITMAPINFOHEADER))
1244 {
1245 *width = header->biWidth;
1246 *height = header->biHeight;
1247 *planes = header->biPlanes;
1248 *bpp = header->biBitCount;
1249 *compr = header->biCompression;
1250 *size = header->biSizeImage;
1251 return 1;
1252 }
1253
1254 if (header->biSize == sizeof(BITMAPV4HEADER))
1255 {
1256 BITMAPV4HEADER *v4hdr = (BITMAPV4HEADER *)header;
1257 *width = v4hdr->bV4Width;
1258 *height = v4hdr->bV4Height;
1259 *planes = v4hdr->bV4Planes;
1260 *bpp = v4hdr->bV4BitCount;
1261 *compr = v4hdr->bV4V4Compression;
1262 *size = v4hdr->bV4SizeImage;
1263 return 4;
1264 }
1265
1266 if (header->biSize == sizeof(BITMAPV5HEADER))
1267 {
1268 BITMAPV5HEADER *v5hdr = (BITMAPV5HEADER *)header;
1269 *width = v5hdr->bV5Width;
1270 *height = v5hdr->bV5Height;
1271 *planes = v5hdr->bV5Planes;
1272 *bpp = v5hdr->bV5BitCount;
1273 *compr = v5hdr->bV5Compression;
1274 *size = v5hdr->bV5SizeImage;
1275 return 5;
1276 }
1277 DPRINT("(%ld): wrong size for header\n", header->biSize );
1278 return -1;
1279 }
1280
1281 // Converts a Device Independent Bitmap (DIB) to a Device Dependant Bitmap (DDB)
1282 // The specified Device Context (DC) defines what the DIB should be converted to
1283 PBITMAPOBJ FASTCALL DIBtoDDB(HGLOBAL hPackedDIB, HDC hdc) // FIXME: This should be removed. All references to this function should
1284 // change to NtGdiSetDIBits
1285 {
1286 HBITMAP hBmp = 0;
1287 PBITMAPOBJ pBmp = NULL;
1288 DIBSECTION *dib;
1289 LPBYTE pbits = NULL;
1290
1291 // Get a pointer to the packed DIB's data
1292 // pPackedDIB = (LPBYTE)GlobalLock(hPackedDIB);
1293 dib = hPackedDIB;
1294
1295 pbits = (LPBYTE)(dib + DIB_BitmapInfoSize((BITMAPINFO*)&dib->dsBmih, DIB_RGB_COLORS));
1296
1297 // Create a DDB from the DIB
1298 hBmp = NtGdiCreateDIBitmap ( hdc, &dib->dsBmih, CBM_INIT,
1299 (LPVOID)pbits, (BITMAPINFO*)&dib->dsBmih, DIB_RGB_COLORS);
1300
1301 // GlobalUnlock(hPackedDIB);
1302
1303 // Retrieve the internal Pixmap from the DDB
1304 pBmp = BITMAPOBJ_LockBitmap(hBmp);
1305
1306 return pBmp;
1307 }
1308
1309 RGBQUAD * FASTCALL
1310 DIB_MapPaletteColors(PDC dc, CONST BITMAPINFO* lpbmi)
1311 {
1312 RGBQUAD *lpRGB;
1313 ULONG nNumColors,i;
1314 USHORT *lpIndex;
1315 PPALGDI palGDI;
1316
1317 palGDI = PALETTE_LockPalette(dc->w.hPalette);
1318
1319 if (NULL == palGDI)
1320 {
1321 // RELEASEDCINFO(hDC);
1322 return NULL;
1323 }
1324
1325 if (palGDI->Mode != PAL_INDEXED)
1326 {
1327 PALETTE_UnlockPalette(palGDI);
1328 palGDI = PALETTE_LockPalette(dc->PalIndexed);
1329 if (palGDI->Mode != PAL_INDEXED)
1330 {
1331 return NULL;
1332 }
1333 }
1334
1335 nNumColors = 1 << lpbmi->bmiHeader.biBitCount;
1336 if (lpbmi->bmiHeader.biClrUsed)
1337 {
1338 nNumColors = min(nNumColors, lpbmi->bmiHeader.biClrUsed);
1339 }
1340
1341 lpRGB = (RGBQUAD *)ExAllocatePoolWithTag(PagedPool, sizeof(RGBQUAD) * nNumColors, TAG_COLORMAP);
1342 if (lpRGB == NULL)
1343 {
1344 PALETTE_UnlockPalette(palGDI);
1345 return NULL;
1346 }
1347
1348 lpIndex = (USHORT *)&lpbmi->bmiColors[0];
1349
1350 for (i = 0; i < nNumColors; i++)
1351 {
1352 lpRGB[i].rgbRed = palGDI->IndexedColors[*lpIndex].peRed;
1353 lpRGB[i].rgbGreen = palGDI->IndexedColors[*lpIndex].peGreen;
1354 lpRGB[i].rgbBlue = palGDI->IndexedColors[*lpIndex].peBlue;
1355 lpIndex++;
1356 }
1357 // RELEASEDCINFO(hDC);
1358 PALETTE_UnlockPalette(palGDI);
1359
1360 return lpRGB;
1361 }
1362
1363 HPALETTE FASTCALL
1364 BuildDIBPalette (CONST BITMAPINFO *bmi, PINT paletteType)
1365 {
1366 BYTE bits;
1367 ULONG ColorCount;
1368 PALETTEENTRY *palEntries = NULL;
1369 HPALETTE hPal;
1370 ULONG RedMask, GreenMask, BlueMask;
1371
1372 // Determine Bits Per Pixel
1373 bits = bmi->bmiHeader.biBitCount;
1374
1375 // Determine paletteType from Bits Per Pixel
1376 if (bits <= 8)
1377 {
1378 *paletteType = PAL_INDEXED;
1379 RedMask = GreenMask = BlueMask = 0;
1380 }
1381 else if(bits < 24)
1382 {
1383 *paletteType = PAL_BITFIELDS;
1384 RedMask = 0xf800;
1385 GreenMask = 0x07e0;
1386 BlueMask = 0x001f;
1387 }
1388 else
1389 {
1390 *paletteType = PAL_BGR;
1391 RedMask = 0xff0000;
1392 GreenMask = 0x00ff00;
1393 BlueMask = 0x0000ff;
1394 }
1395
1396 if (bmi->bmiHeader.biClrUsed == 0)
1397 {
1398 ColorCount = 1 << bmi->bmiHeader.biBitCount;
1399 }
1400 else
1401 {
1402 ColorCount = bmi->bmiHeader.biClrUsed;
1403 }
1404
1405 if (PAL_INDEXED == *paletteType)
1406 {
1407 hPal = PALETTE_AllocPaletteIndexedRGB(ColorCount, (RGBQUAD*)bmi->bmiColors);
1408 }
1409 else
1410 {
1411 hPal = PALETTE_AllocPalette(*paletteType, ColorCount,
1412 (ULONG*) palEntries,
1413 RedMask, GreenMask, BlueMask );
1414 }
1415
1416 return hPal;
1417 }
1418
1419 /* EOF */