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