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