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