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