DIB_CreateDIBSection fix do not zero out memmory if it is a null pointer it got from...
[reactos.git] / reactos / subsys / win32k / objects / dib.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 NtGdiSetDIBColorTable(HDC hDC, UINT StartIndex, UINT Entries, CONST RGBQUAD *Colors)
29 {
30 PDC dc;
31 PBITMAPOBJ BitmapObj;
32 PPALGDI PalGDI;
33 UINT Index;
34
35 if (!(dc = DC_LockDc(hDC))) return 0;
36 if (dc->IsIC)
37 {
38 DC_UnlockDc(dc);
39 return 0;
40 }
41
42 BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap);
43 if (BitmapObj == NULL)
44 {
45 DC_UnlockDc(dc);
46 SetLastWin32Error(ERROR_INVALID_PARAMETER);
47 return 0;
48 }
49
50 if (BitmapObj->dib == NULL)
51 {
52 BITMAPOBJ_UnlockBitmap(BitmapObj);
53 DC_UnlockDc(dc);
54 SetLastWin32Error(ERROR_INVALID_PARAMETER);
55 return 0;
56 }
57
58 if (BitmapObj->dib->dsBmih.biBitCount <= 8 &&
59 StartIndex < (1 << BitmapObj->dib->dsBmih.biBitCount))
60 {
61 if (StartIndex + Entries > (1 << BitmapObj->dib->dsBmih.biBitCount))
62 Entries = (1 << BitmapObj->dib->dsBmih.biBitCount) - StartIndex;
63
64 PalGDI = PALETTE_LockPalette(BitmapObj->hDIBPalette);
65 _SEH_TRY
66 {
67 for (Index = StartIndex;
68 Index < StartIndex + Entries && Index < PalGDI->NumColors;
69 Index++)
70 {
71 PalGDI->IndexedColors[Index].peRed = Colors[Index - StartIndex].rgbRed;
72 PalGDI->IndexedColors[Index].peGreen = Colors[Index - StartIndex].rgbGreen;
73 PalGDI->IndexedColors[Index].peBlue = Colors[Index - StartIndex].rgbBlue;
74 }
75 }
76 _SEH_HANDLE
77 {
78 Entries = 0;
79 }
80 _SEH_END
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 NtGdiGetDIBColorTable(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->IsIC)
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 _SEH_TRY
131 {
132 for (Index = StartIndex;
133 Index < StartIndex + Entries && Index < PalGDI->NumColors;
134 Index++)
135 {
136 Colors[Index - StartIndex].rgbRed = PalGDI->IndexedColors[Index].peRed;
137 Colors[Index - StartIndex].rgbGreen = PalGDI->IndexedColors[Index].peGreen;
138 Colors[Index - StartIndex].rgbBlue = PalGDI->IndexedColors[Index].peBlue;
139 }
140 }
141 _SEH_HANDLE
142 {
143 Entries = 0;
144 }
145 _SEH_END
146 PALETTE_UnlockPalette(PalGDI);
147 }
148 else
149 Entries = 0;
150
151 BITMAPOBJ_UnlockBitmap(BitmapObj);
152 DC_UnlockDc(dc);
153
154 return Entries;
155 }
156
157 // Converts a DIB to a device-dependent bitmap
158 static INT FASTCALL
159 IntSetDIBits(
160 PDC DC,
161 HBITMAP hBitmap,
162 UINT StartScan,
163 UINT ScanLines,
164 CONST VOID *Bits,
165 CONST BITMAPINFO *bmi,
166 UINT ColorUse)
167 {
168 BITMAPOBJ *bitmap;
169 HBITMAP SourceBitmap;
170 INT result = 0;
171 BOOL copyBitsResult;
172 SURFOBJ *DestSurf, *SourceSurf;
173 SIZEL SourceSize;
174 POINTL ZeroPoint;
175 RECTL DestRect;
176 XLATEOBJ *XlateObj;
177 PPALGDI hDCPalette;
178 //RGBQUAD *lpRGB;
179 HPALETTE DDB_Palette, DIB_Palette;
180 ULONG DDB_Palette_Type, DIB_Palette_Type;
181 INT DIBWidth;
182
183 // Check parameters
184 if (!(bitmap = BITMAPOBJ_LockBitmap(hBitmap)))
185 {
186 return 0;
187 }
188
189 // Get RGB values
190 //if (ColorUse == DIB_PAL_COLORS)
191 // lpRGB = DIB_MapPaletteColors(hDC, bmi);
192 //else
193 // lpRGB = &bmi->bmiColors;
194
195 DestSurf = &bitmap->SurfObj;
196
197 // Create source surface
198 SourceSize.cx = bmi->bmiHeader.biWidth;
199 SourceSize.cy = ScanLines;
200
201 // Determine width of DIB
202 DIBWidth = DIB_GetDIBWidthBytes(SourceSize.cx, bmi->bmiHeader.biBitCount);
203
204 SourceBitmap = EngCreateBitmap(SourceSize,
205 DIBWidth,
206 BitmapFormat(bmi->bmiHeader.biBitCount, bmi->bmiHeader.biCompression),
207 bmi->bmiHeader.biHeight < 0 ? BMF_TOPDOWN : 0,
208 (PVOID) Bits);
209 if (0 == SourceBitmap)
210 {
211 BITMAPOBJ_UnlockBitmap(bitmap);
212 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
213 return 0;
214 }
215
216 SourceSurf = EngLockSurface((HSURF)SourceBitmap);
217 if (NULL == SourceSurf)
218 {
219 EngDeleteSurface((HSURF)SourceBitmap);
220 BITMAPOBJ_UnlockBitmap(bitmap);
221 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
222 return 0;
223 }
224
225 // Destination palette obtained from the hDC
226 hDCPalette = PALETTE_LockPalette(DC->DevInfo->hpalDefault);
227 if (NULL == hDCPalette)
228 {
229 EngUnlockSurface(SourceSurf);
230 EngDeleteSurface((HSURF)SourceBitmap);
231 BITMAPOBJ_UnlockBitmap(bitmap);
232 SetLastWin32Error(ERROR_INVALID_HANDLE);
233 return 0;
234 }
235 DDB_Palette_Type = hDCPalette->Mode;
236 DDB_Palette = DC->DevInfo->hpalDefault;
237 PALETTE_UnlockPalette(hDCPalette);
238
239 // Source palette obtained from the BITMAPINFO
240 DIB_Palette = BuildDIBPalette ( (PBITMAPINFO)bmi, (PINT)&DIB_Palette_Type );
241 if (NULL == DIB_Palette)
242 {
243 EngUnlockSurface(SourceSurf);
244 EngDeleteSurface((HSURF)SourceBitmap);
245 BITMAPOBJ_UnlockBitmap(bitmap);
246 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
247 return 0;
248 }
249
250 // Determine XLATEOBJ for color translation
251 XlateObj = IntEngCreateXlate(DDB_Palette_Type, DIB_Palette_Type, DDB_Palette, DIB_Palette);
252 if (NULL == XlateObj)
253 {
254 PALETTE_FreePalette(DIB_Palette);
255 EngUnlockSurface(SourceSurf);
256 EngDeleteSurface((HSURF)SourceBitmap);
257 BITMAPOBJ_UnlockBitmap(bitmap);
258 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
259 return 0;
260 }
261
262 // Zero point
263 ZeroPoint.x = 0;
264 ZeroPoint.y = 0;
265
266 // Determine destination rectangle
267 DestRect.left = 0;
268 DestRect.top = abs(bmi->bmiHeader.biHeight) - StartScan - ScanLines;
269 DestRect.right = SourceSize.cx;
270 DestRect.bottom = DestRect.top + ScanLines;
271
272 copyBitsResult = EngCopyBits(DestSurf, SourceSurf, NULL, XlateObj, &DestRect, &ZeroPoint);
273
274 // If it succeeded, return number of scanlines copies
275 if(copyBitsResult == TRUE)
276 {
277 result = SourceSize.cy - 1;
278 }
279
280 // Clean up
281 EngDeleteXlate(XlateObj);
282 PALETTE_FreePalette(DIB_Palette);
283 EngUnlockSurface(SourceSurf);
284 EngDeleteSurface((HSURF)SourceBitmap);
285
286 // if (ColorUse == DIB_PAL_COLORS)
287 // WinFree((LPSTR)lpRGB);
288
289 BITMAPOBJ_UnlockBitmap(bitmap);
290
291 return result;
292 }
293
294 // Converts a DIB to a device-dependent bitmap
295 INT STDCALL
296 NtGdiSetDIBits(
297 HDC hDC,
298 HBITMAP hBitmap,
299 UINT StartScan,
300 UINT ScanLines,
301 CONST VOID *Bits,
302 CONST BITMAPINFO *bmi,
303 UINT ColorUse)
304 {
305 PDC Dc;
306 INT Ret;
307
308 Dc = DC_LockDc(hDC);
309 if (NULL == Dc)
310 {
311 SetLastWin32Error(ERROR_INVALID_HANDLE);
312 return 0;
313 }
314 if (Dc->IsIC)
315 {
316 DC_UnlockDc(Dc);
317 return 0;
318 }
319
320 Ret = IntSetDIBits(Dc, hBitmap, StartScan, ScanLines, Bits, bmi, ColorUse);
321
322 DC_UnlockDc(Dc);
323
324 return Ret;
325 }
326
327 INT STDCALL
328 NtGdiSetDIBitsToDevice(
329 HDC hDC,
330 INT XDest,
331 INT YDest,
332 DWORD Width,
333 DWORD Height,
334 INT XSrc,
335 INT YSrc,
336 UINT StartScan,
337 UINT ScanLines,
338 CONST VOID *Bits,
339 CONST BITMAPINFO *bmi,
340 UINT ColorUse)
341 {
342 UNIMPLEMENTED;
343 return 0;
344 }
345
346 /* Converts a device-dependent bitmap to a DIB */
347 INT STDCALL
348 NtGdiGetDIBits(HDC hDC,
349 HBITMAP hBitmap,
350 UINT StartScan,
351 UINT ScanLines,
352 LPVOID Bits,
353 LPBITMAPINFO Info,
354 UINT Usage)
355 {
356 BITMAPOBJ *BitmapObj;
357 SURFOBJ *DestSurfObj;
358 XLATEOBJ *XlateObj;
359 HBITMAP DestBitmap;
360 SIZEL DestSize;
361 HPALETTE hSourcePalette;
362 HPALETTE hDestPalette;
363 PPALGDI SourcePalette;
364 PPALGDI DestPalette;
365 ULONG SourcePaletteType;
366 ULONG DestPaletteType;
367 PDC Dc;
368 POINTL SourcePoint;
369 RECTL DestRect;
370 ULONG Result = 0;
371 ULONG Index;
372
373 /* Get handle for the palette in DC. */
374 Dc = DC_LockDc(hDC);
375 if (Dc == NULL)
376 {
377 SetLastWin32Error(ERROR_INVALID_HANDLE);
378 return 0;
379 }
380 if (Dc->IsIC)
381 {
382 DC_UnlockDc(Dc);
383 return 0;
384 }
385 hSourcePalette = Dc->w.hPalette;
386 /* FIXME: This is incorrect. hDestPalette should be something other. */
387 hDestPalette = Dc->DevInfo->hpalDefault;
388 DC_UnlockDc(Dc);
389
390 /* Get pointer to the source bitmap object. */
391 BitmapObj = BITMAPOBJ_LockBitmap(hBitmap);
392 if (BitmapObj == NULL)
393 {
394 SetLastWin32Error(ERROR_INVALID_HANDLE);
395 return 0;
396 }
397
398 if (Bits == NULL)
399 {
400 if (Info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER) ||
401 Info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
402 {
403 Info->bmiHeader.biWidth = BitmapObj->SurfObj.sizlBitmap.cx;
404 Info->bmiHeader.biHeight = BitmapObj->SurfObj.sizlBitmap.cy;
405 /* Report negtive height for top-down bitmaps. */
406 if (BitmapObj->SurfObj.lDelta > 0)
407 Info->bmiHeader.biHeight = -Info->bmiHeader.biHeight;
408 Info->bmiHeader.biPlanes = 1;
409 Info->bmiHeader.biBitCount = BitsPerFormat(BitmapObj->SurfObj.iBitmapFormat);
410 if (Info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
411 {
412 switch (BitmapObj->SurfObj.iBitmapFormat)
413 {
414 case BMF_1BPP: case BMF_4BPP: case BMF_8BPP:
415 case BMF_16BPP: case BMF_24BPP: case BMF_32BPP:
416 Info->bmiHeader.biCompression = BI_RGB;
417 break;
418 case BMF_4RLE:
419 Info->bmiHeader.biCompression = BI_RLE4;
420 break;
421 case BMF_8RLE:
422 Info->bmiHeader.biCompression = BI_RLE8;
423 break;
424 case BMF_JPEG:
425 Info->bmiHeader.biCompression = BI_JPEG;
426 break;
427 case BMF_PNG:
428 Info->bmiHeader.biCompression = BI_PNG;
429 break;
430 }
431 Info->bmiHeader.biSizeImage = BitmapObj->SurfObj.cjBits;
432 Info->bmiHeader.biXPelsPerMeter = 0; /* FIXME */
433 Info->bmiHeader.biYPelsPerMeter = 0; /* FIXME */
434 Info->bmiHeader.biClrUsed =
435 Info->bmiHeader.biClrImportant = 1 << Info->bmiHeader.biBitCount; /* FIXME */
436 Result = BitmapObj->SurfObj.sizlBitmap.cy;
437 }
438 }
439 }
440 else
441 {
442 if (StartScan > BitmapObj->SurfObj.sizlBitmap.cy)
443 {
444 Result = 0;
445 }
446 else
447 {
448 ScanLines = min(ScanLines, BitmapObj->SurfObj.sizlBitmap.cy - StartScan);
449 DestSize.cx = BitmapObj->SurfObj.sizlBitmap.cx;
450 DestSize.cy = ScanLines;
451 DestBitmap = EngCreateBitmap(
452 DestSize, DIB_GetDIBWidthBytes(DestSize.cx,
453 Info->bmiHeader.biBitCount),
454 BitmapFormat(Info->bmiHeader.biBitCount, Info->bmiHeader.biCompression),
455 0 < Info->bmiHeader.biHeight ? 0 : BMF_TOPDOWN,
456 Bits);
457 DestSurfObj = EngLockSurface((HSURF)DestBitmap);
458
459 SourcePalette = PALETTE_LockPalette(hSourcePalette);
460 /* FIXME - SourcePalette can be NULL!!! Don't assert here! */
461 ASSERT(SourcePalette);
462 SourcePaletteType = SourcePalette->Mode;
463 PALETTE_UnlockPalette(SourcePalette);
464
465 DestPalette = PALETTE_LockPalette(hDestPalette);
466 /* FIXME - DestPalette can be NULL!!!! Don't assert here!!! */
467 ASSERT(DestPalette);
468 DestPaletteType = DestPalette->Mode;
469
470 /* Copy palette. */
471 /* FIXME: This is largely incomplete. */
472 if (Info->bmiHeader.biBitCount <= 8)
473 {
474 if (Usage == DIB_RGB_COLORS)
475 {
476 for (Index = 0;
477 Index < (1 << Info->bmiHeader.biBitCount) &&
478 Index < DestPalette->NumColors;
479 Index++)
480 {
481 Info->bmiColors[Index].rgbRed =
482 DestPalette->IndexedColors[Index].peRed;
483 Info->bmiColors[Index].rgbGreen =
484 DestPalette->IndexedColors[Index].peGreen;
485 Info->bmiColors[Index].rgbBlue =
486 DestPalette->IndexedColors[Index].peBlue;
487 }
488 }
489 if (Usage == DIB_PAL_COLORS)
490 {
491 DbgPrint("GetDIBits with DIB_PAL_COLORS isn't implemented yet.");
492 }
493 }
494
495 PALETTE_UnlockPalette(DestPalette);
496
497 XlateObj = IntEngCreateXlate(
498 DestPaletteType, SourcePaletteType, hDestPalette, hSourcePalette);
499
500 SourcePoint.x = 0;
501 SourcePoint.y = BitmapObj->SurfObj.sizlBitmap.cy -
502 (StartScan + ScanLines);
503
504 /* Determine destination rectangle */
505 DestRect.top = 0;
506 DestRect.left = 0;
507 DestRect.right = DestSize.cx;
508 DestRect.bottom = DestSize.cy;
509
510 if (EngCopyBits(DestSurfObj, &BitmapObj->SurfObj,
511 NULL, XlateObj, &DestRect, &SourcePoint))
512 {
513 Result = ScanLines;
514 }
515
516 EngDeleteXlate(XlateObj);
517 EngUnlockSurface(DestSurfObj);
518 }
519 }
520
521 BITMAPOBJ_UnlockBitmap(BitmapObj);
522
523 return Result;
524 }
525
526 INT STDCALL NtGdiStretchDIBits(HDC hDC,
527 INT XDest,
528 INT YDest,
529 INT DestWidth,
530 INT DestHeight,
531 INT XSrc,
532 INT YSrc,
533 INT SrcWidth,
534 INT SrcHeight,
535 CONST VOID *Bits,
536 CONST BITMAPINFO *BitsInfo,
537 UINT Usage,
538 DWORD ROP)
539 {
540 HBITMAP hBitmap, hOldBitmap;
541 HDC hdcMem;
542
543 if (!Bits || !BitsInfo)
544 {
545 SetLastWin32Error(ERROR_INVALID_PARAMETER);
546 return 0;
547 }
548
549 hdcMem = NtGdiCreateCompatibleDC(hDC);
550 hBitmap = NtGdiCreateCompatibleBitmap(hDC, BitsInfo->bmiHeader.biWidth,
551 BitsInfo->bmiHeader.biHeight);
552 hOldBitmap = NtGdiSelectObject(hdcMem, hBitmap);
553
554 if (BitsInfo->bmiHeader.biCompression == BI_RLE4 ||
555 BitsInfo->bmiHeader.biCompression == BI_RLE8)
556 {
557 /* copy existing bitmap from destination dc */
558 if (SrcWidth == DestWidth && SrcHeight == DestHeight)
559 NtGdiBitBlt(hdcMem, XSrc, abs(BitsInfo->bmiHeader.biHeight) - SrcHeight - YSrc,
560 SrcWidth, SrcHeight, hDC, XDest, YDest, ROP, 0, 0);
561 else
562 NtGdiStretchBlt(hdcMem, XSrc, abs(BitsInfo->bmiHeader.biHeight) - SrcHeight - YSrc,
563 SrcWidth, SrcHeight, hDC, XDest, YDest, DestWidth, DestHeight,
564 ROP, 0);
565 }
566
567 NtGdiSetDIBits(hdcMem, hBitmap, 0, BitsInfo->bmiHeader.biHeight, Bits,
568 BitsInfo, Usage);
569
570 /* Origin for DIBitmap may be bottom left (positive biHeight) or top
571 left (negative biHeight) */
572 if (SrcWidth == DestWidth && SrcHeight == DestHeight)
573 NtGdiBitBlt(hDC, XDest, YDest, DestWidth, DestHeight,
574 hdcMem, XSrc, abs(BitsInfo->bmiHeader.biHeight) - SrcHeight - YSrc,
575 ROP, 0, 0);
576 else
577 NtGdiStretchBlt(hDC, XDest, YDest, DestWidth, DestHeight,
578 hdcMem, XSrc, abs(BitsInfo->bmiHeader.biHeight) - SrcHeight - YSrc,
579 SrcWidth, SrcHeight, ROP, 0);
580
581 NtGdiSelectObject(hdcMem, hOldBitmap);
582 NtGdiDeleteDC(hdcMem);
583 NtGdiDeleteObject(hBitmap);
584
585 return SrcHeight;
586 }
587
588 LONG STDCALL NtGdiGetBitmapBits(HBITMAP hBitmap,
589 ULONG Count,
590 OUT OPTIONAL PBYTE Bits)
591 {
592 PBITMAPOBJ bmp;
593 LONG height, ret;
594
595 bmp = BITMAPOBJ_LockBitmap (hBitmap);
596 if (!bmp)
597 {
598 return 0;
599 }
600
601 /* If the bits vector is null, the function should return the read size */
602 if (Bits == NULL)
603 {
604 ret = bmp->SurfObj.cjBits;
605 BITMAPOBJ_UnlockBitmap (bmp);
606 return ret;
607 }
608
609 if (Count < 0)
610 {
611 DPRINT ("(%ld): Negative number of bytes passed???\n", Count);
612 Count = -Count;
613 }
614
615 /* Only get entire lines */
616 height = Count / abs(bmp->SurfObj.lDelta);
617 if (height > bmp->SurfObj.sizlBitmap.cy)
618 {
619 height = bmp->SurfObj.sizlBitmap.cy;
620 }
621 Count = height * abs(bmp->SurfObj.lDelta);
622 if (Count == 0)
623 {
624 DPRINT("Less then one entire line requested\n");
625 BITMAPOBJ_UnlockBitmap (bmp);
626 return 0;
627 }
628
629 DPRINT("(%08x, %ld, %p) %dx%d %d colors fetched height: %ld\n",
630 hBitmap, Count, Bits, bmp->SurfObj.sizlBitmap.cx,
631 bmp->SurfObj.sizlBitmap.cy,
632 1 << BitsPerFormat(bmp->SurfObj.iBitmapFormat), height );
633 #if 0
634 /* FIXME: Call DDI CopyBits here if available */
635 if(bmp->DDBitmap)
636 {
637 DPRINT("Calling device specific BitmapBits\n");
638 if(bmp->DDBitmap->funcs->pBitmapBits)
639 {
640 ret = bmp->DDBitmap->funcs->pBitmapBits(hbitmap, bits, count,
641 DDB_GET);
642 }
643 else
644 {
645 ERR_(bitmap)("BitmapBits == NULL??\n");
646 ret = 0;
647 }
648 }
649 else
650 #endif
651 {
652 memcpy(Bits, bmp->SurfObj.pvBits, Count);
653 ret = Count;
654 }
655
656 BITMAPOBJ_UnlockBitmap (bmp);
657
658 return ret;
659 }
660
661 HBITMAP FASTCALL
662 IntCreateDIBitmap(PDC Dc, const BITMAPINFOHEADER *header,
663 DWORD init, LPCVOID bits, const BITMAPINFO *data,
664 UINT coloruse)
665 {
666 HBITMAP handle;
667 BOOL fColor;
668 DWORD width;
669 int height;
670 WORD bpp;
671 WORD compr;
672 SIZEL size;
673
674 if (DIB_GetBitmapInfo( header, &width, &height, &bpp, &compr ) == -1) return 0;
675
676 // Check if we should create a monochrome or color bitmap. We create a monochrome bitmap only if it has exactly 2
677 // colors, which are black followed by white, nothing else. In all other cases, we create a color bitmap.
678
679 if (bpp != 1) fColor = TRUE;
680 else if ((coloruse != DIB_RGB_COLORS) ||
681 (init != CBM_INIT) || !data) fColor = FALSE;
682 else
683 {
684 if (data->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
685 {
686 RGBQUAD *rgb = data->bmiColors;
687 DWORD col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
688
689 // Check if the first color of the colormap is black
690 if ((col == RGB(0, 0, 0)))
691 {
692 rgb++;
693 col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
694
695 // If the second color is white, create a monochrome bitmap
696 fColor = (col != RGB(0xff,0xff,0xff));
697 }
698 else fColor = TRUE;
699 }
700 else if (data->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
701 {
702 RGBTRIPLE *rgb = ((BITMAPCOREINFO *)data)->bmciColors;
703 DWORD col = RGB( rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue);
704
705 if ((col == RGB(0,0,0)))
706 {
707 rgb++;
708 col = RGB( rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue );
709 fColor = (col != RGB(0xff,0xff,0xff));
710 }
711 else fColor = TRUE;
712 }
713 else
714 {
715 DPRINT("(%ld): wrong size for data\n", data->bmiHeader.biSize );
716 return 0;
717 }
718 }
719
720 // Now create the bitmap
721 if (fColor)
722 {
723 handle = IntCreateCompatibleBitmap(Dc, width, height);
724 }
725 else
726 {
727 size.cx = width;
728 size.cy = abs(height);
729
730 handle = IntCreateBitmap(size, DIB_GetDIBWidthBytes(width, 1), BMF_1BPP,
731 (height < 0 ? BMF_TOPDOWN : 0) | BMF_NOZEROINIT,
732 NULL);
733 }
734
735 if (height < 0)
736 height = -height;
737
738 if (NULL != handle && CBM_INIT == init)
739 {
740 IntSetDIBits(Dc, handle, 0, height, bits, data, coloruse);
741 }
742
743 return handle;
744 }
745
746 // The CreateDIBitmap function creates a device-dependent bitmap (DDB) from a DIB and, optionally, sets the bitmap bits
747 // The DDB that is created will be whatever bit depth your reference DC is
748 HBITMAP STDCALL NtGdiCreateDIBitmap(HDC hDc, const BITMAPINFOHEADER *Header,
749 DWORD Init, LPCVOID Bits, const BITMAPINFO *Data,
750 UINT ColorUse)
751 {
752 PDC Dc;
753 HBITMAP Bmp;
754
755 Dc = DC_LockDc(hDc);
756 if (NULL == Dc)
757 {
758 SetLastWin32Error(ERROR_INVALID_HANDLE);
759 return NULL;
760 }
761
762 Bmp = IntCreateDIBitmap(Dc, Header, Init, Bits, Data, ColorUse);
763
764 DC_UnlockDc(Dc);
765
766 return Bmp;
767 }
768
769 HBITMAP STDCALL NtGdiCreateDIBSection(HDC hDC,
770 IN OPTIONAL HANDLE hSection,
771 IN DWORD dwOffset,
772 IN LPBITMAPINFO bmi,
773 DWORD Usage,
774 IN UINT cjHeader,
775 IN FLONG fl,
776 IN ULONG_PTR dwColorSpace,
777 PVOID *Bits)
778 {
779 HBITMAP hbitmap = 0;
780 DC *dc;
781 BOOL bDesktopDC = FALSE;
782
783 // If the reference hdc is null, take the desktop dc
784 if (hDC == 0)
785 {
786 hDC = NtGdiCreateCompatibleDC(0);
787 bDesktopDC = TRUE;
788 }
789
790 if ((dc = DC_LockDc(hDC)))
791 {
792 hbitmap = DIB_CreateDIBSection ( dc, (BITMAPINFO*)bmi, Usage, Bits,
793 hSection, dwOffset, 0);
794 DC_UnlockDc(dc);
795 }
796 else
797 {
798 SetLastWin32Error(ERROR_INVALID_HANDLE);
799 }
800
801 if (bDesktopDC)
802 NtGdiDeleteDC(hDC);
803
804 return hbitmap;
805 }
806
807 HBITMAP STDCALL
808 DIB_CreateDIBSection(
809 PDC dc, BITMAPINFO *bmi, UINT usage,
810 LPVOID *bits, HANDLE section,
811 DWORD offset, DWORD ovr_pitch)
812 {
813 HBITMAP res = 0;
814 BITMAPOBJ *bmp = NULL;
815 DIBSECTION *dib = NULL;
816
817 // Fill BITMAP32 structure with DIB data
818 BITMAPINFOHEADER *bi = &bmi->bmiHeader;
819 INT effHeight;
820 ULONG totalSize;
821 UINT Entries = 0;
822 BITMAP bm;
823 SIZEL Size;
824 RGBQUAD *lpRGB;
825
826 DPRINT("format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n",
827 bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
828 bi->biSizeImage, bi->biClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB");
829
830 effHeight = bi->biHeight >= 0 ? bi->biHeight : -bi->biHeight;
831 bm.bmType = 0;
832 bm.bmWidth = bi->biWidth;
833 bm.bmHeight = effHeight;
834 bm.bmWidthBytes = ovr_pitch ? ovr_pitch : (ULONG) DIB_GetDIBWidthBytes(bm.bmWidth, bi->biBitCount);
835
836 bm.bmPlanes = bi->biPlanes;
837 bm.bmBitsPixel = bi->biBitCount;
838 bm.bmBits = NULL;
839
840 // Get storage location for DIB bits. Only use biSizeImage if it's valid and
841 // we're dealing with a compressed bitmap. Otherwise, use width * height.
842 totalSize = bi->biSizeImage && bi->biCompression != BI_RGB
843 ? bi->biSizeImage : (ULONG) (bm.bmWidthBytes * effHeight);
844
845 if (section)
846 {
847 /* bm.bmBits = MapViewOfFile(section, FILE_MAP_ALL_ACCESS,
848 0L, offset, totalSize); */
849 DbgPrint("DIB_CreateDIBSection: Cannot yet handle section DIBs\n");
850 SetLastWin32Error(ERROR_CALL_NOT_IMPLEMENTED);
851 return 0;
852 }
853 else if (ovr_pitch && offset)
854 bm.bmBits = (LPVOID) offset;
855 else {
856 offset = 0;
857 bm.bmBits = EngAllocUserMem(totalSize, 0);
858 }
859
860 if(usage == DIB_PAL_COLORS)
861 lpRGB = DIB_MapPaletteColors(dc, bmi);
862 else
863 lpRGB = bmi->bmiColors;
864
865 // Allocate Memory for DIB and fill structure
866 if (bm.bmBits)
867 {
868 dib = ExAllocatePoolWithTag(PagedPool, sizeof(DIBSECTION), TAG_DIB);
869 if (dib != NULL) RtlZeroMemory(dib, sizeof(DIBSECTION));
870 }
871
872 if (dib)
873 {
874 dib->dsBm = bm;
875 dib->dsBmih = *bi;
876 dib->dsBmih.biSizeImage = totalSize;
877
878 /* Set dsBitfields values */
879 if ( usage == DIB_PAL_COLORS || bi->biBitCount <= 8)
880 {
881 dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
882 }
883 else switch(bi->biBitCount)
884 {
885 case 16:
886 dib->dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)lpRGB : 0x7c00;
887 dib->dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)lpRGB + 1) : 0x03e0;
888 dib->dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)lpRGB + 2) : 0x001f; break;
889
890 case 24:
891 dib->dsBitfields[0] = 0xff0000;
892 dib->dsBitfields[1] = 0x00ff00;
893 dib->dsBitfields[2] = 0x0000ff;
894 break;
895
896 case 32:
897 dib->dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)lpRGB : 0xff0000;
898 dib->dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)lpRGB + 1) : 0x00ff00;
899 dib->dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)lpRGB + 2) : 0x0000ff;
900 break;
901 }
902 dib->dshSection = section;
903 dib->dsOffset = offset;
904 }
905
906 // Create Device Dependent Bitmap and add DIB pointer
907 if (dib)
908 {
909 Size.cx = bm.bmWidth;
910 Size.cy = abs(bm.bmHeight);
911 res = IntCreateBitmap(Size, bm.bmWidthBytes,
912 BitmapFormat(bi->biBitCount * bi->biPlanes, bi->biCompression),
913 BMF_DONTCACHE | BMF_USERMEM | BMF_NOZEROINIT |
914 (bi->biHeight < 0 ? BMF_TOPDOWN : 0),
915 bm.bmBits);
916 if (! res)
917 {
918 if (lpRGB != bmi->bmiColors)
919 {
920 ExFreePool(lpRGB);
921 }
922 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
923 return NULL;
924 }
925 bmp = BITMAPOBJ_LockBitmap(res);
926 if (NULL == bmp)
927 {
928 if (lpRGB != bmi->bmiColors)
929 {
930 ExFreePool(lpRGB);
931 }
932 SetLastWin32Error(ERROR_INVALID_HANDLE);
933 NtGdiDeleteObject(bmp);
934 return NULL;
935 }
936 bmp->dib = (DIBSECTION *) dib;
937 bmp->flFlags = BITMAPOBJ_IS_APIBITMAP;
938
939 /* WINE NOTE: WINE makes use of a colormap, which is a color translation table between the DIB and the X physical
940 device. Obviously, this is left out of the ReactOS implementation. Instead, we call
941 NtGdiSetDIBColorTable. */
942 if(bi->biBitCount == 1) { Entries = 2; } else
943 if(bi->biBitCount == 4) { Entries = 16; } else
944 if(bi->biBitCount == 8) { Entries = 256; }
945
946 if (Entries)
947 bmp->hDIBPalette = PALETTE_AllocPaletteIndexedRGB(Entries, lpRGB);
948 else
949 bmp->hDIBPalette = PALETTE_AllocPalette(PAL_BITFIELDS, 0, NULL,
950 dib->dsBitfields[0],
951 dib->dsBitfields[1],
952 dib->dsBitfields[2]);
953 }
954
955 // Clean up in case of errors
956 if (!res || !bmp || !dib || !bm.bmBits)
957 {
958 DPRINT("got an error res=%08x, bmp=%p, dib=%p, bm.bmBits=%p\n", res, bmp, dib, bm.bmBits);
959 /* if (bm.bmBits)
960 {
961 if (section)
962 UnmapViewOfFile(bm.bmBits), bm.bmBits = NULL;
963 else if (!offset)
964 VirtualFree(bm.bmBits, 0L, MEM_RELEASE), bm.bmBits = NULL;
965 } */
966
967 if (dib) { ExFreePool(dib); dib = NULL; }
968 if (bmp) { bmp = NULL; }
969 if (res) { BITMAPOBJ_FreeBitmap(res); res = 0; }
970 }
971
972 if (lpRGB != bmi->bmiColors)
973 {
974 ExFreePool(lpRGB);
975 }
976
977 if (bmp)
978 {
979 BITMAPOBJ_UnlockBitmap(bmp);
980 }
981
982 // Return BITMAP handle and storage location
983 if (NULL != bm.bmBits && NULL != bits)
984 {
985 *bits = bm.bmBits;
986 }
987
988 return res;
989 }
990
991 /***********************************************************************
992 * DIB_GetDIBWidthBytes
993 *
994 * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
995 * http://www.microsoft.com/msdn/sdk/platforms/doc/sdk/win32/struc/src/str01.htm
996 * 11/16/1999 (RJJ) lifted from wine
997 */
998 INT FASTCALL DIB_GetDIBWidthBytes (INT width, INT depth)
999 {
1000 return ((width * depth + 31) & ~31) >> 3;
1001 }
1002
1003 /***********************************************************************
1004 * DIB_GetDIBImageBytes
1005 *
1006 * Return the number of bytes used to hold the image in a DIB bitmap.
1007 * 11/16/1999 (RJJ) lifted from wine
1008 */
1009
1010 INT STDCALL DIB_GetDIBImageBytes (INT width, INT height, INT depth)
1011 {
1012 return DIB_GetDIBWidthBytes( width, depth ) * (height < 0 ? -height : height);
1013 }
1014
1015 /***********************************************************************
1016 * DIB_BitmapInfoSize
1017 *
1018 * Return the size of the bitmap info structure including color table.
1019 * 11/16/1999 (RJJ) lifted from wine
1020 */
1021
1022 INT FASTCALL DIB_BitmapInfoSize (const BITMAPINFO * info, WORD coloruse)
1023 {
1024 int colors;
1025
1026 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
1027 {
1028 BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)info;
1029 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
1030 return sizeof(BITMAPCOREHEADER) + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
1031 }
1032 else /* assume BITMAPINFOHEADER */
1033 {
1034 colors = info->bmiHeader.biClrUsed;
1035 if (!colors && (info->bmiHeader.biBitCount <= 8)) colors = 1 << info->bmiHeader.biBitCount;
1036 return sizeof(BITMAPINFOHEADER) + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
1037 }
1038 }
1039
1040 INT STDCALL DIB_GetBitmapInfo (const BITMAPINFOHEADER *header,
1041 PDWORD width,
1042 PINT height,
1043 PWORD bpp,
1044 PWORD compr)
1045 {
1046 if (header->biSize == sizeof(BITMAPINFOHEADER))
1047 {
1048 *width = header->biWidth;
1049 *height = header->biHeight;
1050 *bpp = header->biBitCount;
1051 *compr = header->biCompression;
1052 return 1;
1053 }
1054 if (header->biSize == sizeof(BITMAPCOREHEADER))
1055 {
1056 BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)header;
1057 *width = core->bcWidth;
1058 *height = core->bcHeight;
1059 *bpp = core->bcBitCount;
1060 *compr = 0;
1061 return 0;
1062 }
1063 DPRINT("(%ld): wrong size for header\n", header->biSize );
1064 return -1;
1065 }
1066
1067 // Converts a Device Independent Bitmap (DIB) to a Device Dependant Bitmap (DDB)
1068 // The specified Device Context (DC) defines what the DIB should be converted to
1069 PBITMAPOBJ FASTCALL DIBtoDDB(HGLOBAL hPackedDIB, HDC hdc) // FIXME: This should be removed. All references to this function should
1070 // change to NtGdiSetDIBits
1071 {
1072 HBITMAP hBmp = 0;
1073 PBITMAPOBJ pBmp = NULL;
1074 DIBSECTION *dib;
1075 LPBYTE pbits = NULL;
1076
1077 // Get a pointer to the packed DIB's data
1078 // pPackedDIB = (LPBYTE)GlobalLock(hPackedDIB);
1079 dib = hPackedDIB;
1080
1081 pbits = (LPBYTE)(dib + DIB_BitmapInfoSize((BITMAPINFO*)&dib->dsBmih, DIB_RGB_COLORS));
1082
1083 // Create a DDB from the DIB
1084 hBmp = NtGdiCreateDIBitmap ( hdc, &dib->dsBmih, CBM_INIT,
1085 (LPVOID)pbits, (BITMAPINFO*)&dib->dsBmih, DIB_RGB_COLORS);
1086
1087 // GlobalUnlock(hPackedDIB);
1088
1089 // Retrieve the internal Pixmap from the DDB
1090 pBmp = BITMAPOBJ_LockBitmap(hBmp);
1091
1092 return pBmp;
1093 }
1094
1095 RGBQUAD * FASTCALL
1096 DIB_MapPaletteColors(PDC dc, CONST BITMAPINFO* lpbmi)
1097 {
1098 RGBQUAD *lpRGB;
1099 ULONG nNumColors,i;
1100 USHORT *lpIndex;
1101 PPALGDI palGDI;
1102
1103 palGDI = PALETTE_LockPalette(dc->w.hPalette);
1104
1105 if (NULL == palGDI)
1106 {
1107 // RELEASEDCINFO(hDC);
1108 return NULL;
1109 }
1110
1111 if (palGDI->Mode != PAL_INDEXED)
1112 {
1113 PALETTE_UnlockPalette(palGDI);
1114 palGDI = PALETTE_LockPalette(dc->PalIndexed);
1115 if (palGDI->Mode != PAL_INDEXED)
1116 {
1117 return NULL;
1118 }
1119 }
1120
1121 nNumColors = 1 << lpbmi->bmiHeader.biBitCount;
1122 if (lpbmi->bmiHeader.biClrUsed)
1123 {
1124 nNumColors = min(nNumColors, lpbmi->bmiHeader.biClrUsed);
1125 }
1126
1127 lpRGB = (RGBQUAD *)ExAllocatePoolWithTag(PagedPool, sizeof(RGBQUAD) * nNumColors, TAG_COLORMAP);
1128 if (lpRGB == NULL)
1129 {
1130 PALETTE_UnlockPalette(palGDI);
1131 return NULL;
1132 }
1133
1134 lpIndex = (USHORT *)&lpbmi->bmiColors[0];
1135
1136 for (i = 0; i < nNumColors; i++)
1137 {
1138 lpRGB[i].rgbRed = palGDI->IndexedColors[*lpIndex].peRed;
1139 lpRGB[i].rgbGreen = palGDI->IndexedColors[*lpIndex].peGreen;
1140 lpRGB[i].rgbBlue = palGDI->IndexedColors[*lpIndex].peBlue;
1141 lpIndex++;
1142 }
1143 // RELEASEDCINFO(hDC);
1144 PALETTE_UnlockPalette(palGDI);
1145
1146 return lpRGB;
1147 }
1148
1149 HPALETTE FASTCALL
1150 BuildDIBPalette (CONST BITMAPINFO *bmi, PINT paletteType)
1151 {
1152 BYTE bits;
1153 ULONG ColorCount;
1154 PALETTEENTRY *palEntries = NULL;
1155 HPALETTE hPal;
1156 ULONG RedMask, GreenMask, BlueMask;
1157
1158 // Determine Bits Per Pixel
1159 bits = bmi->bmiHeader.biBitCount;
1160
1161 // Determine paletteType from Bits Per Pixel
1162 if (bits <= 8)
1163 {
1164 *paletteType = PAL_INDEXED;
1165 RedMask = GreenMask = BlueMask = 0;
1166 }
1167 else if(bits < 24)
1168 {
1169 *paletteType = PAL_BITFIELDS;
1170 RedMask = 0xf800;
1171 GreenMask = 0x07e0;
1172 BlueMask = 0x001f;
1173 }
1174 else
1175 {
1176 *paletteType = PAL_BGR;
1177 RedMask = 0xff0000;
1178 GreenMask = 0x00ff00;
1179 BlueMask = 0x0000ff;
1180 }
1181
1182 if (bmi->bmiHeader.biClrUsed == 0)
1183 {
1184 ColorCount = 1 << bmi->bmiHeader.biBitCount;
1185 }
1186 else
1187 {
1188 ColorCount = bmi->bmiHeader.biClrUsed;
1189 }
1190
1191 if (PAL_INDEXED == *paletteType)
1192 {
1193 hPal = PALETTE_AllocPaletteIndexedRGB(ColorCount, (RGBQUAD*)bmi->bmiColors);
1194 }
1195 else
1196 {
1197 hPal = PALETTE_AllocPalette(*paletteType, ColorCount,
1198 (ULONG*) palEntries,
1199 RedMask, GreenMask, BlueMask );
1200 }
1201
1202 return hPal;
1203 }
1204
1205 /* EOF */