source: trunk/src/gdi32/dibitmap.cpp@ 5855

Last change on this file since 5855 was 5855, checked in by sandervl, 24 years ago

GetDIBits fix for querying the bitmap information

File size: 13.5 KB
Line 
1/* $Id: dibitmap.cpp,v 1.18 2001-06-01 07:49:30 sandervl Exp $ */
2
3/*
4 * GDI32 dib & bitmap code
5 *
6 * Copyright 1998 Sander van Leeuwen (sandervl@xs4all.nl)
7 * Copyright 1998 Patrick Haller
8 *
9 * Project Odin Software License can be found in LICENSE.TXT
10 *
11 */
12#include <os2win.h>
13#include <stdlib.h>
14#include <stdarg.h>
15#include <string.h>
16#include <misc.h>
17#include <winuser32.h>
18#include "dibsect.h"
19
20#define DBG_LOCALLOG DBG_dibitmap
21#include "dbglocal.h"
22
23//******************************************************************************
24//******************************************************************************
25HBITMAP WIN32API CreateDIBitmap(HDC hdc, const BITMAPINFOHEADER *lpbmih,
26 DWORD fdwInit, const void *lpbInit,
27 const BITMAPINFO *lpbmi, UINT fuUsage)
28{
29 int iHeight;
30 HBITMAP rc;
31
32 //SvL: Completely wrong result when creating a 1bpp bitmap here (converted
33 // to 8bpp by Open32)
34 if(lpbmih->biBitCount == 1) {
35 dprintf(("WARNING: CreateDIBitmap doesn't handle 1bpp bitmaps very well!!!!!"));
36 }
37
38 //TEMPORARY HACK TO PREVENT CRASH IN OPEN32 (WSeB GA)
39
40 iHeight = lpbmih->biHeight;
41 if(lpbmih->biHeight < 0)
42 {
43 dprintf(("GDI32: CreateDIBitmap negative height! (%d,%d)", lpbmih->biWidth, lpbmih->biHeight));
44 ((BITMAPINFOHEADER *)lpbmih)->biHeight = -lpbmih->biHeight;
45 }
46
47 // 2000/09/01 PH Netscape 4.7
48 // If color depth of lpbhmi is 16 bit and lpbmi is 8 bit,
49 // Open32 will crash since it won't allocate any palette color memory,
50 // however wants to copy it later on ...
51 int biBitCount = lpbmih->biBitCount;
52
53 if (lpbmih->biBitCount != lpbmi->bmiHeader.biBitCount)
54 {
55 dprintf(("GDI32: CreateDIBitmap: color depths of bitmaps differ! (%d,%d\n",
56 lpbmih->biBitCount,
57 lpbmi->bmiHeader.biBitCount));
58
59 ((BITMAPINFOHEADER *)lpbmih)->biBitCount = lpbmi->bmiHeader.biBitCount;
60 }
61
62 rc = O32_CreateDIBitmap(hdc, lpbmih, fdwInit, lpbInit, lpbmi, fuUsage);
63
64 dprintf(("GDI32: CreateDIBitmap %x %x %x %x %x returned %x (%d,%d, bps %d)", hdc, lpbmih, fdwInit, lpbInit, fuUsage, rc, lpbmih->biWidth, lpbmih->biHeight, lpbmih->biBitCount));
65
66 ((BITMAPINFOHEADER *)lpbmih)->biHeight = iHeight;
67 ((BITMAPINFOHEADER *)lpbmih)->biBitCount = biBitCount;
68
69 return rc;
70}
71//******************************************************************************
72//******************************************************************************
73HBITMAP WIN32API CreateCompatibleBitmap( HDC hdc, int nWidth, int nHeight)
74{
75 HBITMAP hBitmap;
76
77 hBitmap = O32_CreateCompatibleBitmap(hdc, nWidth, nHeight);
78 dprintf(("GDI32: CreateCompatibleBitmap %x (%d,%d) returned %x", hdc, nWidth, nHeight, hBitmap));
79 return hBitmap;
80}
81//******************************************************************************
82//CreateDisardableBitmap is obsolete and can be replaced by CreateCompatibleBitmap
83//******************************************************************************
84HBITMAP WIN32API CreateDiscardableBitmap(HDC hDC, int nWidth, int nHeight)
85{
86 dprintf(("GDI32: CreateDisardableBitmap\n"));
87 return CreateCompatibleBitmap(hDC, nWidth, nHeight);
88}
89//******************************************************************************
90//******************************************************************************
91HBITMAP WIN32API CreateBitmap(int nWidth, int nHeight, UINT cPlanes,
92 UINT cBitsPerPel, const void *lpvBits)
93{
94 HBITMAP hBitmap;
95
96 hBitmap = O32_CreateBitmap(nWidth, nHeight, cPlanes, cBitsPerPel, lpvBits);
97 dprintf(("GDI32: CreateBitmap (%d,%d) bps %d returned %x", nWidth, nHeight, cBitsPerPel, hBitmap));
98 return(hBitmap);
99}
100//******************************************************************************
101//******************************************************************************
102HBITMAP WIN32API CreateBitmapIndirect( const BITMAP * arg1)
103{
104 dprintf(("GDI32: CreateBitmapIndirect"));
105 return O32_CreateBitmapIndirect(arg1);
106}
107//******************************************************************************
108//*********************************************************************************
109HBITMAP WIN32API CreateDIBSection( HDC hdc, BITMAPINFO *pbmi, UINT iUsage,
110 VOID **ppvBits, HANDLE hSection, DWORD dwOffset)
111{
112 HBITMAP res = 0;
113 BOOL fFlip = 0;
114 int iHeight, iWidth;
115 BOOL fCreateDC = FALSE;
116
117 dprintf(("GDI32: CreateDIBSection %x %x %x %x %x %d", hdc, pbmi, iUsage, ppvBits, hSection, dwOffset));
118
119 //SvL: 13-9-98: StarCraft uses bitmap with negative height
120 iWidth = pbmi->bmiHeader.biWidth;
121 if(pbmi->bmiHeader.biWidth < 0)
122 {
123 dprintf(("CreateDIBSection: width %d", pbmi->bmiHeader.biWidth));
124 pbmi->bmiHeader.biWidth = -pbmi->bmiHeader.biWidth;
125 fFlip = FLIP_HOR;
126 }
127 iHeight = pbmi->bmiHeader.biHeight;
128 if(pbmi->bmiHeader.biHeight < 0)
129 {
130 dprintf(("CreateDIBSection: height %d", pbmi->bmiHeader.biHeight));
131 pbmi->bmiHeader.biHeight = -pbmi->bmiHeader.biHeight;
132 fFlip |= FLIP_VERT;
133 }
134
135 //SvL: RP7 (update) calls this api with hdc == 0
136 if(hdc == 0) {
137 hdc = GetWindowDC(GetDesktopWindow());
138 fCreateDC = TRUE;
139 }
140 res = O32_CreateDIBitmap(hdc, &pbmi->bmiHeader, 0, NULL, pbmi, iUsage);
141 if (res)
142 {
143 char PalSize;
144 DIBSection *dsect;
145
146 dsect = new DIBSection((BITMAPINFOHEADER_W *)&pbmi->bmiHeader, (char *)&pbmi->bmiColors, iUsage, hSection, dwOffset, (DWORD)res, fFlip);
147
148 if(dsect != NULL)
149 {
150 PalSize = dsect->GetBitCount();
151 if(PalSize <= 8)
152 {
153 ULONG Pal[256], nrcolors;
154 LOGPALETTE tmpPal = { 0x300,1,{0,0,0,0}};
155 HPALETTE hpalCur, hpalTmp;
156
157 // Now get the current Palette from the DC
158 hpalTmp = CreatePalette(&tmpPal);
159 hpalCur = SelectPalette(hdc, hpalTmp, FALSE);
160
161 // and use it to set the DIBColorTable
162 nrcolors = GetPaletteEntries( hpalCur, 0, 1<<PalSize, (LPPALETTEENTRY)&Pal);
163 dsect->SetDIBColorTable(0, nrcolors, (LPPALETTEENTRY)&Pal);
164
165 // Restore the DC Palette
166 SelectPalette(hdc,hpalCur,FALSE);
167 DeleteObject(hpalTmp);
168 }
169//SvL: Shouldn't an app explicitely select the dib section into the hdc?
170// (RealPlayer does this)
171#if 0
172 // Set the hdc in the DIBSection so we can update the palete if a new
173 // Palette etc. gets selected into the DC.
174
175 dsect->SelectDIBObject(hdc);
176#endif
177
178 if(ppvBits!=NULL)
179 *ppvBits = dsect->GetDIBObject();
180
181 pbmi->bmiHeader.biWidth = iWidth;
182 pbmi->bmiHeader.biHeight = iHeight;
183
184 if(fCreateDC) ReleaseDC(GetDesktopWindow(), hdc);
185 return(res);
186 }
187 }
188 if(fCreateDC) ReleaseDC(GetDesktopWindow(), hdc);
189
190 /* Error. */
191 if (res)
192 DeleteObject(res);
193 *ppvBits = NULL;
194#ifdef DEBUG
195 dprintf(("GDI32: CreateDIBSection, error!\n"));
196 dprintf(("pbmi->biWidth %d", pbmi->bmiHeader.biWidth));
197 dprintf(("pbmi->biHeight %d", pbmi->bmiHeader.biHeight));
198 dprintf(("pbmi->biBitCount %d", pbmi->bmiHeader.biBitCount));
199#endif
200
201 return 0;
202}
203//******************************************************************************
204//******************************************************************************
205UINT WIN32API GetDIBColorTable(HDC hdc, UINT uStartIndex, UINT cEntries,
206 RGBQUAD *pColors)
207{
208 DIBSection *dsect = DIBSection::findHDC(hdc);
209 UINT rc;
210 int i;
211
212 dprintf(("GetDIBColorTable %x %d->%d %x", hdc, uStartIndex, cEntries, pColors));
213
214 if(dsect)
215 {
216 return(dsect->GetDIBColorTable(uStartIndex, cEntries, pColors));
217 }
218 //TODO: Is this correct?????
219 // Wine returns 0 if bitmap selected into dc with bpp > 8
220 HPALETTE hpal = GetCurrentObject(hdc, OBJ_PAL);
221 rc = O32_GetPaletteEntries(hpal, uStartIndex,
222 cEntries, (PALETTEENTRY *)pColors);
223 for(i=0;
224 i<cEntries;
225 i++)
226 {
227 BYTE tmp;
228 tmp = pColors[i].rgbBlue;
229 pColors[i].rgbBlue = pColors[i].rgbRed;
230 pColors[i].rgbRed = tmp;
231 pColors[i].rgbReserved = 0;
232 }
233 dprintf(("GDI32: GetDIBColorTable returns %d\n", rc));
234 return(rc);
235}
236//******************************************************************************
237//******************************************************************************
238UINT WIN32API SetDIBColorTable(HDC hdc, UINT uStartIndex, UINT cEntries,
239 RGBQUAD *pColors)
240{
241 DIBSection *dsect = DIBSection::findHDC(hdc);
242
243 dprintf(("GDI32: SetDIBColorTable %x %d,%d %x", hdc, uStartIndex, cEntries, pColors));
244 if(dsect)
245 {
246 return(dsect->SetDIBColorTable(uStartIndex, cEntries, pColors));
247 }
248 else
249 return(0);
250}
251//******************************************************************************
252//******************************************************************************
253LONG WIN32API GetBitmapBits( HBITMAP hBitmap, LONG arg2, PVOID arg3)
254{
255 dprintf(("GDI32: GetBitmapBits %x", hBitmap));
256 return O32_GetBitmapBits(hBitmap, arg2, arg3);
257}
258//******************************************************************************
259//******************************************************************************
260LONG WIN32API SetBitmapBits( HBITMAP hBitmap, LONG arg2, const VOID * arg3)
261{
262 dprintf(("GDI32: SetBitmapBits %x", hBitmap));
263 return O32_SetBitmapBits(hBitmap, (DWORD)arg2, arg3);
264}
265//******************************************************************************
266//******************************************************************************
267BOOL WIN32API GetBitmapDimensionEx( HBITMAP hBitmap, PSIZE pSize)
268{
269 dprintf(("GDI32: GetBitmapDimensionEx %x (%d,%d)", hBitmap, pSize->cx, pSize->cy));
270 return O32_GetBitmapDimensionEx(hBitmap, pSize);
271}
272//******************************************************************************
273//******************************************************************************
274BOOL WIN32API SetBitmapDimensionEx( HBITMAP arg1, int arg2, int arg3, PSIZE arg4)
275{
276 dprintf(("GDI32: SetBitmapDimensionEx"));
277 return O32_SetBitmapDimensionEx(arg1, arg2, arg3, arg4);
278}
279//******************************************************************************
280//******************************************************************************
281int WIN32API GetDIBits(HDC hdc, HBITMAP hBitmap, UINT uStartScan, UINT cScanLines,
282 void *lpvBits, PBITMAPINFO lpbi, UINT uUsage)
283{
284 int rc;
285
286 dprintf(("GDI32: GetDIBits %x %x %d %d %x %x (biBitCount %d) %d", hdc, hBitmap, uStartScan, cScanLines, lpvBits, lpbi, lpbi->bmiHeader.biBitCount, uUsage));
287 rc = O32_GetDIBits(hdc, hBitmap, uStartScan, cScanLines, lpvBits, lpbi, uUsage);
288 // set proper color masks!
289 switch(lpbi->bmiHeader.biBitCount) {
290 case 16: //RGB 565
291 ((DWORD*)(lpbi->bmiColors))[0] = 0xF800;
292 ((DWORD*)(lpbi->bmiColors))[1] = 0x07E0;
293 ((DWORD*)(lpbi->bmiColors))[2] = 0x001F;
294 break;
295 case 24:
296 case 32:
297 ((DWORD*)(lpbi->bmiColors))[0] = 0x0000FF;
298 ((DWORD*)(lpbi->bmiColors))[1] = 0x00FF00;
299 ((DWORD*)(lpbi->bmiColors))[2] = 0xFF0000;
300 break;
301 }
302 //WGSS/Open32 returns 0 when querying the bitmap info; must return nr of scanlines
303 //as 0 signals failure
304 if(lpvBits == NULL) {
305 rc = cScanLines;
306 }
307 dprintf(("GDI32: GetDIBits return rc %d", rc));
308 return rc;
309}
310//******************************************************************************
311//******************************************************************************
312int WIN32API SetDIBits(HDC hdc, HBITMAP hBitmap, UINT startscan, UINT numlines, const VOID *pBits,
313 const BITMAPINFO *pBitmapInfo, UINT usage)
314{
315 int ret;
316
317 dprintf(("GDI32: SetDIBits %x %x %x %x %x %x %x", hdc, hBitmap, startscan, numlines, pBits, pBitmapInfo, usage));
318
319 //SvL: Open32's SetDIBits really messes things up for 1 bpp bitmaps, must use SetBitmapBits
320 if(pBitmapInfo->bmiHeader.biBitCount == 1 && startscan == 0 && numlines == pBitmapInfo->bmiHeader.biHeight)
321 {//WARNING: hack alert!
322 int dibwidth = DIB_GetDIBWidthBytes(pBitmapInfo->bmiHeader.biWidth, 1);
323 int bmpwidth = BITMAP_GetWidthBytes(pBitmapInfo->bmiHeader.biWidth, 1);
324 char *newpix = (char *)malloc(dibwidth*pBitmapInfo->bmiHeader.biHeight);
325 char *orgpix = (char *)pBits;
326 int ret;
327
328 dprintf(("Flipping 1bpp bitmap and calling SetBitmapBits (WORKAROUND) (%d -> %d)", dibwidth, bmpwidth));
329 newpix += ((pBitmapInfo->bmiHeader.biHeight-1)*bmpwidth);
330
331 //flip bitmap here; SetDIBits assumes origin is left bottom, SetBitmapBits left top
332 //SetDIBits assumes DWORD aligned data
333 //SetBitmapBits assumes WORD aligned data
334 for(int i=0;i<pBitmapInfo->bmiHeader.biHeight;i++) {
335 memcpy(newpix, orgpix, bmpwidth);
336
337 newpix -= bmpwidth;
338 orgpix += dibwidth;
339 }
340 newpix += bmpwidth;
341 ret = O32_SetBitmapBits(hBitmap, pBitmapInfo->bmiHeader.biSizeImage, newpix);
342
343 free(newpix);
344 return ret;
345 }
346#ifdef DEBUG
347 if(pBitmapInfo->bmiHeader.biBitCount == 1) {
348 dprintf(("ERROR: SetDIBits does NOT work well for 1 bpp bitmaps!!!!!"));
349 }
350#endif
351 ret = O32_SetDIBits(hdc, hBitmap, startscan, numlines, pBits, pBitmapInfo, usage);
352 if(DIBSection::getSection() != NULL)
353 {
354 DIBSection *dsect;
355
356 dsect = DIBSection::findObj(hBitmap);
357 if(dsect) {
358 HBITMAP hBmpOld = SelectObject(hdc, hBitmap);
359 dsect->sync(hdc, 0, dsect->GetHeight());
360 SelectObject(hdc, hBmpOld);
361 }
362 }
363
364 return ret;
365}
366//******************************************************************************
367//******************************************************************************
Note: See TracBrowser for help on using the repository browser.