Files
wxWidgets/src/msw/dibutils.cpp
Julian Smart 1cfa5d8e39 Some code tidying; removing dibutils.cpp which
doesn't seem to be used any more


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@19606 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
2003-03-18 15:08:21 +00:00

665 lines
16 KiB
C++

/////////////////////////////////////////////////////////////////////////////
// Name: dibutils.cpp
// Purpose: Utilities for DIBs
// Author: Julian Smart
// Modified by:
// Created: 04/01/98
// RCS-ID: $Id$
// Copyright: (c) Microsoft, Julian Smart
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#ifdef __GNUG__
#pragma implementation "dibutils.h"
#endif
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#ifndef WX_PRECOMP
#include "wx/setup.h"
#include "wx/defs.h"
#include "wx/string.h"
#endif
#include <windows.h>
#include <windowsx.h>
#include <stdio.h>
#include "wx/msw/dibutils.h"
#if defined(__WIN32__)
#if !defined(__MWERKS__) && !defined(__SALFORDC__)
#include <memory.h> // for _fmemcpy()
#endif
#define _huge
#ifndef hmemcpy
#define hmemcpy memcpy
#endif
#endif
#define BFT_ICON 0x4349 /* 'IC' */
#define BFT_BITMAP 0x4d42 /* 'BM' */
#define BFT_CURSOR 0x5450 /* 'PT(' */
#ifndef SEEK_CUR
/* flags for _lseek */
#define SEEK_CUR 1
#define SEEK_END 2
#define SEEK_SET 0
#endif
/* Copied from PNGhandler for coompilation with MingW32, RR */
#ifndef GlobalAllocPtr
#define GlobalPtrHandle(lp) \
((HGLOBAL)GlobalHandle(lp))
#define GlobalLockPtr(lp) \
((BOOL)GlobalLock(GlobalPtrHandle(lp)))
#define GlobalUnlockPtr(lp) \
GlobalUnlock(GlobalPtrHandle(lp))
#define GlobalAllocPtr(flags, cb) \
(GlobalLock(GlobalAlloc((flags), (cb))))
#define GlobalReAllocPtr(lp, cbNew, flags) \
(GlobalUnlockPtr(lp), GlobalLock(GlobalReAlloc(GlobalPtrHandle(lp) , (cbNew), (flags))))
#define GlobalFreePtr(lp) \
(GlobalUnlockPtr(lp), (BOOL)GlobalFree(GlobalPtrHandle(lp)))
#endif
/*
* Open a DIB file and return a MEMORY DIB, a memory handle containing..
*
* BITMAP INFO bi
* palette data
* bits....
*/
int wxDibWriteFile(LPTSTR szFile, LPBITMAPINFOHEADER lpbi)
{
HFILE fh;
OFSTRUCT of;
fh = OpenFile(wxConvFile.cWX2MB(szFile), &of, OF_WRITE | OF_CREATE);
if (!fh) {
return 0;
}
long size = wxDibSize(lpbi);
// write file header
BITMAPFILEHEADER bmf;
bmf.bfType = BFT_BITMAP;
bmf.bfSize = sizeof(bmf) + size;
bmf.bfReserved1 = 0;
bmf.bfReserved2 = 0;
bmf.bfOffBits = sizeof(bmf) + (char FAR*)(wxDibPtr(lpbi)) - (char FAR*)lpbi;
#if 1 // defined( __WATCOMC__) || defined(__VISUALC__) || defined(__SC__) || defined(__SALFORDC__) || defined(__MWERKS__) || wxUSE_NORLANDER_HEADERS
#define HWRITE_2ND_ARG_TYPE LPCSTR
#else // don't know who needs this...
#define HWRITE_2ND_ARG_TYPE LPBYTE
#endif
if ( _hwrite(fh, (HWRITE_2ND_ARG_TYPE)(&bmf), sizeof(bmf)) < 0 ||
_hwrite(fh, (HWRITE_2ND_ARG_TYPE)lpbi, size) < 0 )
{
_lclose(fh);
return 0;
}
#undef HWRITE_2ND_ARG_TYPE
_lclose(fh);
return 1;
}
PDIB wxDibOpenFile(LPTSTR szFile)
{
HFILE fh;
DWORD dwLen;
DWORD dwBits;
PDIB pdib;
LPVOID p;
OFSTRUCT of;
#if defined(__WIN32__)
#define GetCurrentInstance() GetModuleHandle(NULL)
#else
#define GetCurrentInstance() (HINSTANCE)SELECTOROF((LPVOID)&of)
#endif
fh = OpenFile(wxConvFile.cWX2MB(szFile), &of, OF_READ);
if (fh == -1)
{
HRSRC h;
// TODO: Unicode version
#ifdef __WIN16__
h = FindResource(GetCurrentInstance(), szFile, RT_BITMAP);
#elif wxUSE_UNICODE
h = FindResourceW(GetCurrentInstance(), szFile, RT_BITMAP);
#else
h = FindResourceA(GetCurrentInstance(), szFile, RT_BITMAP);
#endif
#if defined(__WIN32__)
//!!! can we call GlobalFree() on this? is it the right format.
//!!! can we write to this resource?
if (h)
return (PDIB)LockResource(LoadResource(GetCurrentInstance(), h));
#else
if (h)
fh = AccessResource(GetCurrentInstance(), h);
#endif
}
if (fh == -1)
return NULL;
pdib = wxDibReadBitmapInfo(fh);
if (!pdib)
return NULL;
/* How much memory do we need to hold the DIB */
dwBits = pdib->biSizeImage;
dwLen = pdib->biSize + wxDibPaletteSize(pdib) + dwBits;
/* Can we get more memory? */
p = GlobalReAllocPtr(pdib,dwLen,0);
if (!p)
{
GlobalFreePtr(pdib);
pdib = NULL;
}
else
{
pdib = (PDIB)p;
}
if (pdib)
{
/* read in the bits */
_hread(fh, (LPBYTE)pdib + (UINT)pdib->biSize + wxDibPaletteSize(pdib), dwBits);
}
_lclose(fh);
return pdib;
}
/*
* ReadDibBitmapInfo()
*
* Will read a file in DIB format and return a global HANDLE to its
* BITMAPINFO. This function will work with both "old" and "new"
* bitmap formats, but will always return a "new" BITMAPINFO.
*/
PDIB wxDibReadBitmapInfo(HFILE fh)
{
DWORD off;
int size;
int i;
int nNumColors;
RGBQUAD FAR *pRgb;
BITMAPINFOHEADER bi;
BITMAPCOREHEADER bc;
BITMAPFILEHEADER bf;
PDIB pdib;
if (fh == -1)
return NULL;
off = _llseek(fh,0L,SEEK_CUR);
if (sizeof(bf) != _lread(fh,(LPSTR)&bf,sizeof(bf)))
return NULL;
/*
* do we have a RC HEADER?
*/
if (bf.bfType != BFT_BITMAP)
{
bf.bfOffBits = 0L;
_llseek(fh,off,SEEK_SET);
}
if (sizeof(bi) != _lread(fh,(LPSTR)&bi,sizeof(bi)))
return NULL;
/*
* what type of bitmap info is this?
*/
switch (size = (int)bi.biSize)
{
default:
case sizeof(BITMAPINFOHEADER):
break;
case sizeof(BITMAPCOREHEADER):
bc = *(BITMAPCOREHEADER*)&bi;
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = (DWORD)bc.bcWidth;
bi.biHeight = (DWORD)bc.bcHeight;
bi.biPlanes = (WORD)bc.bcPlanes;
bi.biBitCount = (WORD)bc.bcBitCount;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
_llseek(fh,(LONG)sizeof(BITMAPCOREHEADER)-sizeof(BITMAPINFOHEADER),SEEK_CUR);
break;
}
nNumColors = wxDibNumColors(&bi);
#if 0
if (bi.biSizeImage == 0)
bi.biSizeImage = DibSizeImage(&bi);
if (bi.biClrUsed == 0)
bi.biClrUsed = wxDibNumColors(&bi);
#else
wxFixBitmapInfo(&bi);
#endif
pdib = (PDIB)GlobalAllocPtr(GMEM_MOVEABLE,(LONG)bi.biSize + nNumColors * sizeof(RGBQUAD));
if (!pdib)
return NULL;
*pdib = bi;
pRgb = wxDibColors(pdib);
if (nNumColors)
{
if (size == sizeof(BITMAPCOREHEADER))
{
/*
* convert a old color table (3 byte entries) to a new
* color table (4 byte entries)
*/
_lread(fh,(LPVOID)pRgb,nNumColors * sizeof(RGBTRIPLE));
for (i=nNumColors-1; i>=0; i--)
{
RGBQUAD rgb;
rgb.rgbRed = ((RGBTRIPLE FAR *)pRgb)[i].rgbtRed;
rgb.rgbBlue = ((RGBTRIPLE FAR *)pRgb)[i].rgbtBlue;
rgb.rgbGreen = ((RGBTRIPLE FAR *)pRgb)[i].rgbtGreen;
rgb.rgbReserved = (BYTE)0;
pRgb[i] = rgb;
}
}
else
{
_lread(fh,(LPVOID)pRgb,nNumColors * sizeof(RGBQUAD));
}
}
if (bf.bfOffBits != 0L)
_llseek(fh,off + bf.bfOffBits,SEEK_SET);
return pdib;
}
/*
* DibSetUsage(hdib,hpal,wUsage)
*
* Modifies the color table of the passed DIB for use with the wUsage
* parameter specifed.
*
* if wUsage is DIB_PAL_COLORS the DIB color table is set to 0-256
* if wUsage is DIB_RGB_COLORS the DIB color table is set to the RGB values
* in the passed palette
*/
BOOL wxDibSetUsage(PDIB pdib, HPALETTE hpal,UINT wUsage)
{
PALETTEENTRY ape[256];
RGBQUAD FAR * pRgb;
WORD FAR * pw;
int nColors;
int n;
if (hpal == NULL)
hpal = (HPALETTE)GetStockObject(DEFAULT_PALETTE);
if (!pdib)
return FALSE;
nColors = wxDibNumColors(pdib);
if (nColors == 3 && wxDibCompression(pdib) == BI_BITFIELDS)
nColors = 0;
if (nColors > 0)
{
pRgb = wxDibColors(pdib);
switch (wUsage)
{
//
// Set the DIB color table to palette indexes
//
case DIB_PAL_COLORS:
for (pw = (WORD FAR*)pRgb,n=0; n<nColors; n++,pw++)
*pw = n;
break;
//
// Set the DIB color table to RGBQUADS
//
default:
case DIB_RGB_COLORS:
nColors = (nColors < 256) ? nColors: 256;
GetPaletteEntries(hpal,0,nColors,ape);
for (n=0; n<nColors; n++)
{
pRgb[n].rgbRed = ape[n].peRed;
pRgb[n].rgbGreen = ape[n].peGreen;
pRgb[n].rgbBlue = ape[n].peBlue;
pRgb[n].rgbReserved = 0;
}
break;
}
}
return TRUE;
}
/*
* DibCreate(bits, dx, dy)
*
* Creates a new packed DIB with the given dimensions and the
* given number of bits per pixel
*/
PDIB wxDibCreate(int bits, int dx, int dy)
{
LPBITMAPINFOHEADER lpbi ;
DWORD dwSizeImage;
int i;
DWORD FAR *pdw;
dwSizeImage = dy*(DWORD)((dx*bits/8+3)&~3);
lpbi = (PDIB)GlobalAllocPtr(GHND,sizeof(BITMAPINFOHEADER)+dwSizeImage + 1024);
if (lpbi == NULL)
return NULL;
lpbi->biSize = sizeof(BITMAPINFOHEADER) ;
lpbi->biWidth = dx;
lpbi->biHeight = dy;
lpbi->biPlanes = 1;
lpbi->biBitCount = bits ;
lpbi->biCompression = BI_RGB ;
lpbi->biSizeImage = dwSizeImage;
lpbi->biXPelsPerMeter = 0 ;
lpbi->biYPelsPerMeter = 0 ;
lpbi->biClrUsed = 0 ;
lpbi->biClrImportant = 0 ;
if (bits == 4)
lpbi->biClrUsed = 16;
else if (bits == 8)
lpbi->biClrUsed = 256;
pdw = (DWORD FAR *)((LPBYTE)lpbi+(int)lpbi->biSize);
for (i=0; i<(int)lpbi->biClrUsed/16; i++)
{
*pdw++ = 0x00000000; // 0000 black
*pdw++ = 0x00800000; // 0001 dark red
*pdw++ = 0x00008000; // 0010 dark green
*pdw++ = 0x00808000; // 0011 mustard
*pdw++ = 0x00000080; // 0100 dark blue
*pdw++ = 0x00800080; // 0101 purple
*pdw++ = 0x00008080; // 0110 dark turquoise
*pdw++ = 0x00C0C0C0; // 1000 gray
*pdw++ = 0x00808080; // 0111 dark gray
*pdw++ = 0x00FF0000; // 1001 red
*pdw++ = 0x0000FF00; // 1010 green
*pdw++ = 0x00FFFF00; // 1011 yellow
*pdw++ = 0x000000FF; // 1100 blue
*pdw++ = 0x00FF00FF; // 1101 pink (magenta)
*pdw++ = 0x0000FFFF; // 1110 cyan
*pdw++ = 0x00FFFFFF; // 1111 white
}
return (PDIB)lpbi;
}
static void xlatClut8(BYTE FAR *pb, DWORD dwSize, BYTE FAR *xlat)
{
DWORD dw;
#ifdef __cplusplus
for (dw = 0; dw < dwSize; dw++, ((BYTE _huge *&)pb)++)
#else
for (dw = 0; dw < dwSize; dw++, ((BYTE _huge *)pb)++)
#endif
*pb = xlat[*pb];
}
static void xlatClut4(BYTE FAR *pb, DWORD dwSize, BYTE FAR *xlat)
{
DWORD dw;
#ifdef __cplusplus
for (dw = 0; dw < dwSize; dw++, ((BYTE _huge *&)pb)++)
#else
for (dw = 0; dw < dwSize; dw++, ((BYTE _huge *)pb)++)
#endif
*pb = (BYTE)(xlat[*pb & 0x0F] | (xlat[(*pb >> 4) & 0x0F] << 4));
}
#define RLE_ESCAPE 0
#define RLE_EOL 0
#define RLE_EOF 1
#define RLE_JMP 2
static void xlatRle8(BYTE FAR *pb, DWORD WXUNUSED(dwSize), BYTE FAR *xlat)
{
BYTE cnt;
BYTE b;
BYTE _huge *prle = pb;
for(;;)
{
cnt = *prle++;
b = *prle;
if (cnt == RLE_ESCAPE)
{
prle++;
switch (b)
{
case RLE_EOF:
return;
case RLE_EOL:
break;
case RLE_JMP:
prle++; // skip dX
prle++; // skip dY
break;
default:
cnt = b;
for (b=0; b<cnt; b++,prle++)
*prle = xlat[*prle];
if (cnt & 1)
prle++;
break;
}
}
else
{
*prle++ = xlat[b];
}
}
}
static void xlatRle4(BYTE FAR *WXUNUSED(pb), DWORD WXUNUSED(dwSize), BYTE FAR *WXUNUSED(xlat))
{
}
static void hmemmove(BYTE _huge *d, BYTE _huge *s, LONG len)
{
d += len-1;
s += len-1;
while (len--)
*d-- = *s--;
}
/*
* DibMapToPalette(pdib, hpal)
*
* Map the colors of the DIB, using GetNearestPaletteIndex, to
* the colors of the given palette.
*/
BOOL wxDibMapToPalette(PDIB pdib, HPALETTE hpal)
{
LPBITMAPINFOHEADER lpbi;
PALETTEENTRY pe;
int n;
int nDibColors;
int nPalColors=0;
BYTE FAR * lpBits;
RGBQUAD FAR * lpRgb;
BYTE xlat[256];
DWORD SizeImage;
if (!hpal || !pdib)
return FALSE;
lpbi = (LPBITMAPINFOHEADER)pdib;
lpRgb = wxDibColors(pdib);
GetObject(hpal,sizeof(int),(LPSTR)&nPalColors);
nDibColors = wxDibNumColors(pdib);
if ((SizeImage = lpbi->biSizeImage) == 0)
SizeImage = wxDibSizeImage(lpbi);
//
// build a xlat table. from the current DIB colors to the given
// palette.
//
for (n=0; n<nDibColors; n++)
xlat[n] = (BYTE)GetNearestPaletteIndex(hpal,RGB(lpRgb[n].rgbRed,lpRgb[n].rgbGreen,lpRgb[n].rgbBlue));
lpBits = (LPBYTE)wxDibPtr(lpbi);
lpbi->biClrUsed = nPalColors;
//
// re-size the DIB
//
if (nPalColors > nDibColors)
{
GlobalReAllocPtr(lpbi, lpbi->biSize + nPalColors*sizeof(RGBQUAD) + SizeImage, 0);
hmemmove((BYTE _huge *)wxDibPtr(lpbi), (BYTE _huge *)lpBits, SizeImage);
lpBits = (LPBYTE)wxDibPtr(lpbi);
}
else if (nPalColors < nDibColors)
{
hmemcpy(wxDibPtr(lpbi), lpBits, SizeImage);
GlobalReAllocPtr(lpbi, lpbi->biSize + nPalColors*sizeof(RGBQUAD) + SizeImage, 0);
lpBits = (LPBYTE)wxDibPtr(lpbi);
}
//
// translate the DIB bits
//
switch (lpbi->biCompression)
{
case BI_RLE8:
xlatRle8(lpBits, SizeImage, xlat);
break;
case BI_RLE4:
xlatRle4(lpBits, SizeImage, xlat);
break;
case BI_RGB:
if (lpbi->biBitCount == 8)
xlatClut8(lpBits, SizeImage, xlat);
else
xlatClut4(lpBits, SizeImage, xlat);
break;
}
//
// Now copy the RGBs in the logical palette to the dib color table
//
for (n=0; n<nPalColors; n++)
{
GetPaletteEntries(hpal,n,1,&pe);
lpRgb[n].rgbRed = pe.peRed;
lpRgb[n].rgbGreen = pe.peGreen;
lpRgb[n].rgbBlue = pe.peBlue;
lpRgb[n].rgbReserved = (BYTE)0;
}
return TRUE;
}
HPALETTE wxMakePalette(const BITMAPINFO FAR* Info, UINT flags)
{
HPALETTE hPalette;
const RGBQUAD FAR* rgb = Info->bmiColors;
WORD nColors = (WORD)Info->bmiHeader.biClrUsed;
if (nColors) {
LOGPALETTE* logPal = (LOGPALETTE*)
new BYTE[sizeof(LOGPALETTE) + (nColors-1)*sizeof(PALETTEENTRY)];
logPal->palVersion = 0x300; // Windows 3.0 version
logPal->palNumEntries = nColors;
for (WORD n = 0; n < nColors; n++) {
logPal->palPalEntry[n].peRed = rgb[n].rgbRed;
logPal->palPalEntry[n].peGreen = rgb[n].rgbGreen;
logPal->palPalEntry[n].peBlue = rgb[n].rgbBlue;
logPal->palPalEntry[n].peFlags = (BYTE)flags;
}
hPalette = ::CreatePalette(logPal);
delete logPal;
} else
hPalette = 0;
return hPalette;
}