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