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