source: trunk/src/gdi32/dibitmap.cpp

Last change on this file was 21304, checked in by ydario, 16 years ago

Gdi32 updates.

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