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