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

Last change on this file since 10373 was 10373, checked in by sandervl, 22 years ago

Update

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