]>
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 and Markus Holzem
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "dibutils.h"
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
33 #include "wx/msw/dibutils.h"
39 #if defined(__WIN32__)
40 #if !defined(__MWERKS__) && !defined(__SALFORDC__)
41 #include <memory.h> // for _fmemcpy()
45 #define hmemcpy memcpy
49 #define BFT_ICON 0x4349 /* 'IC' */
50 #define BFT_BITMAP 0x4d42 /* 'BM' */
51 #define BFT_CURSOR 0x5450 /* 'PT' */
53 /* flags for _lseek */
60 * Clear the System Palette so that we can ensure an identity palette
61 * mapping for fast performance.
64 void ClearSystemPalette(void)
66 //*** A dummy palette setup
71 PALETTEENTRY aEntries
[256];
78 HPALETTE ScreenPalette
= 0;
85 // *** Reset everything in the system palette to black
86 for(Counter
= 0; Counter
< 256; Counter
++)
88 Palette
.aEntries
[Counter
].peRed
= 0;
89 Palette
.aEntries
[Counter
].peGreen
= 0;
90 Palette
.aEntries
[Counter
].peBlue
= 0;
91 Palette
.aEntries
[Counter
].peFlags
= PC_NOCOLLAPSE
;
94 // *** Create, select, realize, deselect, and delete the palette
96 ScreenDC
= GetDC((HWND
)NULL
);
98 ScreenDC
= GetDC(NULL
);
100 ScreenPalette
= CreatePalette((LOGPALETTE
*)&Palette
);
104 ScreenPalette
= SelectPalette(ScreenDC
,ScreenPalette
,FALSE
);
105 nMapped
= RealizePalette(ScreenDC
);
106 ScreenPalette
= SelectPalette(ScreenDC
,ScreenPalette
,FALSE
);
107 bOK
= DeleteObject(ScreenPalette
);
111 nOK
= ReleaseDC((HWND
)NULL
, ScreenDC
);
113 nOK
= ReleaseDC(NULL
, ScreenDC
);
121 * Open a DIB file and return a MEMORY DIB, a memory handle containing..
128 int DibWriteFile(LPTSTR szFile
, LPBITMAPINFOHEADER lpbi
)
133 fh
= OpenFile(wxConvFile
.cWX2MB(szFile
), &of
, OF_WRITE
| OF_CREATE
);
136 // printf("la regamos0");
140 long size
= DibSize(lpbi
);
143 BITMAPFILEHEADER bmf
;
145 bmf
.bfSize
= sizeof(bmf
) + size
;
148 bmf
.bfOffBits
= sizeof(bmf
) + (char far
*)(DibPtr(lpbi
)) - (char far
*)lpbi
;
149 #if defined( __WATCOMC__) || defined(__VISUALC__) || defined(__SC__) || defined(__SALFORDC__) || defined(__MWERKS__)
150 if (_hwrite(fh
, (LPCSTR
)(&bmf
), sizeof(bmf
))<0 ||
151 _hwrite(fh
, (LPCSTR
)lpbi
, size
)<0) {
153 // printf("la regamos1");
157 if (_hwrite(fh
, (LPBYTE
)(&bmf
), sizeof(bmf
))<0 ||
158 _hwrite(fh
, (LPBYTE
)lpbi
, size
)<0) {
160 // printf("la regamos1");
169 PDIB
DibOpenFile(LPTSTR szFile
)
178 #if defined(WIN32) || defined(_WIN32)
179 #define GetCurrentInstance() GetModuleHandle(NULL)
181 #define GetCurrentInstance() (HINSTANCE)SELECTOROF((LPVOID)&of)
184 fh
= OpenFile(wxConvFile
.cWX2MB(szFile
), &of
, OF_READ
);
190 // TODO: Unicode version
192 h
= FindResource(GetCurrentInstance(), szFile
, RT_BITMAP
);
194 h
= FindResourceW(GetCurrentInstance(), szFile
, RT_BITMAP
);
196 h
= FindResourceA(GetCurrentInstance(), szFile
, RT_BITMAP
);
199 #if defined(__WIN32__)
200 //!!! can we call GlobalFree() on this? is it the right format.
201 //!!! can we write to this resource?
203 return (PDIB
)LockResource(LoadResource(GetCurrentInstance(), h
));
206 fh
= AccessResource(GetCurrentInstance(), h
);
213 pdib
= DibReadBitmapInfo(fh
);
218 /* How much memory do we need to hold the DIB */
220 dwBits
= pdib
->biSizeImage
;
221 dwLen
= pdib
->biSize
+ DibPaletteSize(pdib
) + dwBits
;
223 /* Can we get more memory? */
225 p
= GlobalReAllocPtr(pdib
,dwLen
,0);
239 /* read in the bits */
240 _hread(fh
, (LPBYTE
)pdib
+ (UINT
)pdib
->biSize
+ DibPaletteSize(pdib
), dwBits
);
250 * ReadDibBitmapInfo()
252 * Will read a file in DIB format and return a global HANDLE to its
253 * BITMAPINFO. This function will work with both "old" and "new"
254 * bitmap formats, but will always return a "new" BITMAPINFO.
257 PDIB
DibReadBitmapInfo(HFILE fh
)
273 off
= _llseek(fh
,0L,SEEK_CUR
);
275 if (sizeof(bf
) != _lread(fh
,(LPSTR
)&bf
,sizeof(bf
)))
279 * do we have a RC HEADER?
281 if (bf
.bfType
!= BFT_BITMAP
)
284 _llseek(fh
,off
,SEEK_SET
);
287 if (sizeof(bi
) != _lread(fh
,(LPSTR
)&bi
,sizeof(bi
)))
291 * what type of bitmap info is this?
293 switch (size
= (int)bi
.biSize
)
296 case sizeof(BITMAPINFOHEADER
):
299 case sizeof(BITMAPCOREHEADER
):
300 bc
= *(BITMAPCOREHEADER
*)&bi
;
301 bi
.biSize
= sizeof(BITMAPINFOHEADER
);
302 bi
.biWidth
= (DWORD
)bc
.bcWidth
;
303 bi
.biHeight
= (DWORD
)bc
.bcHeight
;
304 bi
.biPlanes
= (UINT
)bc
.bcPlanes
;
305 bi
.biBitCount
= (UINT
)bc
.bcBitCount
;
306 bi
.biCompression
= BI_RGB
;
308 bi
.biXPelsPerMeter
= 0;
309 bi
.biYPelsPerMeter
= 0;
311 bi
.biClrImportant
= 0;
313 _llseek(fh
,(LONG
)sizeof(BITMAPCOREHEADER
)-sizeof(BITMAPINFOHEADER
),SEEK_CUR
);
318 nNumColors
= DibNumColors(&bi
);
321 if (bi
.biSizeImage
== 0)
322 bi
.biSizeImage
= DibSizeImage(&bi
);
324 if (bi
.biClrUsed
== 0)
325 bi
.biClrUsed
= DibNumColors(&bi
);
330 pdib
= (PDIB
)GlobalAllocPtr(GMEM_MOVEABLE
,(LONG
)bi
.biSize
+ nNumColors
* sizeof(RGBQUAD
));
337 pRgb
= DibColors(pdib
);
341 if (size
== sizeof(BITMAPCOREHEADER
))
344 * convert a old color table (3 byte entries) to a new
345 * color table (4 byte entries)
347 _lread(fh
,(LPVOID
)pRgb
,nNumColors
* sizeof(RGBTRIPLE
));
349 for (i
=nNumColors
-1; i
>=0; i
--)
353 rgb
.rgbRed
= ((RGBTRIPLE FAR
*)pRgb
)[i
].rgbtRed
;
354 rgb
.rgbBlue
= ((RGBTRIPLE FAR
*)pRgb
)[i
].rgbtBlue
;
355 rgb
.rgbGreen
= ((RGBTRIPLE FAR
*)pRgb
)[i
].rgbtGreen
;
356 rgb
.rgbReserved
= (BYTE
)0;
363 _lread(fh
,(LPVOID
)pRgb
,nNumColors
* sizeof(RGBQUAD
));
367 if (bf
.bfOffBits
!= 0L)
368 _llseek(fh
,off
+ bf
.bfOffBits
,SEEK_SET
);
374 * DibSetUsage(hdib,hpal,wUsage)
376 * Modifies the color table of the passed DIB for use with the wUsage
377 * parameter specifed.
379 * if wUsage is DIB_PAL_COLORS the DIB color table is set to 0-256
380 * if wUsage is DIB_RGB_COLORS the DIB color table is set to the RGB values
381 * in the passed palette
384 BOOL
DibSetUsage(PDIB pdib
, HPALETTE hpal
,UINT wUsage
)
386 PALETTEENTRY ape
[256];
393 hpal
= (HPALETTE
)GetStockObject(DEFAULT_PALETTE
);
398 nColors
= DibNumColors(pdib
);
400 if (nColors
== 3 && DibCompression(pdib
) == BI_BITFIELDS
)
405 pRgb
= DibColors(pdib
);
410 // Set the DIB color table to palette indexes
413 for (pw
= (WORD FAR
*)pRgb
,n
=0; n
<nColors
; n
++,pw
++)
418 // Set the DIB color table to RGBQUADS
422 nColors
= (nColors
< 256) ? nColors
: 256;
424 GetPaletteEntries(hpal
,0,nColors
,ape
);
426 for (n
=0; n
<nColors
; n
++)
428 pRgb
[n
].rgbRed
= ape
[n
].peRed
;
429 pRgb
[n
].rgbGreen
= ape
[n
].peGreen
;
430 pRgb
[n
].rgbBlue
= ape
[n
].peBlue
;
431 pRgb
[n
].rgbReserved
= 0;
440 * DibCreate(bits, dx, dy)
442 * Creates a new packed DIB with the given dimensions and the
443 * given number of bits per pixel
446 PDIB
DibCreate(int bits
, int dx
, int dy
)
448 LPBITMAPINFOHEADER lpbi
;
453 dwSizeImage
= dy
*(DWORD
)((dx
*bits
/8+3)&~3);
455 lpbi
= (PDIB
)GlobalAllocPtr(GHND
,sizeof(BITMAPINFOHEADER
)+dwSizeImage
+ 1024);
460 lpbi
->biSize
= sizeof(BITMAPINFOHEADER
) ;
464 lpbi
->biBitCount
= bits
;
465 lpbi
->biCompression
= BI_RGB
;
466 lpbi
->biSizeImage
= dwSizeImage
;
467 lpbi
->biXPelsPerMeter
= 0 ;
468 lpbi
->biYPelsPerMeter
= 0 ;
469 lpbi
->biClrUsed
= 0 ;
470 lpbi
->biClrImportant
= 0 ;
473 lpbi
->biClrUsed
= 16;
476 lpbi
->biClrUsed
= 256;
478 pdw
= (DWORD FAR
*)((LPBYTE
)lpbi
+(int)lpbi
->biSize
);
480 for (i
=0; i
<(int)lpbi
->biClrUsed
/16; i
++)
482 *pdw
++ = 0x00000000; // 0000 black
483 *pdw
++ = 0x00800000; // 0001 dark red
484 *pdw
++ = 0x00008000; // 0010 dark green
485 *pdw
++ = 0x00808000; // 0011 mustard
486 *pdw
++ = 0x00000080; // 0100 dark blue
487 *pdw
++ = 0x00800080; // 0101 purple
488 *pdw
++ = 0x00008080; // 0110 dark turquoise
489 *pdw
++ = 0x00C0C0C0; // 1000 gray
490 *pdw
++ = 0x00808080; // 0111 dark gray
491 *pdw
++ = 0x00FF0000; // 1001 red
492 *pdw
++ = 0x0000FF00; // 1010 green
493 *pdw
++ = 0x00FFFF00; // 1011 yellow
494 *pdw
++ = 0x000000FF; // 1100 blue
495 *pdw
++ = 0x00FF00FF; // 1101 pink (magenta)
496 *pdw
++ = 0x0000FFFF; // 1110 cyan
497 *pdw
++ = 0x00FFFFFF; // 1111 white
503 static void xlatClut8(BYTE FAR
*pb
, DWORD dwSize
, BYTE FAR
*xlat
)
508 for (dw
= 0; dw
< dwSize
; dw
++, ((BYTE _huge
*&)pb
)++)
510 for (dw
= 0; dw
< dwSize
; dw
++, ((BYTE _huge
*)pb
)++)
515 static void xlatClut4(BYTE FAR
*pb
, DWORD dwSize
, BYTE FAR
*xlat
)
520 for (dw
= 0; dw
< dwSize
; dw
++, ((BYTE _huge
*&)pb
)++)
522 for (dw
= 0; dw
< dwSize
; dw
++, ((BYTE _huge
*)pb
)++)
524 *pb
= (BYTE
)(xlat
[*pb
& 0x0F] | (xlat
[(*pb
>> 4) & 0x0F] << 4));
532 static void xlatRle8(BYTE FAR
*pb
, DWORD dwSize
, BYTE FAR
*xlat
)
536 BYTE _huge
*prle
= pb
;
543 if (cnt
== RLE_ESCAPE
)
562 for (b
=0; b
<cnt
; b
++,prle
++)
578 static void xlatRle4(BYTE FAR
*pb
, DWORD dwSize
, BYTE FAR
*xlat
)
582 static void hmemmove(BYTE _huge
*d
, BYTE _huge
*s
, LONG len
)
592 * DibMapToPalette(pdib, hpal)
594 * Map the colors of the DIB, using GetNearestPaletteIndex, to
595 * the colors of the given palette.
598 BOOL
DibMapToPalette(PDIB pdib
, HPALETTE hpal
)
600 LPBITMAPINFOHEADER lpbi
;
613 lpbi
= (LPBITMAPINFOHEADER
)pdib
;
614 lpRgb
= DibColors(pdib
);
616 GetObject(hpal
,sizeof(int),(LPSTR
)&nPalColors
);
617 nDibColors
= DibNumColors(pdib
);
619 if ((SizeImage
= lpbi
->biSizeImage
) == 0)
620 SizeImage
= DibSizeImage(lpbi
);
623 // build a xlat table. from the current DIB colors to the given
626 for (n
=0; n
<nDibColors
; n
++)
627 xlat
[n
] = (BYTE
)GetNearestPaletteIndex(hpal
,RGB(lpRgb
[n
].rgbRed
,lpRgb
[n
].rgbGreen
,lpRgb
[n
].rgbBlue
));
629 lpBits
= (LPBYTE
)DibPtr(lpbi
);
630 lpbi
->biClrUsed
= nPalColors
;
635 if (nPalColors
> nDibColors
)
637 GlobalReAllocPtr(lpbi
, lpbi
->biSize
+ nPalColors
*sizeof(RGBQUAD
) + SizeImage
, 0);
638 hmemmove((BYTE _huge
*)DibPtr(lpbi
), (BYTE _huge
*)lpBits
, SizeImage
);
639 lpBits
= (LPBYTE
)DibPtr(lpbi
);
641 else if (nPalColors
< nDibColors
)
643 hmemcpy(DibPtr(lpbi
), lpBits
, SizeImage
);
644 GlobalReAllocPtr(lpbi
, lpbi
->biSize
+ nPalColors
*sizeof(RGBQUAD
) + SizeImage
, 0);
645 lpBits
= (LPBYTE
)DibPtr(lpbi
);
649 // translate the DIB bits
651 switch (lpbi
->biCompression
)
654 xlatRle8(lpBits
, SizeImage
, xlat
);
658 xlatRle4(lpBits
, SizeImage
, xlat
);
662 if (lpbi
->biBitCount
== 8)
663 xlatClut8(lpBits
, SizeImage
, xlat
);
665 xlatClut4(lpBits
, SizeImage
, xlat
);
670 // Now copy the RGBs in the logical palette to the dib color table
672 for (n
=0; n
<nPalColors
; n
++)
674 GetPaletteEntries(hpal
,n
,1,&pe
);
676 lpRgb
[n
].rgbRed
= pe
.peRed
;
677 lpRgb
[n
].rgbGreen
= pe
.peGreen
;
678 lpRgb
[n
].rgbBlue
= pe
.peBlue
;
679 lpRgb
[n
].rgbReserved
= (BYTE
)0;
686 HPALETTE
MakePalette(const BITMAPINFO FAR
* Info
, UINT flags
)
689 const RGBQUAD far
* rgb
= Info
->bmiColors
;
691 WORD nColors
= Info
->bmiHeader
.biClrUsed
;
693 LOGPALETTE
* logPal
= (LOGPALETTE
*)
694 new BYTE
[sizeof(LOGPALETTE
) + (nColors
-1)*sizeof(PALETTEENTRY
)];
696 logPal
->palVersion
= 0x300; // Windows 3.0 version
697 logPal
->palNumEntries
= nColors
;
698 for (short n
= 0; n
< nColors
; n
++) {
699 logPal
->palPalEntry
[n
].peRed
= rgb
[n
].rgbRed
;
700 logPal
->palPalEntry
[n
].peGreen
= rgb
[n
].rgbGreen
;
701 logPal
->palPalEntry
[n
].peBlue
= rgb
[n
].rgbBlue
;
702 logPal
->palPalEntry
[n
].peFlags
= (BYTE
)flags
;
704 hPalette
= ::CreatePalette(logPal
);