The real, definitive, Visual C++ support branch. Accept no substitutes
[reactos.git] / subsystems / win32 / win32k / objects / dibobj.c
1 /*
2 * $Id$
3 *
4 * ReactOS W32 Subsystem
5 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include <w32k.h>
23
24 #define NDEBUG
25 #include <debug.h>
26
27 UINT STDCALL
28 IntSetDIBColorTable(HDC hDC, UINT StartIndex, UINT Entries, CONST RGBQUAD *Colors)
29 {
30 PDC dc;
31 PBITMAPOBJ BitmapObj;
32 PPALGDI PalGDI;
33 UINT Index;
34
35 if (!(dc = DC_LockDc(hDC))) return 0;
36 if (dc->DC_Type == DC_TYPE_INFO)
37 {
38 DC_UnlockDc(dc);
39 return 0;
40 }
41
42 BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap);
43 if (BitmapObj == NULL)
44 {
45 DC_UnlockDc(dc);
46 SetLastWin32Error(ERROR_INVALID_PARAMETER);
47 return 0;
48 }
49
50 if (BitmapObj->dib == NULL)
51 {
52 BITMAPOBJ_UnlockBitmap(BitmapObj);
53 DC_UnlockDc(dc);
54 SetLastWin32Error(ERROR_INVALID_PARAMETER);
55 return 0;
56 }
57
58 if (BitmapObj->dib->dsBmih.biBitCount <= 8 &&
59 StartIndex < (1 << BitmapObj->dib->dsBmih.biBitCount))
60 {
61 if (StartIndex + Entries > (1 << BitmapObj->dib->dsBmih.biBitCount))
62 Entries = (1 << BitmapObj->dib->dsBmih.biBitCount) - StartIndex;
63
64 PalGDI = PALETTE_LockPalette(BitmapObj->hDIBPalette);
65 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
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
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
545 {
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
810 if (!Bits || !BitsInfo)
811 {
812 SetLastWin32Error(ERROR_INVALID_PARAMETER);
813 return 0;
814 }
815
816 hdcMem = NtGdiCreateCompatibleDC(hDC);
817 if (hdcMem == NULL)
818 {
819 DPRINT1("NtGdiCreateCompatibleDC fail create hdc\n");
820 return 0;
821 }
822
823 hBitmap = NtGdiCreateCompatibleBitmap(hDC, BitsInfo->bmiHeader.biWidth,
824 BitsInfo->bmiHeader.biHeight);
825 if (hBitmap == NULL)
826 {
827 DPRINT1("NtGdiCreateCompatibleBitmap fail create bitmap\n");
828 DPRINT1("hDC : 0x%08x \n", hDC);
829 DPRINT1("BitsInfo->bmiHeader.biWidth : 0x%08x \n", BitsInfo->bmiHeader.biWidth);
830 DPRINT1("BitsInfo->bmiHeader.biHeight : 0x%08x \n", BitsInfo->bmiHeader.biHeight);
831 return 0;
832 }
833
834 /* Select the bitmap into hdcMem, and save a handle to the old bitmap */
835 hOldBitmap = NtGdiSelectBitmap(hdcMem, hBitmap);
836
837 if(Usage == DIB_PAL_COLORS)
838 {
839 hPal = NtGdiGetDCObject(hDC, GDI_OBJECT_TYPE_PALETTE);
840 hPal = GdiSelectPalette(hdcMem, hPal, FALSE);
841 }
842
843 if (BitsInfo->bmiHeader.biCompression == BI_RLE4 ||
844 BitsInfo->bmiHeader.biCompression == BI_RLE8)
845 {
846 /* copy existing bitmap from destination dc */
847 if (SrcWidth == DestWidth && SrcHeight == DestHeight)
848 NtGdiBitBlt(hdcMem, XSrc, abs(BitsInfo->bmiHeader.biHeight) - SrcHeight - YSrc,
849 SrcWidth, SrcHeight, hDC, XDest, YDest, ROP, 0, 0);
850 else
851 NtGdiStretchBlt(hdcMem, XSrc, abs(BitsInfo->bmiHeader.biHeight) - SrcHeight - YSrc,
852 SrcWidth, SrcHeight, hDC, XDest, YDest, DestWidth, DestHeight,
853 ROP, 0);
854 }
855
856 pDC = DC_LockDc(hdcMem);
857 if (pDC != NULL)
858 {
859 /* Note BitsInfo->bmiHeader.biHeight is the number of scanline,
860 * if it negitve we getting to many scanline for scanline is UINT not
861 * a INT, so we need make the negtive value to positve and that make the
862 * count correct for negtive bitmap, TODO : we need testcase for this api */
863
864 IntSetDIBits(pDC, hBitmap, 0, abs(BitsInfo->bmiHeader.biHeight), Bits,
865 BitsInfo, Usage);
866
867 DC_UnlockDc(pDC);
868 }
869
870
871 /* Origin for DIBitmap may be bottom left (positive biHeight) or top
872 left (negative biHeight) */
873 if (SrcWidth == DestWidth && SrcHeight == DestHeight)
874 NtGdiBitBlt(hDC, XDest, YDest, DestWidth, DestHeight,
875 hdcMem, XSrc, abs(BitsInfo->bmiHeader.biHeight) - SrcHeight - YSrc,
876 ROP, 0, 0);
877 else
878 NtGdiStretchBlt(hDC, XDest, YDest, DestWidth, DestHeight,
879 hdcMem, XSrc, abs(BitsInfo->bmiHeader.biHeight) - SrcHeight - YSrc,
880 SrcWidth, SrcHeight, ROP, 0);
881
882 /* cleanup */
883 if(hPal)
884 GdiSelectPalette(hdcMem, hPal, FALSE);
885
886 if (hOldBitmap)
887 NtGdiSelectBitmap(hdcMem, hOldBitmap);
888
889 NtGdiDeleteObjectApp(hdcMem);
890
891 NtGdiDeleteObject(hBitmap);
892
893 return SrcHeight;
894 }
895
896
897 HBITMAP
898 FASTCALL
899 IntCreateDIBitmap(PDC Dc,
900 INT width,
901 INT height,
902 UINT bpp,
903 DWORD init,
904 LPBYTE bits,
905 PBITMAPINFO data,
906 DWORD coloruse)
907 {
908 HBITMAP handle;
909 BOOL fColor;
910
911 // Check if we should create a monochrome or color bitmap. We create a monochrome bitmap only if it has exactly 2
912 // colors, which are black followed by white, nothing else. In all other cases, we create a color bitmap.
913
914 if (bpp != 1) fColor = TRUE;
915 else if ((coloruse != DIB_RGB_COLORS) || (init != CBM_INIT) || !data) fColor = FALSE;
916 else
917 {
918 if (data->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
919 {
920 const RGBQUAD *rgb = data->bmiColors;
921 DWORD col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
922
923 // Check if the first color of the colormap is black
924 if ((col == RGB(0, 0, 0)))
925 {
926 rgb++;
927 col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
928
929 // If the second color is white, create a monochrome bitmap
930 fColor = (col != RGB(0xff,0xff,0xff));
931 }
932 else fColor = TRUE;
933 }
934 else if (data->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
935 {
936 RGBTRIPLE *rgb = ((BITMAPCOREINFO *)data)->bmciColors;
937 DWORD col = RGB( rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue);
938
939 if ((col == RGB(0,0,0)))
940 {
941 rgb++;
942 col = RGB( rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue );
943 fColor = (col != RGB(0xff,0xff,0xff));
944 }
945 else fColor = TRUE;
946 }
947 else
948 {
949 DPRINT("(%ld): wrong size for data\n", data->bmiHeader.biSize );
950 return 0;
951 }
952 }
953
954 // Now create the bitmap
955 if (fColor)
956 {
957 handle = IntCreateCompatibleBitmap(Dc, width, height);
958 }
959 else
960 {
961 handle = IntGdiCreateBitmap(width,
962 height,
963 1,
964 1,
965 NULL);
966 }
967
968 if (height < 0)
969 height = -height;
970
971 if (NULL != handle && CBM_INIT == init)
972 {
973 IntSetDIBits(Dc, handle, 0, height, bits, data, coloruse);
974 }
975
976 return handle;
977 }
978
979 // The CreateDIBitmap function creates a device-dependent bitmap (DDB) from a DIB and, optionally, sets the bitmap bits
980 // The DDB that is created will be whatever bit depth your reference DC is
981 HBITMAP
982 APIENTRY
983 NtGdiCreateDIBitmapInternal(IN HDC hDc,
984 IN INT cx,
985 IN INT cy,
986 IN DWORD fInit,
987 IN OPTIONAL LPBYTE pjInit,
988 IN OPTIONAL LPBITMAPINFO pbmi,
989 IN DWORD iUsage,
990 IN UINT cjMaxInitInfo,
991 IN UINT cjMaxBits,
992 IN FLONG fl,
993 IN HANDLE hcmXform)
994 {
995 PDC Dc;
996 HBITMAP Bmp;
997
998 if (!hDc)
999 {
1000 hDc = IntGdiCreateDC(NULL, NULL, NULL, NULL,FALSE);
1001 if (!hDc)
1002 {
1003 SetLastWin32Error(ERROR_INVALID_HANDLE);
1004 return NULL;
1005 }
1006
1007 Dc = DC_LockDc(hDc);
1008 if (!Dc)
1009 {
1010 NtGdiDeleteObjectApp(hDc);
1011 SetLastWin32Error(ERROR_INVALID_HANDLE);
1012 return NULL;
1013 }
1014
1015 cjMaxInitInfo = 1;
1016 Bmp = IntCreateDIBitmap(Dc, cx, cy, cjMaxInitInfo, fInit, pjInit, pbmi, iUsage);
1017
1018 DC_UnlockDc(Dc);
1019 NtGdiDeleteObjectApp(hDc);
1020 }
1021 else
1022 {
1023 Dc = DC_LockDc(hDc);
1024 if (!Dc)
1025 {
1026 SetLastWin32Error(ERROR_INVALID_HANDLE);
1027 return NULL;
1028 }
1029
1030 Bmp = IntCreateDIBitmap(Dc, cx, cy, cjMaxInitInfo, fInit, pjInit, pbmi, iUsage);
1031 DC_UnlockDc(Dc);
1032 }
1033 return Bmp;
1034 }
1035
1036
1037 HBITMAP STDCALL NtGdiCreateDIBSection(HDC hDC,
1038 IN OPTIONAL HANDLE hSection,
1039 IN DWORD dwOffset,
1040 IN LPBITMAPINFO bmi,
1041 DWORD Usage,
1042 IN UINT cjHeader,
1043 IN FLONG fl,
1044 IN ULONG_PTR dwColorSpace,
1045 PVOID *Bits)
1046 {
1047 HBITMAP hbitmap = 0;
1048 DC *dc;
1049 BOOL bDesktopDC = FALSE;
1050
1051 if (!bmi) return hbitmap; // Make sure.
1052
1053 // If the reference hdc is null, take the desktop dc
1054 if (hDC == 0)
1055 {
1056 hDC = NtGdiCreateCompatibleDC(0);
1057 bDesktopDC = TRUE;
1058 }
1059
1060 if ((dc = DC_LockDc(hDC)))
1061 {
1062 hbitmap = DIB_CreateDIBSection ( dc, (BITMAPINFO*)bmi, Usage, Bits,
1063 hSection, dwOffset, 0);
1064 DC_UnlockDc(dc);
1065 }
1066 else
1067 {
1068 SetLastWin32Error(ERROR_INVALID_HANDLE);
1069 }
1070
1071 if (bDesktopDC)
1072 NtGdiDeleteObjectApp(hDC);
1073
1074 return hbitmap;
1075 }
1076
1077 HBITMAP STDCALL
1078 DIB_CreateDIBSection(
1079 PDC dc, BITMAPINFO *bmi, UINT usage,
1080 LPVOID *bits, HANDLE section,
1081 DWORD offset, DWORD ovr_pitch)
1082 {
1083 HBITMAP res = 0;
1084 BITMAPOBJ *bmp = NULL;
1085 DIBSECTION *dib = NULL;
1086
1087 // Fill BITMAP32 structure with DIB data
1088 BITMAPINFOHEADER *bi = &bmi->bmiHeader;
1089 INT effHeight;
1090 ULONG totalSize;
1091 BITMAP bm;
1092 SIZEL Size;
1093 RGBQUAD *lpRGB;
1094
1095 DPRINT("format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n",
1096 bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
1097 bi->biSizeImage, bi->biClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1098
1099 /* CreateDIBSection should fail for compressed formats */
1100 if (bi->biCompression == BI_RLE4 || bi->biCompression == BI_RLE8)
1101 {
1102 return (HBITMAP)NULL;
1103 }
1104
1105 effHeight = bi->biHeight >= 0 ? bi->biHeight : -bi->biHeight;
1106 bm.bmType = 0;
1107 bm.bmWidth = bi->biWidth;
1108 bm.bmHeight = effHeight;
1109 bm.bmWidthBytes = ovr_pitch ? ovr_pitch : (ULONG) DIB_GetDIBWidthBytes(bm.bmWidth, bi->biBitCount);
1110
1111 bm.bmPlanes = bi->biPlanes;
1112 bm.bmBitsPixel = bi->biBitCount;
1113 bm.bmBits = NULL;
1114
1115 // Get storage location for DIB bits. Only use biSizeImage if it's valid and
1116 // we're dealing with a compressed bitmap. Otherwise, use width * height.
1117 totalSize = bi->biSizeImage && bi->biCompression != BI_RGB
1118 ? bi->biSizeImage : (ULONG) (bm.bmWidthBytes * effHeight);
1119
1120 if (section)
1121 {
1122 /* bm.bmBits = MapViewOfFile(section, FILE_MAP_ALL_ACCESS,
1123 0L, offset, totalSize); */
1124 DbgPrint("DIB_CreateDIBSection: Cannot yet handle section DIBs\n");
1125 SetLastWin32Error(ERROR_CALL_NOT_IMPLEMENTED);
1126 return 0;
1127 }
1128 else if (ovr_pitch && offset)
1129 bm.bmBits = (LPVOID) offset;
1130 else {
1131 offset = 0;
1132 bm.bmBits = EngAllocUserMem(totalSize, 0);
1133 }
1134
1135 if(usage == DIB_PAL_COLORS)
1136 lpRGB = DIB_MapPaletteColors(dc, bmi);
1137 else
1138 lpRGB = bmi->bmiColors;
1139
1140 // Allocate Memory for DIB and fill structure
1141 if (bm.bmBits)
1142 {
1143 dib = ExAllocatePoolWithTag(PagedPool, sizeof(DIBSECTION), TAG_DIB);
1144 if (dib != NULL) RtlZeroMemory(dib, sizeof(DIBSECTION));
1145 }
1146
1147 if (dib)
1148 {
1149 dib->dsBm = bm;
1150 /* Set dsBitfields values */
1151 if ( usage == DIB_PAL_COLORS || bi->biBitCount <= 8)
1152 {
1153 dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
1154 }
1155 else switch(bi->biBitCount)
1156 {
1157 case 16:
1158 dib->dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)lpRGB : 0x7c00;
1159 dib->dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)lpRGB + 1) : 0x03e0;
1160 dib->dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)lpRGB + 2) : 0x001f;
1161 break;
1162
1163 case 24:
1164 dib->dsBitfields[0] = 0xff0000;
1165 dib->dsBitfields[1] = 0x00ff00;
1166 dib->dsBitfields[2] = 0x0000ff;
1167 break;
1168
1169 case 32:
1170 dib->dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)lpRGB : 0xff0000;
1171 dib->dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)lpRGB + 1) : 0x00ff00;
1172 dib->dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)lpRGB + 2) : 0x0000ff;
1173 break;
1174 }
1175 dib->dshSection = section;
1176 dib->dsOffset = offset;
1177
1178 // Create Device Dependent Bitmap and add DIB pointer
1179 Size.cx = bm.bmWidth;
1180 Size.cy = abs(bm.bmHeight);
1181 res = IntCreateBitmap(Size, bm.bmWidthBytes,
1182 BitmapFormat(bi->biBitCount * bi->biPlanes, bi->biCompression),
1183 BMF_DONTCACHE | BMF_USERMEM | BMF_NOZEROINIT |
1184 (bi->biHeight < 0 ? BMF_TOPDOWN : 0),
1185 bm.bmBits);
1186 if (! res)
1187 {
1188 if (lpRGB != bmi->bmiColors)
1189 {
1190 ExFreePool(lpRGB);
1191 }
1192 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
1193 return NULL;
1194 }
1195 bmp = BITMAPOBJ_LockBitmap(res);
1196 if (NULL == bmp)
1197 {
1198 if (lpRGB != bmi->bmiColors)
1199 {
1200 ExFreePool(lpRGB);
1201 }
1202 SetLastWin32Error(ERROR_INVALID_HANDLE);
1203 NtGdiDeleteObject(bmp);
1204 return NULL;
1205 }
1206 bmp->dib = (DIBSECTION *) dib;
1207 bmp->flFlags = BITMAPOBJ_IS_APIBITMAP;
1208
1209 /* WINE NOTE: WINE makes use of a colormap, which is a color translation table between the DIB and the X physical
1210 device. Obviously, this is left out of the ReactOS implementation. Instead, we call
1211 NtGdiSetDIBColorTable. */
1212 bi->biClrUsed = 0;
1213 if(bi->biBitCount == 1) { bi->biClrUsed = 2; } else
1214 if(bi->biBitCount == 4) { bi->biClrUsed = 16; } else
1215 if(bi->biBitCount == 8) { bi->biClrUsed = 256; }
1216
1217 if (bi->biClrUsed != 0)
1218 bmp->hDIBPalette = PALETTE_AllocPaletteIndexedRGB(bi->biClrUsed, lpRGB);
1219 else
1220 bmp->hDIBPalette = PALETTE_AllocPalette(PAL_BITFIELDS, 0, NULL,
1221 dib->dsBitfields[0],
1222 dib->dsBitfields[1],
1223 dib->dsBitfields[2]);
1224
1225 dib->dsBmih = *bi;
1226 dib->dsBmih.biSizeImage = totalSize;
1227 }
1228
1229 // Clean up in case of errors
1230 if (!res || !bmp || !dib || !bm.bmBits)
1231 {
1232 DPRINT("got an error res=%08x, bmp=%p, dib=%p, bm.bmBits=%p\n", res, bmp, dib, bm.bmBits);
1233 /* if (bm.bmBits)
1234 {
1235 if (section)
1236 UnmapViewOfFile(bm.bmBits), bm.bmBits = NULL;
1237 else if (!offset)
1238 VirtualFree(bm.bmBits, 0L, MEM_RELEASE), bm.bmBits = NULL;
1239 } */
1240
1241 if (dib) { ExFreePool(dib); dib = NULL; }
1242 if (bmp) { bmp = NULL; }
1243 if (res) { BITMAPOBJ_FreeBitmapByHandle(res); res = 0; }
1244 }
1245
1246 if (lpRGB != bmi->bmiColors)
1247 {
1248 ExFreePool(lpRGB);
1249 }
1250
1251 if (bmp)
1252 {
1253 BITMAPOBJ_UnlockBitmap(bmp);
1254 }
1255
1256 // Return BITMAP handle and storage location
1257 if (NULL != bm.bmBits && NULL != bits)
1258 {
1259 *bits = bm.bmBits;
1260 }
1261
1262 return res;
1263 }
1264
1265 /***********************************************************************
1266 * DIB_GetDIBWidthBytes
1267 *
1268 * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
1269 * http://www.microsoft.com/msdn/sdk/platforms/doc/sdk/win32/struc/src/str01.htm
1270 * 11/16/1999 (RJJ) lifted from wine
1271 */
1272 INT FASTCALL DIB_GetDIBWidthBytes (INT width, INT depth)
1273 {
1274 return ((width * depth + 31) & ~31) >> 3;
1275 }
1276
1277 /***********************************************************************
1278 * DIB_GetDIBImageBytes
1279 *
1280 * Return the number of bytes used to hold the image in a DIB bitmap.
1281 * 11/16/1999 (RJJ) lifted from wine
1282 */
1283
1284 INT STDCALL DIB_GetDIBImageBytes (INT width, INT height, INT depth)
1285 {
1286 return DIB_GetDIBWidthBytes( width, depth ) * (height < 0 ? -height : height);
1287 }
1288
1289 /***********************************************************************
1290 * DIB_BitmapInfoSize
1291 *
1292 * Return the size of the bitmap info structure including color table.
1293 * 11/16/1999 (RJJ) lifted from wine
1294 */
1295
1296 INT FASTCALL DIB_BitmapInfoSize (const BITMAPINFO * info, WORD coloruse)
1297 {
1298 int colors;
1299
1300 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
1301 {
1302 BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)info;
1303 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
1304 return sizeof(BITMAPCOREHEADER) + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
1305 }
1306 else /* assume BITMAPINFOHEADER */
1307 {
1308 colors = info->bmiHeader.biClrUsed;
1309 if (!colors && (info->bmiHeader.biBitCount <= 8)) colors = 1 << info->bmiHeader.biBitCount;
1310 return sizeof(BITMAPINFOHEADER) + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
1311 }
1312 }
1313
1314 RGBQUAD * FASTCALL
1315 DIB_MapPaletteColors(PDC dc, CONST BITMAPINFO* lpbmi)
1316 {
1317 RGBQUAD *lpRGB;
1318 ULONG nNumColors,i;
1319 USHORT *lpIndex;
1320 PPALGDI palGDI;
1321
1322 palGDI = PALETTE_LockPalette(dc->DcLevel.hpal);
1323
1324 if (NULL == palGDI)
1325 {
1326 return NULL;
1327 }
1328
1329 if (palGDI->Mode != PAL_INDEXED)
1330 {
1331 PALETTE_UnlockPalette(palGDI);
1332 return NULL;
1333 }
1334
1335 nNumColors = 1 << lpbmi->bmiHeader.biBitCount;
1336 if (lpbmi->bmiHeader.biClrUsed)
1337 {
1338 nNumColors = min(nNumColors, lpbmi->bmiHeader.biClrUsed);
1339 }
1340
1341 lpRGB = (RGBQUAD *)ExAllocatePoolWithTag(PagedPool, sizeof(RGBQUAD) * nNumColors, TAG_COLORMAP);
1342 if (lpRGB == NULL)
1343 {
1344 PALETTE_UnlockPalette(palGDI);
1345 return NULL;
1346 }
1347
1348 lpIndex = (USHORT *)&lpbmi->bmiColors[0];
1349
1350 for (i = 0; i < nNumColors; i++)
1351 {
1352 lpRGB[i].rgbRed = palGDI->IndexedColors[*lpIndex].peRed;
1353 lpRGB[i].rgbGreen = palGDI->IndexedColors[*lpIndex].peGreen;
1354 lpRGB[i].rgbBlue = palGDI->IndexedColors[*lpIndex].peBlue;
1355 lpRGB[i].rgbReserved = 0;
1356 lpIndex++;
1357 }
1358 PALETTE_UnlockPalette(palGDI);
1359
1360 return lpRGB;
1361 }
1362
1363 HPALETTE FASTCALL
1364 BuildDIBPalette (CONST BITMAPINFO *bmi, PINT paletteType)
1365 {
1366 BYTE bits;
1367 ULONG ColorCount;
1368 PALETTEENTRY *palEntries = NULL;
1369 HPALETTE hPal;
1370 ULONG RedMask, GreenMask, BlueMask;
1371
1372 // Determine Bits Per Pixel
1373 bits = bmi->bmiHeader.biBitCount;
1374
1375 // Determine paletteType from Bits Per Pixel
1376 if (bits <= 8)
1377 {
1378 *paletteType = PAL_INDEXED;
1379 RedMask = GreenMask = BlueMask = 0;
1380 }
1381 else if(bmi->bmiHeader.biCompression == BI_BITFIELDS)
1382 {
1383 *paletteType = PAL_BITFIELDS;
1384 RedMask = ((ULONG *)bmi->bmiColors)[0];
1385 GreenMask = ((ULONG *)bmi->bmiColors)[1];
1386 BlueMask = ((ULONG *)bmi->bmiColors)[2];
1387 }
1388 else if(bits < 24)
1389 {
1390 *paletteType = PAL_BITFIELDS;
1391 RedMask = 0x7c00;
1392 GreenMask = 0x03e0;
1393 BlueMask = 0x001f;
1394 }
1395 else
1396 {
1397 *paletteType = PAL_BGR;
1398 RedMask = 0xff0000;
1399 GreenMask = 0x00ff00;
1400 BlueMask = 0x0000ff;
1401 }
1402
1403 if (bmi->bmiHeader.biClrUsed == 0)
1404 {
1405 ColorCount = 1 << bmi->bmiHeader.biBitCount;
1406 }
1407 else
1408 {
1409 ColorCount = bmi->bmiHeader.biClrUsed;
1410 }
1411
1412 if (PAL_INDEXED == *paletteType)
1413 {
1414 hPal = PALETTE_AllocPaletteIndexedRGB(ColorCount, (RGBQUAD*)bmi->bmiColors);
1415 }
1416 else
1417 {
1418 hPal = PALETTE_AllocPalette(*paletteType, ColorCount,
1419 (ULONG*) palEntries,
1420 RedMask, GreenMask, BlueMask );
1421 }
1422
1423 return hPal;
1424 }
1425
1426 /* EOF */