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