- Fix bpp count in CreateDIBitmap.
[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) // CreateBitmap
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 = 1;
1033 Bmp = IntCreateDIBitmap(Dc, cx, cy, bpp, fInit, pjInit, pbmi, iUsage);
1034
1035 DC_UnlockDc(Dc);
1036 NtGdiDeleteObjectApp(hDc);
1037 }
1038 else // CreateCompatibleBitmap
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 {
1054 if (Dc->DC_Type != DC_TYPE_MEMORY )
1055 bpp = IntGdiGetDeviceCaps(Dc, BITSPIXEL);
1056 else
1057 {
1058 DIBSECTION dibs;
1059 INT Count;
1060 BITMAPOBJ *BitmapObject = BITMAPOBJ_LockBitmap(Dc->w.hBitmap);
1061 Count = BITMAP_GetObject(BitmapObject, sizeof(dibs), &dibs);
1062 if (!Count)
1063 bpp = 1;
1064 else
1065 {
1066 if (Count == sizeof(BITMAP))
1067 /* A device-dependent bitmap is selected in the DC */
1068 bpp = dibs.dsBm.bmBitsPixel;
1069 else
1070 /* A DIB section is selected in the DC */
1071 bpp = dibs.dsBmih.biBitCount;
1072 }
1073 BITMAPOBJ_UnlockBitmap(BitmapObject);
1074 }
1075 }
1076 Bmp = IntCreateDIBitmap(Dc, cx, cy, bpp, fInit, pjInit, pbmi, iUsage);
1077 DC_UnlockDc(Dc);
1078 }
1079 return Bmp;
1080 }
1081
1082
1083 HBITMAP STDCALL NtGdiCreateDIBSection(HDC hDC,
1084 IN OPTIONAL HANDLE hSection,
1085 IN DWORD dwOffset,
1086 IN LPBITMAPINFO bmi,
1087 DWORD Usage,
1088 IN UINT cjHeader,
1089 IN FLONG fl,
1090 IN ULONG_PTR dwColorSpace,
1091 PVOID *Bits)
1092 {
1093 HBITMAP hbitmap = 0;
1094 DC *dc;
1095 BOOL bDesktopDC = FALSE;
1096
1097 if (!bmi) return hbitmap; // Make sure.
1098
1099 // If the reference hdc is null, take the desktop dc
1100 if (hDC == 0)
1101 {
1102 hDC = NtGdiCreateCompatibleDC(0);
1103 bDesktopDC = TRUE;
1104 }
1105
1106 if ((dc = DC_LockDc(hDC)))
1107 {
1108 hbitmap = DIB_CreateDIBSection ( dc, (BITMAPINFO*)bmi, Usage, Bits,
1109 hSection, dwOffset, 0);
1110 DC_UnlockDc(dc);
1111 }
1112 else
1113 {
1114 SetLastWin32Error(ERROR_INVALID_HANDLE);
1115 }
1116
1117 if (bDesktopDC)
1118 NtGdiDeleteObjectApp(hDC);
1119
1120 return hbitmap;
1121 }
1122
1123 HBITMAP STDCALL
1124 DIB_CreateDIBSection(
1125 PDC dc, BITMAPINFO *bmi, UINT usage,
1126 LPVOID *bits, HANDLE section,
1127 DWORD offset, DWORD ovr_pitch)
1128 {
1129 HBITMAP res = 0;
1130 BITMAPOBJ *bmp = NULL;
1131 DIBSECTION *dib = NULL;
1132
1133 // Fill BITMAP32 structure with DIB data
1134 BITMAPINFOHEADER *bi = &bmi->bmiHeader;
1135 INT effHeight;
1136 ULONG totalSize;
1137 BITMAP bm;
1138 SIZEL Size;
1139 RGBQUAD *lpRGB;
1140
1141 DPRINT("format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n",
1142 bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
1143 bi->biSizeImage, bi->biClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1144
1145 /* CreateDIBSection should fail for compressed formats */
1146 if (bi->biCompression == BI_RLE4 || bi->biCompression == BI_RLE8)
1147 {
1148 return (HBITMAP)NULL;
1149 }
1150
1151 effHeight = bi->biHeight >= 0 ? bi->biHeight : -bi->biHeight;
1152 bm.bmType = 0;
1153 bm.bmWidth = bi->biWidth;
1154 bm.bmHeight = effHeight;
1155 bm.bmWidthBytes = ovr_pitch ? ovr_pitch : (ULONG) DIB_GetDIBWidthBytes(bm.bmWidth, bi->biBitCount);
1156
1157 bm.bmPlanes = bi->biPlanes;
1158 bm.bmBitsPixel = bi->biBitCount;
1159 bm.bmBits = NULL;
1160
1161 // Get storage location for DIB bits. Only use biSizeImage if it's valid and
1162 // we're dealing with a compressed bitmap. Otherwise, use width * height.
1163 totalSize = bi->biSizeImage && bi->biCompression != BI_RGB
1164 ? bi->biSizeImage : (ULONG) (bm.bmWidthBytes * effHeight);
1165
1166 if (section)
1167 {
1168 /* bm.bmBits = MapViewOfFile(section, FILE_MAP_ALL_ACCESS,
1169 0L, offset, totalSize); */
1170 DbgPrint("DIB_CreateDIBSection: Cannot yet handle section DIBs\n");
1171 SetLastWin32Error(ERROR_CALL_NOT_IMPLEMENTED);
1172 return 0;
1173 }
1174 else if (ovr_pitch && offset)
1175 bm.bmBits = (LPVOID) offset;
1176 else {
1177 offset = 0;
1178 bm.bmBits = EngAllocUserMem(totalSize, 0);
1179 }
1180
1181 if(usage == DIB_PAL_COLORS)
1182 lpRGB = DIB_MapPaletteColors(dc, bmi);
1183 else
1184 lpRGB = bmi->bmiColors;
1185
1186 // Allocate Memory for DIB and fill structure
1187 if (bm.bmBits)
1188 {
1189 dib = ExAllocatePoolWithTag(PagedPool, sizeof(DIBSECTION), TAG_DIB);
1190 if (dib != NULL) RtlZeroMemory(dib, sizeof(DIBSECTION));
1191 }
1192
1193 if (dib)
1194 {
1195 dib->dsBm = bm;
1196 /* Set dsBitfields values */
1197 if ( usage == DIB_PAL_COLORS || bi->biBitCount <= 8)
1198 {
1199 dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
1200 }
1201 else switch(bi->biBitCount)
1202 {
1203 case 16:
1204 dib->dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)lpRGB : 0x7c00;
1205 dib->dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)lpRGB + 1) : 0x03e0;
1206 dib->dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)lpRGB + 2) : 0x001f;
1207 break;
1208
1209 case 24:
1210 dib->dsBitfields[0] = 0xff0000;
1211 dib->dsBitfields[1] = 0x00ff00;
1212 dib->dsBitfields[2] = 0x0000ff;
1213 break;
1214
1215 case 32:
1216 dib->dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)lpRGB : 0xff0000;
1217 dib->dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)lpRGB + 1) : 0x00ff00;
1218 dib->dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)lpRGB + 2) : 0x0000ff;
1219 break;
1220 }
1221 dib->dshSection = section;
1222 dib->dsOffset = offset;
1223
1224 // Create Device Dependent Bitmap and add DIB pointer
1225 Size.cx = bm.bmWidth;
1226 Size.cy = abs(bm.bmHeight);
1227 res = IntCreateBitmap(Size, bm.bmWidthBytes,
1228 BitmapFormat(bi->biBitCount * bi->biPlanes, bi->biCompression),
1229 BMF_DONTCACHE | BMF_USERMEM | BMF_NOZEROINIT |
1230 (bi->biHeight < 0 ? BMF_TOPDOWN : 0),
1231 bm.bmBits);
1232 if (! res)
1233 {
1234 if (lpRGB != bmi->bmiColors)
1235 {
1236 ExFreePoolWithTag(lpRGB, TAG_COLORMAP);
1237 }
1238 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
1239 return NULL;
1240 }
1241 bmp = BITMAPOBJ_LockBitmap(res);
1242 if (NULL == bmp)
1243 {
1244 if (lpRGB != bmi->bmiColors)
1245 {
1246 ExFreePoolWithTag(lpRGB, TAG_COLORMAP);
1247 }
1248 SetLastWin32Error(ERROR_INVALID_HANDLE);
1249 NtGdiDeleteObject(bmp);
1250 return NULL;
1251 }
1252 bmp->dib = (DIBSECTION *) dib;
1253 bmp->flFlags = BITMAPOBJ_IS_APIBITMAP;
1254
1255 /* WINE NOTE: WINE makes use of a colormap, which is a color translation table between the DIB and the X physical
1256 device. Obviously, this is left out of the ReactOS implementation. Instead, we call
1257 NtGdiSetDIBColorTable. */
1258 bi->biClrUsed = 0;
1259 if(bi->biBitCount == 1) { bi->biClrUsed = 2; } else
1260 if(bi->biBitCount == 4) { bi->biClrUsed = 16; } else
1261 if(bi->biBitCount == 8) { bi->biClrUsed = 256; }
1262
1263 if (bi->biClrUsed != 0)
1264 bmp->hDIBPalette = PALETTE_AllocPaletteIndexedRGB(bi->biClrUsed, lpRGB);
1265 else
1266 bmp->hDIBPalette = PALETTE_AllocPalette(PAL_BITFIELDS, 0, NULL,
1267 dib->dsBitfields[0],
1268 dib->dsBitfields[1],
1269 dib->dsBitfields[2]);
1270
1271 dib->dsBmih = *bi;
1272 dib->dsBmih.biSizeImage = totalSize;
1273 }
1274
1275 // Clean up in case of errors
1276 if (!res || !bmp || !dib || !bm.bmBits)
1277 {
1278 DPRINT("got an error res=%08x, bmp=%p, dib=%p, bm.bmBits=%p\n", res, bmp, dib, bm.bmBits);
1279 /* if (bm.bmBits)
1280 {
1281 if (section)
1282 UnmapViewOfFile(bm.bmBits), bm.bmBits = NULL;
1283 else if (!offset)
1284 VirtualFree(bm.bmBits, 0L, MEM_RELEASE), bm.bmBits = NULL;
1285 } */
1286
1287 if (dib) { ExFreePoolWithTag(dib, TAG_DIB); dib = NULL; }
1288 if (bmp) { bmp = NULL; }
1289 if (res) { BITMAPOBJ_FreeBitmapByHandle(res); res = 0; }
1290 }
1291
1292 if (lpRGB != bmi->bmiColors)
1293 {
1294 ExFreePoolWithTag(lpRGB, TAG_COLORMAP);
1295 }
1296
1297 if (bmp)
1298 {
1299 BITMAPOBJ_UnlockBitmap(bmp);
1300 }
1301
1302 // Return BITMAP handle and storage location
1303 if (NULL != bm.bmBits && NULL != bits)
1304 {
1305 *bits = bm.bmBits;
1306 }
1307
1308 return res;
1309 }
1310
1311 /***********************************************************************
1312 * DIB_GetDIBWidthBytes
1313 *
1314 * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
1315 * http://www.microsoft.com/msdn/sdk/platforms/doc/sdk/win32/struc/src/str01.htm
1316 * 11/16/1999 (RJJ) lifted from wine
1317 */
1318 INT FASTCALL DIB_GetDIBWidthBytes (INT width, INT depth)
1319 {
1320 return ((width * depth + 31) & ~31) >> 3;
1321 }
1322
1323 /***********************************************************************
1324 * DIB_GetDIBImageBytes
1325 *
1326 * Return the number of bytes used to hold the image in a DIB bitmap.
1327 * 11/16/1999 (RJJ) lifted from wine
1328 */
1329
1330 INT STDCALL DIB_GetDIBImageBytes (INT width, INT height, INT depth)
1331 {
1332 return DIB_GetDIBWidthBytes( width, depth ) * (height < 0 ? -height : height);
1333 }
1334
1335 /***********************************************************************
1336 * DIB_BitmapInfoSize
1337 *
1338 * Return the size of the bitmap info structure including color table.
1339 * 11/16/1999 (RJJ) lifted from wine
1340 */
1341
1342 INT FASTCALL DIB_BitmapInfoSize (const BITMAPINFO * info, WORD coloruse)
1343 {
1344 int colors;
1345
1346 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
1347 {
1348 BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)info;
1349 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
1350 return sizeof(BITMAPCOREHEADER) + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
1351 }
1352 else /* assume BITMAPINFOHEADER */
1353 {
1354 colors = info->bmiHeader.biClrUsed;
1355 if (!colors && (info->bmiHeader.biBitCount <= 8)) colors = 1 << info->bmiHeader.biBitCount;
1356 return sizeof(BITMAPINFOHEADER) + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
1357 }
1358 }
1359
1360 RGBQUAD * FASTCALL
1361 DIB_MapPaletteColors(PDC dc, CONST BITMAPINFO* lpbmi)
1362 {
1363 RGBQUAD *lpRGB;
1364 ULONG nNumColors,i;
1365 USHORT *lpIndex;
1366 PPALGDI palGDI;
1367
1368 palGDI = PALETTE_LockPalette(dc->DcLevel.hpal);
1369
1370 if (NULL == palGDI)
1371 {
1372 return NULL;
1373 }
1374
1375 if (palGDI->Mode != PAL_INDEXED)
1376 {
1377 PALETTE_UnlockPalette(palGDI);
1378 return NULL;
1379 }
1380
1381 nNumColors = 1 << lpbmi->bmiHeader.biBitCount;
1382 if (lpbmi->bmiHeader.biClrUsed)
1383 {
1384 nNumColors = min(nNumColors, lpbmi->bmiHeader.biClrUsed);
1385 }
1386
1387 lpRGB = (RGBQUAD *)ExAllocatePoolWithTag(PagedPool, sizeof(RGBQUAD) * nNumColors, TAG_COLORMAP);
1388 if (lpRGB == NULL)
1389 {
1390 PALETTE_UnlockPalette(palGDI);
1391 return NULL;
1392 }
1393
1394 lpIndex = (USHORT *)&lpbmi->bmiColors[0];
1395
1396 for (i = 0; i < nNumColors; i++)
1397 {
1398 lpRGB[i].rgbRed = palGDI->IndexedColors[*lpIndex].peRed;
1399 lpRGB[i].rgbGreen = palGDI->IndexedColors[*lpIndex].peGreen;
1400 lpRGB[i].rgbBlue = palGDI->IndexedColors[*lpIndex].peBlue;
1401 lpRGB[i].rgbReserved = 0;
1402 lpIndex++;
1403 }
1404 PALETTE_UnlockPalette(palGDI);
1405
1406 return lpRGB;
1407 }
1408
1409 HPALETTE FASTCALL
1410 BuildDIBPalette (CONST BITMAPINFO *bmi, PINT paletteType)
1411 {
1412 BYTE bits;
1413 ULONG ColorCount;
1414 PALETTEENTRY *palEntries = NULL;
1415 HPALETTE hPal;
1416 ULONG RedMask, GreenMask, BlueMask;
1417
1418 // Determine Bits Per Pixel
1419 bits = bmi->bmiHeader.biBitCount;
1420
1421 // Determine paletteType from Bits Per Pixel
1422 if (bits <= 8)
1423 {
1424 *paletteType = PAL_INDEXED;
1425 RedMask = GreenMask = BlueMask = 0;
1426 }
1427 else if(bmi->bmiHeader.biCompression == BI_BITFIELDS)
1428 {
1429 *paletteType = PAL_BITFIELDS;
1430 RedMask = ((ULONG *)bmi->bmiColors)[0];
1431 GreenMask = ((ULONG *)bmi->bmiColors)[1];
1432 BlueMask = ((ULONG *)bmi->bmiColors)[2];
1433 }
1434 else if(bits < 24)
1435 {
1436 *paletteType = PAL_BITFIELDS;
1437 RedMask = 0x7c00;
1438 GreenMask = 0x03e0;
1439 BlueMask = 0x001f;
1440 }
1441 else
1442 {
1443 *paletteType = PAL_BGR;
1444 RedMask = 0xff0000;
1445 GreenMask = 0x00ff00;
1446 BlueMask = 0x0000ff;
1447 }
1448
1449 if (bmi->bmiHeader.biClrUsed == 0)
1450 {
1451 ColorCount = 1 << bmi->bmiHeader.biBitCount;
1452 }
1453 else
1454 {
1455 ColorCount = bmi->bmiHeader.biClrUsed;
1456 }
1457
1458 if (PAL_INDEXED == *paletteType)
1459 {
1460 hPal = PALETTE_AllocPaletteIndexedRGB(ColorCount, (RGBQUAD*)bmi->bmiColors);
1461 }
1462 else
1463 {
1464 hPal = PALETTE_AllocPalette(*paletteType, ColorCount,
1465 (ULONG*) palEntries,
1466 RedMask, GreenMask, BlueMask );
1467 }
1468
1469 return hPal;
1470 }
1471
1472 /* EOF */