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

Last change on this file since 9565 was 9565, checked in by sandervl, 23 years ago

Support reversed bitmap data in SetDIBits

File size: 23.0 KB
Line 
1/* $Id: dibitmap.cpp,v 1.36 2002-12-30 14:05:21 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#include <stats.h>
22#include "oslibgpi.h"
23#include <objhandle.h>
24
25#define DBG_LOCALLOG DBG_dibitmap
26#include "dbglocal.h"
27
28ULONG CalcBitmapSize(ULONG cBits, LONG cx, LONG cy);
29
30//******************************************************************************
31//******************************************************************************
32HBITMAP WIN32API CreateDIBitmap(HDC hdc, const BITMAPINFOHEADER *lpbmih,
33 DWORD fdwInit, const void *lpbInit,
34 const BITMAPINFO *lpbmi, UINT fuUsage)
35{
36 int iHeight;
37 HBITMAP rc;
38 DWORD bitfields[3];
39 WORD *newbits = NULL;
40
41 //SvL: Completely wrong result when creating a 1bpp bitmap here (converted
42 // to 8bpp by Open32)
43 if(lpbmih->biBitCount == 1) {
44 dprintf(("WARNING: CreateDIBitmap doesn't handle 1bpp bitmaps very well!!!!!"));
45 }
46
47 //TEMPORARY HACK TO PREVENT CRASH IN OPEN32 (WSeB GA)
48 iHeight = lpbmih->biHeight;
49 if(lpbmih->biHeight < 0)
50 {
51 dprintf(("GDI32: CreateDIBitmap negative height! (%d,%d)", lpbmih->biWidth, lpbmih->biHeight));
52 //TODO: doesn't work if memory is readonly!!
53 ((BITMAPINFOHEADER *)lpbmih)->biHeight = -lpbmih->biHeight;
54
55 if(lpbInit && fdwInit == CBM_INIT)
56 {
57 // upside down
58 HBITMAP rc = 0;
59 long lLineByte = DIB_GetDIBWidthBytes(lpbmih->biWidth, lpbmih->biBitCount);
60 long lHeight = lpbmih->biHeight;
61
62 newbits = (WORD *)malloc( lLineByte * lHeight );
63 if(newbits) {
64 unsigned char *pbSrc = (unsigned char *)lpbInit + lLineByte * (lHeight - 1);
65 unsigned char *pbDst = (unsigned char *)newbits;
66 for(int y = 0; y < lHeight; y++) {
67 memcpy( pbDst, pbSrc, lLineByte );
68 pbDst += lLineByte;
69 pbSrc -= lLineByte;
70 }
71 rc = CreateDIBitmap(hdc, lpbmih, fdwInit, newbits, lpbmi, fuUsage);
72 free( newbits );
73 }
74
75 ((BITMAPINFOHEADER *)lpbmih)->biHeight = iHeight;
76 return rc;
77 }
78 }
79
80 // 2000/09/01 PH Netscape 4.7
81 // If color depth of lpbhmi is 16 bit and lpbmi is 8 bit,
82 // Open32 will crash since it won't allocate any palette color memory,
83 // however wants to copy it later on ...
84 int biBitCount = lpbmih->biBitCount;
85
86 if (lpbmih->biBitCount != lpbmi->bmiHeader.biBitCount)
87 {
88 dprintf(("GDI32: CreateDIBitmap: color depths of bitmaps differ! (%d,%d\n", lpbmih->biBitCount,
89 lpbmi->bmiHeader.biBitCount));
90
91 ((BITMAPINFOHEADER *)lpbmih)->biBitCount = lpbmi->bmiHeader.biBitCount;
92 }
93
94 switch(lpbmih->biBitCount) {
95 case 15:
96 case 16: //Default if BI_BITFIELDS not set is RGB 555
97 bitfields[0] = (lpbmih->biCompression == BI_BITFIELDS) ? *(DWORD *)lpbmi->bmiColors : DEFAULT_16BPP_RED_MASK;
98 bitfields[1] = (lpbmih->biCompression == BI_BITFIELDS) ? *((DWORD *)lpbmi->bmiColors + 1) : DEFAULT_16BPP_GREEN_MASK;
99 bitfields[2] = (lpbmih->biCompression == BI_BITFIELDS) ? *((DWORD *)lpbmi->bmiColors + 2) : DEFAULT_16BPP_BLUE_MASK;
100 break;
101 case 24:
102 case 32:
103 bitfields[0] = (lpbmih->biCompression == BI_BITFIELDS) ? *(DWORD *)lpbmi->bmiColors : DEFAULT_24BPP_RED_MASK;
104 bitfields[1] = (lpbmih->biCompression == BI_BITFIELDS) ? *((DWORD *)lpbmi->bmiColors + 1) : DEFAULT_24BPP_GREEN_MASK;
105 bitfields[2] = (lpbmih->biCompression == BI_BITFIELDS) ? *((DWORD *)lpbmi->bmiColors + 2) : DEFAULT_24BPP_BLUE_MASK;
106 break;
107 default:
108 bitfields[0] = 0;
109 bitfields[1] = 0;
110 bitfields[2] = 0;
111 break;
112 }
113 if(bitfields[1] == RGB555_GREEN_MASK && lpbInit && fdwInit == CBM_INIT)
114 {//RGB 555?
115 dprintf(("RGB 555->565 conversion required %x %x %x", bitfields[0], bitfields[1], bitfields[2]));
116
117 int imgsize = CalcBitmapSize(lpbmih->biBitCount, lpbmih->biWidth, lpbmih->biHeight);
118
119 newbits = (WORD *)malloc(imgsize);
120 if(CPUFeatures & CPUID_MMX) {
121 RGB555to565MMX(newbits, (WORD *)lpbInit, imgsize/sizeof(WORD));
122 }
123 else RGB555to565(newbits, (WORD *)lpbInit, imgsize/sizeof(WORD));
124 lpbInit = newbits;
125 }
126
127 rc = O32_CreateDIBitmap(hdc, lpbmih, fdwInit, lpbInit, lpbmi, fuUsage);
128
129 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));
130
131 if(newbits) free(newbits);
132
133 ((BITMAPINFOHEADER *)lpbmih)->biHeight = iHeight;
134 ((BITMAPINFOHEADER *)lpbmih)->biBitCount = biBitCount;
135
136 if(rc) {
137 STATS_CreateDIBitmap(rc, hdc, lpbmih, fdwInit, lpbInit, lpbmi, fuUsage);
138 if(bitfields[1] == RGB565_GREEN_MASK) {
139 //mark bitmap as RGB565
140 dprintf(("RGB565 bitmap"));
141 ObjSetHandleFlag(rc, OBJHANDLE_FLAG_BMP_RGB565, TRUE);
142 }
143 }
144
145 return rc;
146}
147//******************************************************************************
148//******************************************************************************
149HBITMAP WIN32API CreateCompatibleBitmap( HDC hdc, int nWidth, int nHeight)
150{
151 HBITMAP hBitmap;
152 pDCData pHps;
153
154 pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
155 if(!pHps)
156 {
157 SetLastError(ERROR_INVALID_HANDLE);
158 return 0;
159 }
160
161 hBitmap = O32_CreateCompatibleBitmap(hdc, nWidth, nHeight);
162 if(hBitmap) {
163 STATS_CreateCompatibleBitmap(hBitmap,hdc, nWidth, nHeight);
164 if(pHps->hwnd == 1) { //1 == HWND_DESKTOP
165 dprintf(("Screen compatible bitmap"));
166 ObjSetHandleFlag(hBitmap, OBJHANDLE_FLAG_BMP_SCREEN_COMPATIBLE, 1);
167 }
168 }
169
170 return hBitmap;
171}
172//******************************************************************************
173//CreateDisardableBitmap is obsolete and can be replaced by CreateCompatibleBitmap
174//******************************************************************************
175HBITMAP WIN32API CreateDiscardableBitmap(HDC hDC, int nWidth, int nHeight)
176{
177 dprintf(("GDI32: CreateDisardableBitmap"));
178 return CreateCompatibleBitmap(hDC, nWidth, nHeight);
179}
180//******************************************************************************
181//******************************************************************************
182HBITMAP WIN32API CreateBitmap(int nWidth, int nHeight, UINT cPlanes,
183 UINT cBitsPerPel, const void *lpvBits)
184{
185 HBITMAP hBitmap;
186
187 hBitmap = O32_CreateBitmap(nWidth, nHeight, cPlanes, cBitsPerPel, lpvBits);
188 if(hBitmap) STATS_CreateBitmap(hBitmap,nWidth, nHeight, cPlanes, cBitsPerPel, lpvBits);
189 return(hBitmap);
190}
191//******************************************************************************
192//******************************************************************************
193HBITMAP WIN32API CreateBitmapIndirect( const BITMAP *pBitmap)
194{
195 HBITMAP hBitmap;
196
197 dprintf(("GDI32: CreateBitmapIndirect (%d,%d) bpp %d bits %x", pBitmap->bmWidth, pBitmap->bmHeight, pBitmap->bmBitsPixel, pBitmap->bmBits));
198 hBitmap = O32_CreateBitmapIndirect(pBitmap);
199 if(hBitmap) STATS_CreateBitmapIndirect(hBitmap, pBitmap);
200 return hBitmap;
201}
202//******************************************************************************
203//*********************************************************************************
204HBITMAP WIN32API CreateDIBSection( HDC hdc, BITMAPINFO *pbmi, UINT iUsage,
205 VOID **ppvBits, HANDLE hSection, DWORD dwOffset)
206{
207 HBITMAP res = 0;
208 BOOL fFlip = 0;
209 int iHeight, iWidth;
210 BOOL fCreateDC = FALSE;
211
212 dprintf(("GDI32: CreateDIBSection %x %x %x %x %x %d", hdc, pbmi, iUsage, ppvBits, hSection, dwOffset));
213
214 //SvL: 13-9-98: StarCraft uses bitmap with negative height
215 iWidth = pbmi->bmiHeader.biWidth;
216 if(pbmi->bmiHeader.biWidth < 0)
217 {
218 dprintf(("CreateDIBSection: width %d", pbmi->bmiHeader.biWidth));
219 pbmi->bmiHeader.biWidth = -pbmi->bmiHeader.biWidth;
220 fFlip = FLIP_HOR;
221 }
222 iHeight = pbmi->bmiHeader.biHeight;
223 if(pbmi->bmiHeader.biHeight < 0)
224 {
225 dprintf(("CreateDIBSection: height %d", pbmi->bmiHeader.biHeight));
226 pbmi->bmiHeader.biHeight = -pbmi->bmiHeader.biHeight;
227 fFlip |= FLIP_VERT;
228 }
229
230 //SvL: RP7 (update) calls this api with hdc == 0
231 if(hdc == 0) {
232 hdc = CreateCompatibleDC(0);
233 fCreateDC = TRUE;
234 }
235 res = O32_CreateDIBitmap(hdc, &pbmi->bmiHeader, 0, NULL, pbmi, iUsage);
236 if (res)
237 {
238 char PalSize;
239 DIBSection *dsect;
240
241 dsect = new DIBSection((BITMAPINFOHEADER_W *)&pbmi->bmiHeader, (char *)&pbmi->bmiColors, iUsage, hSection, dwOffset, (DWORD)res, fFlip);
242
243 if(dsect != NULL)
244 {
245 PalSize = dsect->GetBitCount();
246 if(PalSize <= 8)
247 {
248 ULONG Pal[256], nrcolors;
249 LOGPALETTE tmpPal = { 0x300,1,{0,0,0,0}};
250 HPALETTE hpalCur, hpalTmp;
251
252 // Now get the current Palette from the DC
253 hpalTmp = CreatePalette(&tmpPal);
254 hpalCur = SelectPalette(hdc, hpalTmp, FALSE);
255
256 // and use it to set the DIBColorTable
257 nrcolors = GetPaletteEntries( hpalCur, 0, 1<<PalSize, (LPPALETTEENTRY)&Pal);
258 dsect->SetDIBColorTable(0, nrcolors, (LPPALETTEENTRY)&Pal);
259
260 // Restore the DC Palette
261 SelectPalette(hdc,hpalCur,FALSE);
262 DeleteObject(hpalTmp);
263 }
264
265 if(ppvBits!=NULL)
266 *ppvBits = dsect->GetDIBObject();
267
268 pbmi->bmiHeader.biWidth = iWidth;
269 pbmi->bmiHeader.biHeight = iHeight;
270
271 if(fCreateDC) DeleteDC(hdc);
272
273 STATS_CreateDIBSection(res, hdc, pbmi, iUsage, ppvBits, hSection, dwOffset);
274
275 return(res);
276 }
277 }
278 if(fCreateDC) DeleteDC(hdc);
279
280 /* Error. */
281 if (res)
282 DeleteObject(res);
283 *ppvBits = NULL;
284
285#ifdef DEBUG
286 dprintf(("GDI32: CreateDIBSection, error!\n"));
287 dprintf(("pbmi->biWidth %d", pbmi->bmiHeader.biWidth));
288 dprintf(("pbmi->biHeight %d", pbmi->bmiHeader.biHeight));
289 dprintf(("pbmi->biBitCount %d", pbmi->bmiHeader.biBitCount));
290#endif
291
292 return 0;
293}
294//******************************************************************************
295//******************************************************************************
296UINT WIN32API GetDIBColorTable(HDC hdc, UINT uStartIndex, UINT cEntries,
297 RGBQUAD *pColors)
298{
299 DIBSection *dsect = DIBSection::findHDC(hdc);
300 UINT rc;
301 int i;
302
303 dprintf(("GetDIBColorTable %x %d->%d %x", hdc, uStartIndex, cEntries, pColors));
304
305 if(dsect)
306 {
307 return(dsect->GetDIBColorTable(uStartIndex, cEntries, pColors));
308 }
309 //TODO: Is this correct?????
310 // Wine returns 0 if bitmap selected into dc with bpp > 8
311 HPALETTE hpal = GetCurrentObject(hdc, OBJ_PAL);
312 rc = O32_GetPaletteEntries(hpal, uStartIndex, cEntries, (PALETTEENTRY *)pColors);
313 for(i=0;i<cEntries;i++)
314 {
315 BYTE tmp;
316 tmp = pColors[i].rgbBlue;
317 pColors[i].rgbBlue = pColors[i].rgbRed;
318 pColors[i].rgbRed = tmp;
319 pColors[i].rgbReserved = 0;
320 }
321 dprintf(("GDI32: GetDIBColorTable returns %d\n", rc));
322 return(rc);
323}
324//******************************************************************************
325//******************************************************************************
326UINT WIN32API SetDIBColorTable(HDC hdc, UINT uStartIndex, UINT cEntries,
327 RGBQUAD *pColors)
328{
329 DIBSection *dsect = DIBSection::findHDC(hdc);
330
331 dprintf(("GDI32: SetDIBColorTable %x %d,%d %x", hdc, uStartIndex, cEntries, pColors));
332 if(dsect)
333 {
334 return(dsect->SetDIBColorTable(uStartIndex, cEntries, pColors));
335 }
336 else return(0);
337}
338//******************************************************************************
339//******************************************************************************
340LONG WIN32API GetBitmapBits( HBITMAP hBitmap, LONG arg2, PVOID arg3)
341{
342 dprintf(("GDI32: GetBitmapBits %x", hBitmap));
343 return O32_GetBitmapBits(hBitmap, arg2, arg3);
344}
345//******************************************************************************
346//******************************************************************************
347LONG WIN32API SetBitmapBits( HBITMAP hBitmap, LONG arg2, const VOID * arg3)
348{
349 dprintf(("GDI32: SetBitmapBits %x", hBitmap));
350 return O32_SetBitmapBits(hBitmap, (DWORD)arg2, arg3);
351}
352//******************************************************************************
353//******************************************************************************
354BOOL WIN32API GetBitmapDimensionEx( HBITMAP hBitmap, PSIZE pSize)
355{
356 dprintf(("GDI32: GetBitmapDimensionEx %x (%d,%d)", hBitmap, pSize->cx, pSize->cy));
357 return O32_GetBitmapDimensionEx(hBitmap, pSize);
358}
359//******************************************************************************
360//******************************************************************************
361BOOL WIN32API SetBitmapDimensionEx( HBITMAP arg1, int arg2, int arg3, PSIZE arg4)
362{
363 dprintf(("GDI32: SetBitmapDimensionEx"));
364 return O32_SetBitmapDimensionEx(arg1, arg2, arg3, arg4);
365}
366//******************************************************************************
367//******************************************************************************
368int WIN32API GetDIBits(HDC hdc, HBITMAP hBitmap, UINT uStartScan, UINT cScanLines,
369 void *lpvBits, PBITMAPINFO lpbi, UINT uUsage)
370{
371 int nrlines;
372 pDCData pHps;
373 HDC hdcMem;
374
375 dprintf(("GDI32: GetDIBits %x %x %d %d %x %x (biBitCount %d) %d", hdc, hBitmap, uStartScan, cScanLines, lpvBits, lpbi, lpbi->bmiHeader.biBitCount, uUsage));
376
377 //SvL: WGSS screws up the DC if it's a memory DC
378 // TODO: Fix in WGSS (tries to select another bitmap in the DC which fails)
379 pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
380 if(!pHps)
381 {
382 SetLastError(ERROR_INVALID_HANDLE);
383 return 0;
384 }
385 if(pHps->isMemoryPS) {
386 hdcMem = CreateCompatibleDC(0);
387 }
388 else hdcMem = hdc;
389
390 if(lpbi->bmiHeader.biHeight < 0) {
391 //NOTE: workaround for WGSS bug; remove when fixed
392 LONG height = lpbi->bmiHeader.biHeight;
393
394 nrlines = O32_GetDIBits(hdcMem, hBitmap, uStartScan, cScanLines, lpvBits, lpbi, uUsage);
395
396 //NOTE: workaround for WGSS bug; remove when fixed
397 lpbi->bmiHeader.biHeight = height;
398 }
399 else {
400 nrlines = O32_GetDIBits(hdcMem, hBitmap, uStartScan, cScanLines, lpvBits, lpbi, uUsage);
401 }
402
403 if(pHps->isMemoryPS)
404 DeleteDC(hdcMem);
405
406 if(lpvBits) {
407 // set proper color masks (only if lpvBits not NULL)
408 switch(lpbi->bmiHeader.biBitCount) {
409 case 15:
410 case 16: //RGB 565
411 {
412 DWORD dwFlags;
413
414 dwFlags = ObjQueryHandleFlags(hBitmap);
415 if(dwFlags & (OBJHANDLE_FLAG_BMP_SCREEN_COMPATIBLE|OBJHANDLE_FLAG_BMP_RGB565)) {
416 ((DWORD*)(lpbi->bmiColors))[0] = RGB565_RED_MASK;
417 ((DWORD*)(lpbi->bmiColors))[1] = RGB565_GREEN_MASK;
418 ((DWORD*)(lpbi->bmiColors))[2] = RGB565_BLUE_MASK;
419 }
420 else {
421 ((DWORD*)(lpbi->bmiColors))[0] = RGB555_RED_MASK;
422 ((DWORD*)(lpbi->bmiColors))[1] = RGB555_GREEN_MASK;
423 ((DWORD*)(lpbi->bmiColors))[2] = RGB555_BLUE_MASK;
424 }
425 break;
426 }
427 case 24:
428 case 32:
429 ((DWORD*)(lpbi->bmiColors))[0] = DEFAULT_24BPP_RED_MASK;
430 ((DWORD*)(lpbi->bmiColors))[1] = DEFAULT_24BPP_GREEN_MASK;
431 ((DWORD*)(lpbi->bmiColors))[2] = DEFAULT_24BPP_BLUE_MASK;
432 break;
433 }
434 if(lpbi->bmiHeader.biCompression == BI_RGB && lpbi->bmiHeader.biBitCount > 8) {
435 lpbi->bmiHeader.biCompression = BI_BITFIELDS;
436 dprintf(("BI_BITFIELDS: %x %x %x", ((DWORD*)(lpbi->bmiColors))[0], ((DWORD*)(lpbi->bmiColors))[1], ((DWORD*)(lpbi->bmiColors))[2]));
437 }
438 }
439 if(nrlines && lpvBits && lpbi->bmiHeader.biBitCount == 16 && ((DWORD*)(lpbi->bmiColors))[1] == RGB555_GREEN_MASK)
440 {//RGB 555?
441 dprintf(("RGB 565->555 conversion required"));
442
443 int imgsize = CalcBitmapSize(lpbi->bmiHeader.biBitCount,
444 lpbi->bmiHeader.biWidth, nrlines);
445
446 if(CPUFeatures & CPUID_MMX) {
447 RGB565to555MMX((WORD *)lpvBits, (WORD *)lpvBits, imgsize/sizeof(WORD));
448 }
449 else RGB565to555((WORD *)lpvBits, (WORD *)lpvBits, imgsize/sizeof(WORD));
450 }
451
452 //WGSS/Open32 returns 0 when querying the bitmap info; must return nr of scanlines
453 //as 0 signals failure
454 if(lpvBits == NULL) {
455 nrlines = cScanLines;
456 }
457 return nrlines;
458}
459//******************************************************************************
460//******************************************************************************
461void WIN32API ConvertRGB555to565(LPVOID dest, LPVOID src, UINT imgsize)
462{
463 if(CPUFeatures & CPUID_MMX) {
464 RGB555to565MMX((WORD *)dest, (WORD *)src, imgsize/sizeof(WORD));
465 }
466 else RGB555to565((WORD *)dest, (WORD *)src, imgsize/sizeof(WORD));
467}
468//******************************************************************************
469//******************************************************************************
470int WIN32API SetDIBits(HDC hdc, HBITMAP hBitmap, UINT startscan, UINT numlines, const VOID *pBits,
471 const BITMAPINFO *pBitmapInfo, UINT usage)
472{
473 int ret;
474 DWORD bitfields[3];
475 WORD *newbits = NULL;
476
477 dprintf(("GDI32: SetDIBits %x %x %x %x %x %x %x", hdc, hBitmap, startscan, numlines, pBits, pBitmapInfo, usage));
478
479 //SvL: Open32's SetDIBits really messes things up for 1 bpp bitmaps, must use SetBitmapBits
480 if(pBitmapInfo->bmiHeader.biBitCount == 1 && startscan == 0 && numlines == pBitmapInfo->bmiHeader.biHeight)
481 {//WARNING: hack alert!
482 int dibwidth = DIB_GetDIBWidthBytes(pBitmapInfo->bmiHeader.biWidth, 1);
483 int bmpwidth = BITMAP_GetWidthBytes(pBitmapInfo->bmiHeader.biWidth, 1);
484 char *newpix = (char *)malloc(dibwidth*pBitmapInfo->bmiHeader.biHeight);
485 char *orgpix = (char *)pBits;
486 int ret;
487
488 dprintf(("Flipping 1bpp bitmap and calling SetBitmapBits (WORKAROUND) (%d -> %d)", dibwidth, bmpwidth));
489 newpix += ((pBitmapInfo->bmiHeader.biHeight-1)*bmpwidth);
490
491 //flip bitmap here; SetDIBits assumes origin is left bottom, SetBitmapBits left top
492 //SetDIBits assumes DWORD aligned data
493 //SetBitmapBits assumes WORD aligned data
494 for(int i=0;i<pBitmapInfo->bmiHeader.biHeight;i++) {
495 memcpy(newpix, orgpix, bmpwidth);
496
497 newpix -= bmpwidth;
498 orgpix += dibwidth;
499 }
500 newpix += bmpwidth;
501 ret = O32_SetBitmapBits(hBitmap, pBitmapInfo->bmiHeader.biSizeImage, newpix);
502
503 free(newpix);
504 return ret;
505 }
506#ifdef DEBUG
507 if(pBitmapInfo->bmiHeader.biBitCount == 1) {
508 dprintf(("ERROR: SetDIBits does NOT work well for 1 bpp bitmaps!!!!!"));
509 }
510#endif
511
512 switch(pBitmapInfo->bmiHeader.biBitCount) {
513 case 15:
514 case 16: //Default if BI_BITFIELDS not set is RGB 555
515 bitfields[0] = (pBitmapInfo->bmiHeader.biCompression == BI_BITFIELDS) ? *(DWORD *)pBitmapInfo->bmiColors : DEFAULT_16BPP_RED_MASK;
516 bitfields[1] = (pBitmapInfo->bmiHeader.biCompression == BI_BITFIELDS) ? *((DWORD *)pBitmapInfo->bmiColors + 1) : DEFAULT_16BPP_GREEN_MASK;
517 bitfields[2] = (pBitmapInfo->bmiHeader.biCompression == BI_BITFIELDS) ? *((DWORD *)pBitmapInfo->bmiColors + 2) : DEFAULT_16BPP_BLUE_MASK;
518 break;
519
520 case 24:
521 case 32:
522 bitfields[0] = (pBitmapInfo->bmiHeader.biCompression == BI_BITFIELDS) ? *(DWORD *)pBitmapInfo->bmiColors : DEFAULT_24BPP_RED_MASK;
523 bitfields[1] = (pBitmapInfo->bmiHeader.biCompression == BI_BITFIELDS) ? *((DWORD *)pBitmapInfo->bmiColors + 1) : DEFAULT_24BPP_GREEN_MASK;
524 bitfields[2] = (pBitmapInfo->bmiHeader.biCompression == BI_BITFIELDS) ? *((DWORD *)pBitmapInfo->bmiColors + 2) : DEFAULT_24BPP_BLUE_MASK;
525 break;
526 default:
527 bitfields[0] = 0;
528 bitfields[1] = 0;
529 bitfields[2] = 0;
530 break;
531 }
532 if(pBits && bitfields[1] == RGB555_GREEN_MASK)
533 {//RGB 555?
534 dprintf(("RGB 555->565 conversion required %x %x %x", bitfields[0], bitfields[1], bitfields[2]));
535
536 int imgsize = CalcBitmapSize(pBitmapInfo->bmiHeader.biBitCount,
537 pBitmapInfo->bmiHeader.biWidth, numlines);
538
539 newbits = (WORD *)malloc(imgsize);
540 if(CPUFeatures & CPUID_MMX) {
541 RGB555to565MMX(newbits, (WORD *)pBits, imgsize/sizeof(WORD));
542 }
543 else RGB555to565(newbits, (WORD *)pBits, imgsize/sizeof(WORD));
544 pBits = newbits;
545 }
546
547 //If upside down, reverse scanlines and call SetDIBits again
548 if(pBitmapInfo->bmiHeader.biHeight < 0 && (pBitmapInfo->bmiHeader.biCompression == BI_RGB ||
549 pBitmapInfo->bmiHeader.biCompression == BI_BITFIELDS))
550 {
551 // upside down
552 INT rc = -1;
553 long lLineByte;
554
555 //TODO: doesn't work if memory is readonly!!
556 ((BITMAPINFO *)pBitmapInfo)->bmiHeader.biHeight = -pBitmapInfo->bmiHeader.biHeight;
557
558 lLineByte = DIB_GetDIBWidthBytes(pBitmapInfo->bmiHeader.biWidth, pBitmapInfo->bmiHeader.biBitCount);
559
560 dprintf(("Reverse bitmap (negative height)"));
561 char *pNewBits = (char *)malloc( lLineByte * numlines );
562 if(pNewBits) {
563 unsigned char *pbSrc = (unsigned char *)pBits + lLineByte * (numlines - 1);
564 unsigned char *pbDst = (unsigned char *)pNewBits;
565 for(int y = 0; y < numlines; y++) {
566 memcpy( pbDst, pbSrc, lLineByte );
567 pbDst += lLineByte;
568 pbSrc -= lLineByte;
569 }
570 ret = O32_SetDIBits(hdc, hBitmap, startscan, numlines, pNewBits, pBitmapInfo, usage);
571 free(pNewBits);
572 }
573 else DebugInt3();
574
575 //TODO: doesn't work if memory is readonly!!
576 ((BITMAPINFO *)pBitmapInfo)->bmiHeader.biHeight = -pBitmapInfo->bmiHeader.biHeight;
577 }
578 else {
579 ret = O32_SetDIBits(hdc, hBitmap, startscan, numlines, pBits, pBitmapInfo, usage);
580 }
581 if(newbits) free(newbits);
582
583 if(DIBSection::getSection() != NULL)
584 {
585 DIBSection *dsect;
586
587 dsect = DIBSection::findObj(hBitmap);
588 if(dsect) {
589 HBITMAP hBmpOld = SelectObject(hdc, hBitmap);
590 dsect->sync(hdc, 0, dsect->GetHeight());
591 SelectObject(hdc, hBmpOld);
592 }
593 }
594
595 return ret;
596}
597//******************************************************************************
598//******************************************************************************
Note: See TracBrowser for help on using the repository browser.