]>
git.saurik.com Git - wxWidgets.git/blob - src/msw/dibutils.cpp
1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Utilities for DIBs
4 // Author: Julian Smart
8 // Copyright: (c) Microsoft, Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "dibutils.h"
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
26 #include "wx/string.h"
33 #include "wx/msw/dibutils.h"
35 #if defined(__WIN32__)
36 #if !defined(__MWERKS__) && !defined(__SALFORDC__)
37 #include <memory.h> // for _fmemcpy()
41 #define hmemcpy memcpy
45 #define BFT_ICON 0x4349 /* 'IC' */
46 #define BFT_BITMAP 0x4d42 /* 'BM' */
47 #define BFT_CURSOR 0x5450 /* 'PT(' */
50 /* flags for _lseek */
56 /* Copied from PNGhandler for coompilation with MingW32, RR */
58 #ifndef GlobalAllocPtr
59 #define GlobalPtrHandle(lp) \
60 ((HGLOBAL)GlobalHandle(lp))
62 #define GlobalLockPtr(lp) \
63 ((BOOL)GlobalLock(GlobalPtrHandle(lp)))
64 #define GlobalUnlockPtr(lp) \
65 GlobalUnlock(GlobalPtrHandle(lp))
67 #define GlobalAllocPtr(flags, cb) \
68 (GlobalLock(GlobalAlloc((flags), (cb))))
69 #define GlobalReAllocPtr(lp, cbNew, flags) \
70 (GlobalUnlockPtr(lp), GlobalLock(GlobalReAlloc(GlobalPtrHandle(lp) , (cbNew), (flags))))
71 #define GlobalFreePtr(lp) \
72 (GlobalUnlockPtr(lp), (BOOL)GlobalFree(GlobalPtrHandle(lp)))
76 * Open a DIB file and return a MEMORY DIB, a memory handle containing..
83 int wxDibWriteFile(LPTSTR szFile
, LPBITMAPINFOHEADER lpbi
)
88 fh
= OpenFile(wxConvFile
.cWX2MB(szFile
), &of
, OF_WRITE
| OF_CREATE
);
94 long size
= wxDibSize(lpbi
);
98 bmf
.bfType
= BFT_BITMAP
;
99 bmf
.bfSize
= sizeof(bmf
) + size
;
102 bmf
.bfOffBits
= sizeof(bmf
) + (char FAR
*)(wxDibPtr(lpbi
)) - (char FAR
*)lpbi
;
103 #if 1 // defined( __WATCOMC__) || defined(__VISUALC__) || defined(__SC__) || defined(__SALFORDC__) || defined(__MWERKS__) || wxUSE_NORLANDER_HEADERS
104 #define HWRITE_2ND_ARG_TYPE LPCSTR
105 #else // don't know who needs this...
106 #define HWRITE_2ND_ARG_TYPE LPBYTE
109 if ( _hwrite(fh
, (HWRITE_2ND_ARG_TYPE
)(&bmf
), sizeof(bmf
)) < 0 ||
110 _hwrite(fh
, (HWRITE_2ND_ARG_TYPE
)lpbi
, size
) < 0 )
116 #undef HWRITE_2ND_ARG_TYPE
122 PDIB
wxDibOpenFile(LPTSTR szFile
)
131 #if defined(__WIN32__)
132 #define GetCurrentInstance() GetModuleHandle(NULL)
134 #define GetCurrentInstance() (HINSTANCE)SELECTOROF((LPVOID)&of)
137 fh
= OpenFile(wxConvFile
.cWX2MB(szFile
), &of
, OF_READ
);
143 // TODO: Unicode version
145 h
= FindResource(GetCurrentInstance(), szFile
, RT_BITMAP
);
147 h
= FindResourceW(GetCurrentInstance(), szFile
, RT_BITMAP
);
149 h
= FindResourceA(GetCurrentInstance(), szFile
, RT_BITMAP
);
152 #if defined(__WIN32__)
153 //!!! can we call GlobalFree() on this? is it the right format.
154 //!!! can we write to this resource?
156 return (PDIB
)LockResource(LoadResource(GetCurrentInstance(), h
));
159 fh
= AccessResource(GetCurrentInstance(), h
);
166 pdib
= wxDibReadBitmapInfo(fh
);
171 /* How much memory do we need to hold the DIB */
173 dwBits
= pdib
->biSizeImage
;
174 dwLen
= pdib
->biSize
+ wxDibPaletteSize(pdib
) + dwBits
;
176 /* Can we get more memory? */
178 p
= GlobalReAllocPtr(pdib
,dwLen
,0);
192 /* read in the bits */
193 _hread(fh
, (LPBYTE
)pdib
+ (UINT
)pdib
->biSize
+ wxDibPaletteSize(pdib
), dwBits
);
203 * ReadDibBitmapInfo()
205 * Will read a file in DIB format and return a global HANDLE to its
206 * BITMAPINFO. This function will work with both "old" and "new"
207 * bitmap formats, but will always return a "new" BITMAPINFO.
210 PDIB
wxDibReadBitmapInfo(HFILE fh
)
226 off
= _llseek(fh
,0L,SEEK_CUR
);
228 if (sizeof(bf
) != _lread(fh
,(LPSTR
)&bf
,sizeof(bf
)))
232 * do we have a RC HEADER?
234 if (bf
.bfType
!= BFT_BITMAP
)
237 _llseek(fh
,off
,SEEK_SET
);
240 if (sizeof(bi
) != _lread(fh
,(LPSTR
)&bi
,sizeof(bi
)))
244 * what type of bitmap info is this?
246 switch (size
= (int)bi
.biSize
)
249 case sizeof(BITMAPINFOHEADER
):
252 case sizeof(BITMAPCOREHEADER
):
253 bc
= *(BITMAPCOREHEADER
*)&bi
;
254 bi
.biSize
= sizeof(BITMAPINFOHEADER
);
255 bi
.biWidth
= (DWORD
)bc
.bcWidth
;
256 bi
.biHeight
= (DWORD
)bc
.bcHeight
;
257 bi
.biPlanes
= (WORD
)bc
.bcPlanes
;
258 bi
.biBitCount
= (WORD
)bc
.bcBitCount
;
259 bi
.biCompression
= BI_RGB
;
261 bi
.biXPelsPerMeter
= 0;
262 bi
.biYPelsPerMeter
= 0;
264 bi
.biClrImportant
= 0;
266 _llseek(fh
,(LONG
)sizeof(BITMAPCOREHEADER
)-sizeof(BITMAPINFOHEADER
),SEEK_CUR
);
271 nNumColors
= wxDibNumColors(&bi
);
274 if (bi
.biSizeImage
== 0)
275 bi
.biSizeImage
= DibSizeImage(&bi
);
277 if (bi
.biClrUsed
== 0)
278 bi
.biClrUsed
= wxDibNumColors(&bi
);
280 wxFixBitmapInfo(&bi
);
283 pdib
= (PDIB
)GlobalAllocPtr(GMEM_MOVEABLE
,(LONG
)bi
.biSize
+ nNumColors
* sizeof(RGBQUAD
));
290 pRgb
= wxDibColors(pdib
);
294 if (size
== sizeof(BITMAPCOREHEADER
))
297 * convert a old color table (3 byte entries) to a new
298 * color table (4 byte entries)
300 _lread(fh
,(LPVOID
)pRgb
,nNumColors
* sizeof(RGBTRIPLE
));
302 for (i
=nNumColors
-1; i
>=0; i
--)
306 rgb
.rgbRed
= ((RGBTRIPLE FAR
*)pRgb
)[i
].rgbtRed
;
307 rgb
.rgbBlue
= ((RGBTRIPLE FAR
*)pRgb
)[i
].rgbtBlue
;
308 rgb
.rgbGreen
= ((RGBTRIPLE FAR
*)pRgb
)[i
].rgbtGreen
;
309 rgb
.rgbReserved
= (BYTE
)0;
316 _lread(fh
,(LPVOID
)pRgb
,nNumColors
* sizeof(RGBQUAD
));
320 if (bf
.bfOffBits
!= 0L)
321 _llseek(fh
,off
+ bf
.bfOffBits
,SEEK_SET
);
327 * DibSetUsage(hdib,hpal,wUsage)
329 * Modifies the color table of the passed DIB for use with the wUsage
330 * parameter specifed.
332 * if wUsage is DIB_PAL_COLORS the DIB color table is set to 0-256
333 * if wUsage is DIB_RGB_COLORS the DIB color table is set to the RGB values
334 * in the passed palette
337 BOOL
wxDibSetUsage(PDIB pdib
, HPALETTE hpal
,UINT wUsage
)
339 PALETTEENTRY ape
[256];
346 hpal
= (HPALETTE
)GetStockObject(DEFAULT_PALETTE
);
351 nColors
= wxDibNumColors(pdib
);
353 if (nColors
== 3 && wxDibCompression(pdib
) == BI_BITFIELDS
)
358 pRgb
= wxDibColors(pdib
);
363 // Set the DIB color table to palette indexes
366 for (pw
= (WORD FAR
*)pRgb
,n
=0; n
<nColors
; n
++,pw
++)
371 // Set the DIB color table to RGBQUADS
375 nColors
= (nColors
< 256) ? nColors
: 256;
377 GetPaletteEntries(hpal
,0,nColors
,ape
);
379 for (n
=0; n
<nColors
; n
++)
381 pRgb
[n
].rgbRed
= ape
[n
].peRed
;
382 pRgb
[n
].rgbGreen
= ape
[n
].peGreen
;
383 pRgb
[n
].rgbBlue
= ape
[n
].peBlue
;
384 pRgb
[n
].rgbReserved
= 0;
393 * DibCreate(bits, dx, dy)
395 * Creates a new packed DIB with the given dimensions and the
396 * given number of bits per pixel
399 PDIB
wxDibCreate(int bits
, int dx
, int dy
)
401 LPBITMAPINFOHEADER lpbi
;
406 dwSizeImage
= dy
*(DWORD
)((dx
*bits
/8+3)&~3);
408 lpbi
= (PDIB
)GlobalAllocPtr(GHND
,sizeof(BITMAPINFOHEADER
)+dwSizeImage
+ 1024);
413 lpbi
->biSize
= sizeof(BITMAPINFOHEADER
) ;
417 lpbi
->biBitCount
= bits
;
418 lpbi
->biCompression
= BI_RGB
;
419 lpbi
->biSizeImage
= dwSizeImage
;
420 lpbi
->biXPelsPerMeter
= 0 ;
421 lpbi
->biYPelsPerMeter
= 0 ;
422 lpbi
->biClrUsed
= 0 ;
423 lpbi
->biClrImportant
= 0 ;
426 lpbi
->biClrUsed
= 16;
429 lpbi
->biClrUsed
= 256;
431 pdw
= (DWORD FAR
*)((LPBYTE
)lpbi
+(int)lpbi
->biSize
);
433 for (i
=0; i
<(int)lpbi
->biClrUsed
/16; i
++)
435 *pdw
++ = 0x00000000; // 0000 black
436 *pdw
++ = 0x00800000; // 0001 dark red
437 *pdw
++ = 0x00008000; // 0010 dark green
438 *pdw
++ = 0x00808000; // 0011 mustard
439 *pdw
++ = 0x00000080; // 0100 dark blue
440 *pdw
++ = 0x00800080; // 0101 purple
441 *pdw
++ = 0x00008080; // 0110 dark turquoise
442 *pdw
++ = 0x00C0C0C0; // 1000 gray
443 *pdw
++ = 0x00808080; // 0111 dark gray
444 *pdw
++ = 0x00FF0000; // 1001 red
445 *pdw
++ = 0x0000FF00; // 1010 green
446 *pdw
++ = 0x00FFFF00; // 1011 yellow
447 *pdw
++ = 0x000000FF; // 1100 blue
448 *pdw
++ = 0x00FF00FF; // 1101 pink (magenta)
449 *pdw
++ = 0x0000FFFF; // 1110 cyan
450 *pdw
++ = 0x00FFFFFF; // 1111 white
456 static void xlatClut8(BYTE FAR
*pb
, DWORD dwSize
, BYTE FAR
*xlat
)
461 for (dw
= 0; dw
< dwSize
; dw
++, ((BYTE _huge
*&)pb
)++)
463 for (dw
= 0; dw
< dwSize
; dw
++, ((BYTE _huge
*)pb
)++)
468 static void xlatClut4(BYTE FAR
*pb
, DWORD dwSize
, BYTE FAR
*xlat
)
473 for (dw
= 0; dw
< dwSize
; dw
++, ((BYTE _huge
*&)pb
)++)
475 for (dw
= 0; dw
< dwSize
; dw
++, ((BYTE _huge
*)pb
)++)
477 *pb
= (BYTE
)(xlat
[*pb
& 0x0F] | (xlat
[(*pb
>> 4) & 0x0F] << 4));
485 static void xlatRle8(BYTE FAR
*pb
, DWORD
WXUNUSED(dwSize
), BYTE FAR
*xlat
)
489 BYTE _huge
*prle
= pb
;
496 if (cnt
== RLE_ESCAPE
)
515 for (b
=0; b
<cnt
; b
++,prle
++)
531 static void xlatRle4(BYTE FAR
*WXUNUSED(pb
), DWORD
WXUNUSED(dwSize
), BYTE FAR
*WXUNUSED(xlat
))
535 static void hmemmove(BYTE _huge
*d
, BYTE _huge
*s
, LONG len
)
545 * DibMapToPalette(pdib, hpal)
547 * Map the colors of the DIB, using GetNearestPaletteIndex, to
548 * the colors of the given palette.
551 BOOL
wxDibMapToPalette(PDIB pdib
, HPALETTE hpal
)
553 LPBITMAPINFOHEADER lpbi
;
566 lpbi
= (LPBITMAPINFOHEADER
)pdib
;
567 lpRgb
= wxDibColors(pdib
);
569 GetObject(hpal
,sizeof(int),(LPSTR
)&nPalColors
);
570 nDibColors
= wxDibNumColors(pdib
);
572 if ((SizeImage
= lpbi
->biSizeImage
) == 0)
573 SizeImage
= wxDibSizeImage(lpbi
);
576 // build a xlat table. from the current DIB colors to the given
579 for (n
=0; n
<nDibColors
; n
++)
580 xlat
[n
] = (BYTE
)GetNearestPaletteIndex(hpal
,RGB(lpRgb
[n
].rgbRed
,lpRgb
[n
].rgbGreen
,lpRgb
[n
].rgbBlue
));
582 lpBits
= (LPBYTE
)wxDibPtr(lpbi
);
583 lpbi
->biClrUsed
= nPalColors
;
588 if (nPalColors
> nDibColors
)
590 GlobalReAllocPtr(lpbi
, lpbi
->biSize
+ nPalColors
*sizeof(RGBQUAD
) + SizeImage
, 0);
591 hmemmove((BYTE _huge
*)wxDibPtr(lpbi
), (BYTE _huge
*)lpBits
, SizeImage
);
592 lpBits
= (LPBYTE
)wxDibPtr(lpbi
);
594 else if (nPalColors
< nDibColors
)
596 hmemcpy(wxDibPtr(lpbi
), lpBits
, SizeImage
);
597 GlobalReAllocPtr(lpbi
, lpbi
->biSize
+ nPalColors
*sizeof(RGBQUAD
) + SizeImage
, 0);
598 lpBits
= (LPBYTE
)wxDibPtr(lpbi
);
602 // translate the DIB bits
604 switch (lpbi
->biCompression
)
607 xlatRle8(lpBits
, SizeImage
, xlat
);
611 xlatRle4(lpBits
, SizeImage
, xlat
);
615 if (lpbi
->biBitCount
== 8)
616 xlatClut8(lpBits
, SizeImage
, xlat
);
618 xlatClut4(lpBits
, SizeImage
, xlat
);
623 // Now copy the RGBs in the logical palette to the dib color table
625 for (n
=0; n
<nPalColors
; n
++)
627 GetPaletteEntries(hpal
,n
,1,&pe
);
629 lpRgb
[n
].rgbRed
= pe
.peRed
;
630 lpRgb
[n
].rgbGreen
= pe
.peGreen
;
631 lpRgb
[n
].rgbBlue
= pe
.peBlue
;
632 lpRgb
[n
].rgbReserved
= (BYTE
)0;
639 HPALETTE
wxMakePalette(const BITMAPINFO FAR
* Info
, UINT flags
)
642 const RGBQUAD FAR
* rgb
= Info
->bmiColors
;
644 WORD nColors
= (WORD
)Info
->bmiHeader
.biClrUsed
;
646 LOGPALETTE
* logPal
= (LOGPALETTE
*)
647 new BYTE
[sizeof(LOGPALETTE
) + (nColors
-1)*sizeof(PALETTEENTRY
)];
649 logPal
->palVersion
= 0x300; // Windows 3.0 version
650 logPal
->palNumEntries
= nColors
;
651 for (WORD n
= 0; n
< nColors
; n
++) {
652 logPal
->palPalEntry
[n
].peRed
= rgb
[n
].rgbRed
;
653 logPal
->palPalEntry
[n
].peGreen
= rgb
[n
].rgbGreen
;
654 logPal
->palPalEntry
[n
].peBlue
= rgb
[n
].rgbBlue
;
655 logPal
->palPalEntry
[n
].peFlags
= (BYTE
)flags
;
657 hPalette
= ::CreatePalette(logPal
);