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

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

rgb conversions added + palette fix

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