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