Fix CreateDIBSection() and add some stuff to GetDIBits()
[reactos.git] / reactos / subsys / win32k / objects / dib.c
1 /*
2 * $Id: dib.c,v 1.23 2003/06/06 10:17:44 gvg Exp $
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 #undef WIN32_LEAN_AND_MEAN
23 #include <windows.h>
24 #include <stdlib.h>
25 #include <win32k/bitmaps.h>
26 #include <win32k/debug.h>
27 #include "../eng/handle.h"
28 #include <ntos/minmax.h>
29 #include <include/error.h>
30 #include <include/inteng.h>
31 #include <include/eng.h>
32 #include <include/dib.h>
33 #include <internal/safe.h>
34 #include <include/surface.h>
35
36 #define NDEBUG
37 #include <win32k/debug1.h>
38
39 UINT STDCALL W32kSetDIBColorTable(HDC hDC,
40 UINT StartIndex,
41 UINT Entries,
42 CONST RGBQUAD *Colors)
43 {
44 PDC dc;
45 PALETTEENTRY * palEntry;
46 PPALOBJ palette;
47 RGBQUAD *end;
48
49 if (!(dc = (PDC)AccessUserObject(hDC))) return 0;
50
51 if (!(palette = (PPALOBJ)AccessUserObject(dc->DevInfo->hpalDefault)))
52 {
53 // GDI_ReleaseObj( hdc );
54 return 0;
55 }
56
57 // Transfer color info
58
59 if (dc->w.bitsPerPixel <= 8) {
60 palEntry = palette->logpalette->palPalEntry + StartIndex;
61 if (StartIndex + Entries > (1 << dc->w.bitsPerPixel))
62 Entries = (1 << dc->w.bitsPerPixel) - StartIndex;
63
64 if (StartIndex + Entries > palette->logpalette->palNumEntries)
65 Entries = palette->logpalette->palNumEntries - StartIndex;
66
67 for (end = Colors + Entries; Colors < end; palEntry++, Colors++)
68 {
69 palEntry->peRed = Colors->rgbRed;
70 palEntry->peGreen = Colors->rgbGreen;
71 palEntry->peBlue = Colors->rgbBlue;
72 }
73 } else {
74 Entries = 0;
75 }
76
77 // GDI_ReleaseObj(dc->DevInfo->hpalDefault);
78 // GDI_ReleaseObj(hdc);
79
80 return Entries;
81 }
82
83 // Converts a DIB to a device-dependent bitmap
84 INT STDCALL W32kSetDIBits(HDC hDC,
85 HBITMAP hBitmap,
86 UINT StartScan,
87 UINT ScanLines,
88 CONST VOID *Bits,
89 CONST BITMAPINFO *bmi,
90 UINT ColorUse)
91 {
92 DC *dc;
93 BITMAPOBJ *bitmap;
94 HBITMAP SourceBitmap, DestBitmap;
95 INT result = 0;
96 BOOL copyBitsResult;
97 PSURFOBJ DestSurf, SourceSurf;
98 PSURFGDI DestGDI;
99 SIZEL SourceSize;
100 POINTL ZeroPoint;
101 RECTL DestRect;
102 PXLATEOBJ XlateObj;
103 PPALGDI hDCPalette;
104 RGBQUAD *lpRGB;
105 HPALETTE DDB_Palette, DIB_Palette;
106 ULONG DDB_Palette_Type, DIB_Palette_Type;
107 PBYTE vBits = Bits;
108 INT scanDirection = 1, DIBWidth;
109
110 // Check parameters
111 if (!(dc = DC_HandleToPtr(hDC)))
112 return 0;
113
114 if (!(bitmap = (BITMAPOBJ *)GDIOBJ_LockObj(hBitmap, GO_BITMAP_MAGIC)))
115 {
116 DC_ReleasePtr(hDC);
117 return 0;
118 }
119
120 // Get RGB values
121 if (ColorUse == DIB_PAL_COLORS)
122 lpRGB = DIB_MapPaletteColors(hDC, bmi);
123 else
124 lpRGB = &bmi->bmiColors[0];
125
126 // Create a temporary surface for the destination bitmap
127 DestBitmap = BitmapToSurf(bitmap);
128
129 DestSurf = (PSURFOBJ) AccessUserObject( DestBitmap );
130 DestGDI = (PSURFGDI) AccessInternalObject( DestBitmap );
131
132 // Create source surface
133 SourceSize.cx = bmi->bmiHeader.biWidth;
134 SourceSize.cy = abs(bmi->bmiHeader.biHeight);
135
136 // Determine width of DIB
137 DIBWidth = DIB_GetDIBWidthBytes(SourceSize.cx, bmi->bmiHeader.biBitCount);
138
139 // Determine DIB Vertical Orientation
140 if(bmi->bmiHeader.biHeight > 0)
141 {
142 scanDirection = -1;
143 vBits += DIBWidth * bmi->bmiHeader.biHeight - DIBWidth;
144 }
145
146 SourceBitmap = EngCreateBitmap(SourceSize,
147 DIBWidth * scanDirection,
148 BitmapFormat(bmi->bmiHeader.biBitCount, bmi->bmiHeader.biCompression),
149 0,
150 vBits);
151 SourceSurf = (PSURFOBJ)AccessUserObject(SourceBitmap);
152
153 // Destination palette obtained from the hDC
154 hDCPalette = (PPALGDI)AccessInternalObject(dc->DevInfo->hpalDefault);
155 DDB_Palette_Type = hDCPalette->Mode;
156 DDB_Palette = dc->DevInfo->hpalDefault;
157
158 // Source palette obtained from the BITMAPINFO
159 DIB_Palette = BuildDIBPalette(bmi, &DIB_Palette_Type);
160
161 // Determine XLATEOBJ for color translation
162 XlateObj = IntEngCreateXlate(DDB_Palette_Type, DIB_Palette_Type, DDB_Palette, DIB_Palette);
163
164 // Zero point
165 ZeroPoint.x = 0;
166 ZeroPoint.y = 0;
167
168 // Determine destination rectangle
169 DestRect.top = 0;
170 DestRect.left = 0;
171 DestRect.right = SourceSize.cx;
172 DestRect.bottom = SourceSize.cy;
173
174 copyBitsResult = EngCopyBits(DestSurf, SourceSurf, NULL, XlateObj, &DestRect, &ZeroPoint);
175
176 // If it succeeded, return number of scanlines copies
177 if(copyBitsResult == TRUE)
178 {
179 result = SourceSize.cy - 1;
180 }
181
182 // Clean up
183 EngDeleteXlate(XlateObj);
184 EngDeletePalette(DIB_Palette);
185 EngDeleteSurface(SourceBitmap);
186 EngDeleteSurface(DestBitmap);
187
188 // if (ColorUse == DIB_PAL_COLORS)
189 // WinFree((LPSTR)lpRGB);
190
191 // GDI_ReleaseObj(hBitmap); unlock?
192 GDIOBJ_UnlockObj(hBitmap, GO_BITMAP_MAGIC);
193 DC_ReleasePtr(hDC);
194
195 return result;
196 }
197
198 INT STDCALL W32kSetDIBitsToDevice(HDC hDC,
199 INT XDest,
200 INT YDest,
201 DWORD Width,
202 DWORD Height,
203 INT XSrc,
204 INT YSrc,
205 UINT StartScan,
206 UINT ScanLines,
207 CONST VOID *Bits,
208 CONST BITMAPINFO *bmi,
209 UINT ColorUse)
210 {
211
212 }
213
214 UINT STDCALL W32kGetDIBColorTable(HDC hDC,
215 UINT StartIndex,
216 UINT Entries,
217 RGBQUAD *Colors)
218 {
219 UNIMPLEMENTED;
220 }
221
222 // Converts a device-dependent bitmap to a DIB
223 INT STDCALL W32kGetDIBits(HDC hDC,
224 HBITMAP hBitmap,
225 UINT StartScan,
226 UINT ScanLines,
227 LPVOID Bits,
228 LPBITMAPINFO UnsafeInfo,
229 UINT Usage)
230 {
231 BITMAPINFO Info;
232 BITMAPCOREHEADER *Core;
233 PBITMAPOBJ BitmapObj;
234 INT Result;
235 NTSTATUS Status;
236 PDC DCObj;
237 PPALGDI PalGdi;
238 struct
239 {
240 BITMAPINFO Info;
241 DWORD BitFields[3];
242 } InfoWithBitFields;
243 DWORD *BitField;
244 DWORD InfoSize;
245
246 BitmapObj = (PBITMAPOBJ) GDIOBJ_LockObj(hBitmap, GO_BITMAP_MAGIC);
247 if (NULL == BitmapObj)
248 {
249 SetLastWin32Error(ERROR_INVALID_HANDLE);
250 return 0;
251 }
252
253 RtlZeroMemory(&Info, sizeof(BITMAPINFO));
254 Status = MmCopyFromCaller(&(Info.bmiHeader.biSize),
255 &(UnsafeInfo->bmiHeader.biSize),
256 sizeof(DWORD));
257 if (! NT_SUCCESS(Status))
258 {
259 SetLastNtError(Status);
260 GDIOBJ_UnlockObj(hBitmap, GO_BITMAP_MAGIC);
261 return 0;
262 }
263
264 /* If the bits are not requested, UnsafeInfo can point to either a
265 BITMAPINFOHEADER or a BITMAPCOREHEADER */
266 if (sizeof(BITMAPINFOHEADER) != Info.bmiHeader.biSize &&
267 (sizeof(BITMAPCOREHEADER) != Info.bmiHeader.biSize ||
268 NULL != Bits))
269 {
270 SetLastWin32Error(ERROR_INVALID_PARAMETER);
271 GDIOBJ_UnlockObj(hBitmap, GO_BITMAP_MAGIC);
272 return 0;
273 }
274
275 Status = MmCopyFromCaller(&(Info.bmiHeader),
276 &(UnsafeInfo->bmiHeader),
277 Info.bmiHeader.biSize);
278 if (! NT_SUCCESS(Status))
279 {
280 SetLastNtError(Status);
281 GDIOBJ_UnlockObj(hBitmap, GO_BITMAP_MAGIC);
282 return 0;
283 }
284
285 if (NULL == Bits)
286 {
287 if (sizeof(BITMAPINFOHEADER) == Info.bmiHeader.biSize)
288 {
289 if (0 != Info.bmiHeader.biBitCount)
290 {
291 UNIMPLEMENTED;
292 }
293
294 Info.bmiHeader.biWidth = BitmapObj->bitmap.bmWidth;
295 Info.bmiHeader.biHeight = BitmapObj->bitmap.bmHeight;
296 Info.bmiHeader.biPlanes = BitmapObj->bitmap.bmPlanes;
297 Info.bmiHeader.biBitCount = BitmapObj->bitmap.bmBitsPixel;
298 Info.bmiHeader.biCompression = BI_RGB;
299 Info.bmiHeader.biSizeImage = BitmapObj->bitmap.bmHeight * BitmapObj->bitmap.bmWidthBytes;
300 }
301 else
302 {
303 Core = (BITMAPCOREHEADER *)(&Info.bmiHeader);
304 if (0 != Core->bcBitCount)
305 {
306 UNIMPLEMENTED;
307 }
308
309 Core->bcWidth = BitmapObj->bitmap.bmWidth;
310 Core->bcHeight = BitmapObj->bitmap.bmHeight;
311 Core->bcPlanes = BitmapObj->bitmap.bmPlanes;
312 Core->bcBitCount = BitmapObj->bitmap.bmBitsPixel;
313 }
314
315 Status = MmCopyToCaller(UnsafeInfo, &Info, Info.bmiHeader.biSize);
316 if (! NT_SUCCESS(Status))
317 {
318 SetLastNtError(Status);
319 GDIOBJ_UnlockObj(hBitmap, GO_BITMAP_MAGIC);
320 return 0;
321 }
322 Result = 1;
323 }
324 else if (0 == StartScan && Info.bmiHeader.biHeight == StartScan + ScanLines &&
325 Info.bmiHeader.biWidth == BitmapObj->bitmap.bmWidth &&
326 Info.bmiHeader.biHeight == BitmapObj->bitmap.bmHeight &&
327 Info.bmiHeader.biPlanes == BitmapObj->bitmap.bmPlanes &&
328 Info.bmiHeader.biBitCount == BitmapObj->bitmap.bmBitsPixel &&
329 8 < Info.bmiHeader.biBitCount)
330 {
331 Info.bmiHeader.biSizeImage = BitmapObj->bitmap.bmHeight * BitmapObj->bitmap.bmWidthBytes;
332 Status = MmCopyToCaller(Bits, BitmapObj->bitmap.bmBits, Info.bmiHeader.biSizeImage);
333 if (! NT_SUCCESS(Status))
334 {
335 SetLastNtError(Status);
336 GDIOBJ_UnlockObj(hBitmap, GO_BITMAP_MAGIC);
337 return 0;
338 }
339 RtlZeroMemory(&InfoWithBitFields, sizeof(InfoWithBitFields));
340 RtlCopyMemory(&(InfoWithBitFields.Info), &Info, sizeof(BITMAPINFO));
341 if (BI_BITFIELDS == Info.bmiHeader.biCompression)
342 {
343 DCObj = DC_HandleToPtr(hDC);
344 if (NULL == DCObj)
345 {
346 SetLastWin32Error(ERROR_INVALID_HANDLE);
347 GDIOBJ_UnlockObj(hBitmap, GO_BITMAP_MAGIC);
348 return 0;
349 }
350 PalGdi = (PPALGDI) AccessInternalObject((ULONG) DCObj->w.hPalette);
351 BitField = (DWORD *) ((char *) &InfoWithBitFields + InfoWithBitFields.Info.bmiHeader.biSize);
352 BitField[0] = PalGdi->RedMask;
353 BitField[1] = PalGdi->GreenMask;
354 BitField[2] = PalGdi->BlueMask;
355 InfoSize = InfoWithBitFields.Info.bmiHeader.biSize + 3 * sizeof(DWORD);
356 DC_ReleasePtr(hDC);
357 }
358 else
359 {
360 InfoSize = Info.bmiHeader.biSize;
361 }
362 Status = MmCopyToCaller(UnsafeInfo, &InfoWithBitFields, InfoSize);
363 if (! NT_SUCCESS(Status))
364 {
365 SetLastNtError(Status);
366 GDIOBJ_UnlockObj(hBitmap, GO_BITMAP_MAGIC);
367 return 0;
368 }
369 }
370 else
371 {
372 UNIMPLEMENTED;
373 }
374
375 GDIOBJ_UnlockObj(hBitmap, GO_BITMAP_MAGIC);
376
377 return Result;
378 }
379
380 INT STDCALL W32kStretchDIBits(HDC hDC,
381 INT XDest,
382 INT YDest,
383 INT DestWidth,
384 INT DestHeight,
385 INT XSrc,
386 INT YSrc,
387 INT SrcWidth,
388 INT SrcHeight,
389 CONST VOID *Bits,
390 CONST BITMAPINFO *BitsInfo,
391 UINT Usage,
392 DWORD ROP)
393 {
394 UNIMPLEMENTED;
395 }
396
397 LONG STDCALL W32kGetBitmapBits(HBITMAP hBitmap,
398 LONG Count,
399 LPVOID Bits)
400 {
401 PBITMAPOBJ bmp;
402 LONG height, ret;
403
404 bmp = BITMAPOBJ_HandleToPtr (hBitmap);
405 if (!bmp)
406 {
407 return 0;
408 }
409
410 /* If the bits vector is null, the function should return the read size */
411 if (Bits == NULL)
412 {
413 return bmp->bitmap.bmWidthBytes * bmp->bitmap.bmHeight;
414 }
415
416 if (Count < 0)
417 {
418 DPRINT ("(%ld): Negative number of bytes passed???\n", Count);
419 Count = -Count;
420 }
421
422 /* Only get entire lines */
423 height = Count / bmp->bitmap.bmWidthBytes;
424 if (height > bmp->bitmap.bmHeight)
425 {
426 height = bmp->bitmap.bmHeight;
427 }
428 Count = height * bmp->bitmap.bmWidthBytes;
429 if (Count == 0)
430 {
431 DPRINT("Less then one entire line requested\n");
432 return 0;
433 }
434
435 DPRINT("(%08x, %ld, %p) %dx%d %d colors fetched height: %ld\n",
436 hBitmap, Count, Bits, bmp->bitmap.bmWidth, bmp->bitmap.bmHeight,
437 1 << bmp->bitmap.bmBitsPixel, height );
438 #if 0
439 /* FIXME: Call DDI CopyBits here if available */
440 if(bmp->DDBitmap)
441 {
442 DPRINT("Calling device specific BitmapBits\n");
443 if(bmp->DDBitmap->funcs->pBitmapBits)
444 {
445 ret = bmp->DDBitmap->funcs->pBitmapBits(hbitmap, bits, count,
446 DDB_GET);
447 }
448 else
449 {
450 ERR_(bitmap)("BitmapBits == NULL??\n");
451 ret = 0;
452 }
453 }
454 else
455 #endif
456 {
457 if(!bmp->bitmap.bmBits)
458 {
459 DPRINT ("Bitmap is empty\n");
460 ret = 0;
461 }
462 else
463 {
464 memcpy(Bits, bmp->bitmap.bmBits, Count);
465 ret = Count;
466 }
467 }
468
469 return ret;
470 }
471
472 // The CreateDIBitmap function creates a device-dependent bitmap (DDB) from a DIB and, optionally, sets the bitmap bits
473 // The DDB that is created will be whatever bit depth your reference DC is
474 HBITMAP STDCALL W32kCreateDIBitmap(HDC hdc, const BITMAPINFOHEADER *header,
475 DWORD init, LPCVOID bits, const BITMAPINFO *data,
476 UINT coloruse)
477 {
478 HBITMAP handle;
479 BOOL fColor;
480 DWORD width;
481 int height;
482 WORD bpp;
483 WORD compr;
484
485 if (DIB_GetBitmapInfo( header, &width, &height, &bpp, &compr ) == -1) return 0;
486 if (height < 0) height = -height;
487
488 // Check if we should create a monochrome or color bitmap. We create a monochrome bitmap only if it has exactly 2
489 // colors, which are black followed by white, nothing else. In all other cases, we create a color bitmap.
490
491 if (bpp != 1) fColor = TRUE;
492 else if ((coloruse != DIB_RGB_COLORS) ||
493 (init != CBM_INIT) || !data) fColor = FALSE;
494 else
495 {
496 if (data->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
497 {
498 RGBQUAD *rgb = data->bmiColors;
499 DWORD col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
500
501 // Check if the first color of the colormap is black
502 if ((col == RGB(0, 0, 0)))
503 {
504 rgb++;
505 col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
506
507 // If the second color is white, create a monochrome bitmap
508 fColor = (col != RGB(0xff,0xff,0xff));
509 }
510 else fColor = TRUE;
511 }
512 else if (data->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
513 {
514 RGBTRIPLE *rgb = ((BITMAPCOREINFO *)data)->bmciColors;
515 DWORD col = RGB( rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue);
516
517 if ((col == RGB(0,0,0)))
518 {
519 rgb++;
520 col = RGB( rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue );
521 fColor = (col != RGB(0xff,0xff,0xff));
522 }
523 else fColor = TRUE;
524 }
525 else
526 {
527 DPRINT("(%ld): wrong size for data\n", data->bmiHeader.biSize );
528 return 0;
529 }
530 }
531
532 // Now create the bitmap
533
534 if(fColor)
535 {
536 // If we are using indexed colors, then we need to create a bitmap that is compatible with the palette
537 if(coloruse == DIB_PAL_COLORS)
538 {
539 handle = W32kCreateCompatibleBitmap(hdc, width, height);
540 }
541 else if(coloruse == DIB_RGB_COLORS) {
542 handle = W32kCreateBitmap(width, height, 1, 24, NULL);
543 }
544 }
545 else handle = W32kCreateBitmap(width, height, 1, 1, NULL);
546
547 if (!handle) return 0;
548
549 if (init == CBM_INIT)
550 {
551 W32kSetDIBits(hdc, handle, 0, height, bits, data, coloruse);
552 }
553
554 return handle;
555 }
556
557 HBITMAP STDCALL W32kCreateDIBSection(HDC hDC,
558 CONST BITMAPINFO *bmi,
559 UINT Usage,
560 VOID *Bits,
561 HANDLE hSection,
562 DWORD dwOffset)
563 {
564 HBITMAP hbitmap = 0;
565 DC *dc;
566 BOOL bDesktopDC = FALSE;
567
568 // If the reference hdc is null, take the desktop dc
569 if (hDC == 0)
570 {
571 hDC = W32kCreateCompatableDC(0);
572 bDesktopDC = TRUE;
573 }
574
575 if ((dc = DC_HandleToPtr(hDC)))
576 {
577 hbitmap = DIB_CreateDIBSection(dc, bmi, Usage, Bits, hSection, dwOffset, 0);
578 DC_ReleasePtr(hDC);
579 }
580
581 if (bDesktopDC)
582 W32kDeleteDC(hDC);
583
584 return hbitmap;
585 }
586
587 HBITMAP STDCALL
588 DIB_CreateDIBSection(
589 PDC dc, BITMAPINFO *bmi, UINT usage,
590 LPVOID *bits, HANDLE section,
591 DWORD offset, DWORD ovr_pitch)
592 {
593 HBITMAP res = 0;
594 BITMAPOBJ *bmp = NULL;
595 DIBSECTION *dib = NULL;
596
597 // Fill BITMAP32 structure with DIB data
598 BITMAPINFOHEADER *bi = &bmi->bmiHeader;
599 INT effHeight, totalSize;
600 UINT Entries = 0;
601 BITMAP bm;
602
603 DPRINT("format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n",
604 bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
605 bi->biSizeImage, bi->biClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB");
606
607 effHeight = bi->biHeight >= 0 ? bi->biHeight : -bi->biHeight;
608 bm.bmType = 0;
609 bm.bmWidth = bi->biWidth;
610 bm.bmHeight = effHeight;
611 bm.bmWidthBytes = ovr_pitch ? ovr_pitch : DIB_GetDIBWidthBytes(bm.bmWidth, bi->biBitCount);
612
613 bm.bmPlanes = bi->biPlanes;
614 bm.bmBitsPixel = bi->biBitCount;
615 bm.bmBits = NULL;
616
617 // Get storage location for DIB bits. Only use biSizeImage if it's valid and
618 // we're dealing with a compressed bitmap. Otherwise, use width * height.
619 totalSize = bi->biSizeImage && bi->biCompression != BI_RGB
620 ? bi->biSizeImage : bm.bmWidthBytes * effHeight;
621
622 if (section)
623 /* bm.bmBits = MapViewOfFile(section, FILE_MAP_ALL_ACCESS,
624 0L, offset, totalSize); */
625 DPRINT("DIB_CreateDIBSection: Cannot yet handle section DIBs\n");
626 else if (ovr_pitch && offset)
627 bm.bmBits = (LPVOID) offset;
628 else {
629 offset = 0;
630 bm.bmBits = EngAllocUserMem(totalSize, 0);
631 }
632
633 /* bm.bmBits = ExAllocatePool(NonPagedPool, totalSize); */
634
635 if(usage == DIB_PAL_COLORS) memcpy(bmi->bmiColors, (UINT *)DIB_MapPaletteColors(dc, bmi), sizeof(UINT *));
636
637 // Allocate Memory for DIB and fill structure
638 if (bm.bmBits)
639 {
640 dib = ExAllocatePool(PagedPool, sizeof(DIBSECTION));
641 RtlZeroMemory(dib, sizeof(DIBSECTION));
642 }
643
644 if (dib)
645 {
646 dib->dsBm = bm;
647 dib->dsBmih = *bi;
648 dib->dsBmih.biSizeImage = totalSize;
649
650 /* Set dsBitfields values */
651 if ( usage == DIB_PAL_COLORS || bi->biBitCount <= 8)
652 {
653 dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
654 }
655 else switch(bi->biBitCount)
656 {
657 case 16:
658 dib->dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)bmi->bmiColors : 0x7c00;
659 dib->dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 1) : 0x03e0;
660 dib->dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 2) : 0x001f;
661 break;
662
663 case 24:
664 dib->dsBitfields[0] = 0xff;
665 dib->dsBitfields[1] = 0xff00;
666 dib->dsBitfields[2] = 0xff0000;
667 break;
668
669 case 32:
670 dib->dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)bmi->bmiColors : 0xff;
671 dib->dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 1) : 0xff00;
672 dib->dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 2) : 0xff0000;
673 break;
674 }
675 dib->dshSection = section;
676 dib->dsOffset = offset;
677 }
678
679 // Create Device Dependent Bitmap and add DIB pointer
680 if (dib)
681 {
682 res = W32kCreateDIBitmap(dc->hSelf, bi, 0, NULL, bmi, usage);
683 if (res)
684 {
685 bmp = BITMAPOBJ_HandleToPtr (res);
686 if (bmp)
687 {
688 bmp->dib = (DIBSECTION *) dib;
689 /* Install user-mode bits instead of kernel-mode bits */
690 ExFreePool(bmp->bitmap.bmBits);
691 bmp->bitmap.bmBits = bm.bmBits;
692 }
693 }
694
695 /* WINE NOTE: WINE makes use of a colormap, which is a color translation table between the DIB and the X physical
696 device. Obviously, this is left out of the ReactOS implementation. Instead, we call
697 W32kSetDIBColorTable. */
698 if(bi->biBitCount == 1) { Entries = 2; } else
699 if(bi->biBitCount == 4) { Entries = 16; } else
700 if(bi->biBitCount == 8) { Entries = 256; }
701
702 bmp->ColorMap = ExAllocatePool(NonPagedPool, sizeof(RGBQUAD)*Entries);
703 RtlCopyMemory(bmp->ColorMap, bmi->bmiColors, sizeof(RGBQUAD)*Entries);
704 }
705
706 // Clean up in case of errors
707 if (!res || !bmp || !dib || !bm.bmBits)
708 {
709 DPRINT("got an error res=%08x, bmp=%p, dib=%p, bm.bmBits=%p\n", res, bmp, dib, bm.bmBits);
710 /* if (bm.bmBits)
711 {
712 if (section)
713 UnmapViewOfFile(bm.bmBits), bm.bmBits = NULL;
714 else if (!offset)
715 VirtualFree(bm.bmBits, 0L, MEM_RELEASE), bm.bmBits = NULL;
716 } */
717
718 if (dib) { ExFreePool(dib); dib = NULL; }
719 if (bmp) { bmp = NULL; }
720 if (res) { GDIOBJ_FreeObj(res, GO_BITMAP_MAGIC, GDIOBJFLAG_DEFAULT); res = 0; }
721 }
722
723 if (bmp)
724 {
725 BITMAPOBJ_ReleasePtr(res);
726 }
727
728 // Return BITMAP handle and storage location
729 if (NULL != bm.bmBits && NULL != bits)
730 {
731 *bits = bm.bmBits;
732 }
733
734 return res;
735 }
736
737 /***********************************************************************
738 * DIB_GetDIBWidthBytes
739 *
740 * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
741 * http://www.microsoft.com/msdn/sdk/platforms/doc/sdk/win32/struc/src/str01.htm
742 * 11/16/1999 (RJJ) lifted from wine
743 */
744 INT FASTCALL DIB_GetDIBWidthBytes (INT width, INT depth)
745 {
746 int words;
747
748 switch(depth)
749 {
750 case 1: words = (width + 31) / 32; break;
751 case 4: words = (width + 7) / 8; break;
752 case 8: words = (width + 3) / 4; break;
753 case 15:
754 case 16: words = (width + 1) / 2; break;
755 case 24: words = (width * 3 + 3)/4; break;
756
757 default:
758 DPRINT("(%d): Unsupported depth\n", depth );
759 /* fall through */
760 case 32:
761 words = width;
762 }
763 return 4 * words;
764 }
765
766 /***********************************************************************
767 * DIB_GetDIBImageBytes
768 *
769 * Return the number of bytes used to hold the image in a DIB bitmap.
770 * 11/16/1999 (RJJ) lifted from wine
771 */
772
773 INT STDCALL DIB_GetDIBImageBytes (INT width, INT height, INT depth)
774 {
775 return DIB_GetDIBWidthBytes( width, depth ) * (height < 0 ? -height : height);
776 }
777
778 /***********************************************************************
779 * DIB_BitmapInfoSize
780 *
781 * Return the size of the bitmap info structure including color table.
782 * 11/16/1999 (RJJ) lifted from wine
783 */
784
785 INT FASTCALL DIB_BitmapInfoSize (const BITMAPINFO * info, WORD coloruse)
786 {
787 int colors;
788
789 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
790 {
791 BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)info;
792 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
793 return sizeof(BITMAPCOREHEADER) + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
794 }
795 else /* assume BITMAPINFOHEADER */
796 {
797 colors = info->bmiHeader.biClrUsed;
798 if (!colors && (info->bmiHeader.biBitCount <= 8)) colors = 1 << info->bmiHeader.biBitCount;
799 return sizeof(BITMAPINFOHEADER) + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
800 }
801 }
802
803 INT STDCALL DIB_GetBitmapInfo (const BITMAPINFOHEADER *header,
804 PDWORD width,
805 PINT height,
806 PWORD bpp,
807 PWORD compr)
808 {
809 if (header->biSize == sizeof(BITMAPINFOHEADER))
810 {
811 *width = header->biWidth;
812 *height = header->biHeight;
813 *bpp = header->biBitCount;
814 *compr = header->biCompression;
815 return 1;
816 }
817 if (header->biSize == sizeof(BITMAPCOREHEADER))
818 {
819 BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)header;
820 *width = core->bcWidth;
821 *height = core->bcHeight;
822 *bpp = core->bcBitCount;
823 *compr = 0;
824 return 0;
825 }
826 DPRINT("(%ld): wrong size for header\n", header->biSize );
827 return -1;
828 }
829
830 // Converts a Device Independent Bitmap (DIB) to a Device Dependant Bitmap (DDB)
831 // The specified Device Context (DC) defines what the DIB should be converted to
832 PBITMAPOBJ FASTCALL DIBtoDDB(HGLOBAL hPackedDIB, HDC hdc) // FIXME: This should be removed. All references to this function should
833 // change to W32kSetDIBits
834 {
835 HBITMAP hBmp = 0;
836 PBITMAPOBJ pBmp = NULL;
837 DIBSECTION *dib;
838 LPBYTE pbits = NULL;
839
840 // Get a pointer to the packed DIB's data
841 // pPackedDIB = (LPBYTE)GlobalLock(hPackedDIB);
842 dib = hPackedDIB;
843
844 pbits = (dib + DIB_BitmapInfoSize(&dib->dsBmih, DIB_RGB_COLORS));
845
846 // Create a DDB from the DIB
847 hBmp = W32kCreateDIBitmap(hdc, &dib->dsBmih, CBM_INIT, (LPVOID)pbits, &dib->dsBmih, DIB_RGB_COLORS);
848
849 // GlobalUnlock(hPackedDIB);
850
851 // Retrieve the internal Pixmap from the DDB
852 pBmp = (BITMAPOBJ *)GDIOBJ_LockObj(hBmp, GO_BITMAP_MAGIC);
853
854 return pBmp;
855 }
856
857 RGBQUAD * FASTCALL DIB_MapPaletteColors(PDC dc, LPBITMAPINFO lpbmi)
858 {
859 RGBQUAD *lpRGB;
860 int nNumColors,i;
861 DWORD *lpIndex;
862 PPALOBJ palObj;
863
864 palObj = AccessUserObject(dc->DevInfo->hpalDefault);
865
866 if (palObj == NULL) {
867 // RELEASEDCINFO(hDC);
868 return NULL;
869 }
870
871 nNumColors = 1 << lpbmi->bmiHeader.biBitCount;
872 if (lpbmi->bmiHeader.biClrUsed)
873 nNumColors = min(nNumColors, lpbmi->bmiHeader.biClrUsed);
874
875 lpRGB = (RGBQUAD *)ExAllocatePool(NonPagedPool, sizeof(RGBQUAD) * nNumColors);
876 lpIndex = (DWORD *)&lpbmi->bmiColors[0];
877
878 for (i=0; i<nNumColors; i++) {
879 lpRGB[i].rgbRed = palObj->logpalette->palPalEntry[*lpIndex].peRed;
880 lpRGB[i].rgbGreen = palObj->logpalette->palPalEntry[*lpIndex].peGreen;
881 lpRGB[i].rgbBlue = palObj->logpalette->palPalEntry[*lpIndex].peBlue;
882 lpIndex++;
883 }
884 // RELEASEDCINFO(hDC);
885 // RELEASEPALETTEINFO(hPalette);
886 return lpRGB;
887 }
888
889 PPALETTEENTRY STDCALL
890 DIBColorTableToPaletteEntries(PPALETTEENTRY palEntries, const RGBQUAD *DIBColorTable, ULONG ColorCount)
891 {
892 ULONG i;
893
894 for(i=0; i<ColorCount; i++)
895 {
896 palEntries->peRed = DIBColorTable->rgbRed;
897 palEntries->peGreen = DIBColorTable->rgbGreen;
898 palEntries->peBlue = DIBColorTable->rgbBlue;
899 palEntries++;
900 DIBColorTable++;
901 }
902 }
903
904 HPALETTE FASTCALL BuildDIBPalette (PBITMAPINFO bmi, PINT paletteType)
905 {
906 BYTE bits;
907 ULONG ColorCount;
908 PALETTEENTRY *palEntries;
909 HPALETTE hPal;
910
911 // Determine Bits Per Pixel
912 bits = bmi->bmiHeader.biBitCount;
913
914 // Determine paletteType from Bits Per Pixel
915 if(bits <= 8)
916 {
917 *paletteType = PAL_INDEXED;
918 } else
919 if(bits < 24)
920 {
921 *paletteType = PAL_BITFIELDS;
922 } else {
923 *paletteType = PAL_RGB; // Would it be BGR, considering the BGR nature of the DIB color table?
924 }
925
926 if (bmi->bmiHeader.biClrUsed == 0 &&
927 bmi->bmiHeader.biBitCount <= 8)
928 {
929 ColorCount = 1 << bmi->bmiHeader.biBitCount;
930 }
931 else
932 {
933 ColorCount = bmi->bmiHeader.biClrUsed;
934 }
935
936 palEntries = ExAllocatePool(NonPagedPool, sizeof(PALETTEENTRY)*ColorCount);
937 DIBColorTableToPaletteEntries(palEntries, bmi->bmiColors, ColorCount);
938 hPal = EngCreatePalette(*paletteType, ColorCount, palEntries, 0, 0, 0);
939 ExFreePool(palEntries);
940
941 return hPal;
942 }
943 /* EOF */