252 lines
8.3 KiB
C++
252 lines
8.3 KiB
C++
#include <mdiwin/bitmap.hpp>
|
||
|
||
#define MaxBlock 64000L
|
||
|
||
Bitmap::Bitmap(void)
|
||
: mhFile(HFILE_ERROR), mMaxColors(0), mhPalette(0), mhGlobalImage(0),
|
||
mhGlobalBitmapInfo(0), mCurrentMode(Idle), mSizeImage(0),
|
||
mBlockSize(MaxBlock)
|
||
{
|
||
}
|
||
|
||
Bitmap::Bitmap(String pathFileName)
|
||
: mhFile(HFILE_ERROR), mMaxColors(0), mhPalette(0), mhGlobalImage(0),
|
||
mhGlobalBitmapInfo(0), mCurrentMode(Read), mSizeImage(0),
|
||
mBlockSize(MaxBlock)
|
||
{
|
||
processBitmap(pathFileName);
|
||
}
|
||
|
||
Bitmap::Bitmap(String pathFileName,HGLOBAL hGlobalImage,HGLOBAL hGlobalBitmapInfo)
|
||
: mhFile(HFILE_ERROR), mMaxColors(0), mhPalette(0), mhGlobalImage(0),
|
||
mhGlobalBitmapInfo(0), mCurrentMode(Write), mSizeImage(0),
|
||
mBlockSize(MaxBlock)
|
||
{
|
||
DWORD sizeBitmapInfo;
|
||
BITMAPINFO FAR *lpSourceBitmapInfo;
|
||
OFSTRUCT ofStruct;
|
||
UHUGE *lpSourceImage;
|
||
|
||
if(!hGlobalImage||!hGlobalBitmapInfo)return;
|
||
mFileName=pathFileName;
|
||
if(HFILE_ERROR==(mhFile=::OpenFile(pathFileName,&ofStruct,OF_WRITE|OF_CREATE)))return;
|
||
#if defined(__FLAT__)
|
||
sizeBitmapInfo=::GlobalSize(hGlobalBitmapInfo);
|
||
#else
|
||
sizeBitmapInfo=::GetSelectorLimit((UINT)hGlobalBitmapInfo)+1;
|
||
#endif
|
||
mhGlobalBitmapInfo=::GlobalAlloc(GMEM_FIXED,sizeBitmapInfo);
|
||
mpBitmapInfo=(BITMAPINFO FAR *)::GlobalLock(mhGlobalBitmapInfo);
|
||
lpSourceBitmapInfo=(BITMAPINFO FAR *)::GlobalLock(hGlobalBitmapInfo);
|
||
copyBits((UHUGE *)mpBitmapInfo,(UHUGE *)lpSourceBitmapInfo,sizeBitmapInfo);
|
||
::GlobalUnlock(hGlobalBitmapInfo);
|
||
mSizeImage=((((mpBitmapInfo->bmiHeader.biWidth*
|
||
mpBitmapInfo->bmiHeader.biBitCount)+31)&~31)>>3)*
|
||
mpBitmapInfo->bmiHeader.biHeight;
|
||
mhGlobalImage=::GlobalAlloc(GMEM_FIXED,mSizeImage);
|
||
mpImage=(UHUGE *)::GlobalLock(mhGlobalImage);
|
||
lpSourceImage=(UHUGE *)::GlobalLock(hGlobalImage);
|
||
copyBits(mpImage,lpSourceImage,mSizeImage);
|
||
::GlobalUnlock(hGlobalImage);
|
||
if(!(mMaxColors=(WORD)mpBitmapInfo->bmiHeader.biClrUsed))
|
||
mMaxColors=1 << mpBitmapInfo->bmiHeader.biBitCount;
|
||
}
|
||
|
||
Bitmap::~Bitmap()
|
||
{
|
||
cleanup();
|
||
}
|
||
|
||
WORD Bitmap::operator=(String pathFileName)
|
||
{
|
||
int returnCode;
|
||
|
||
cleanup();
|
||
mCurrentMode=Read;
|
||
returnCode=processBitmap(pathFileName);
|
||
::_lclose(mhFile);
|
||
mhFile=HFILE_ERROR;
|
||
return returnCode;
|
||
}
|
||
|
||
WORD Bitmap::processBitmap(String pathFileName)
|
||
{
|
||
OFSTRUCT ofStruct;
|
||
|
||
mFileName=pathFileName;
|
||
if(HFILE_ERROR==(mhFile=::OpenFile(pathFileName,&ofStruct,OF_READ)))return FALSE;
|
||
::_lread(mhFile,&mBitmapFileHeader,sizeof(BITMAPFILEHEADER));
|
||
if(Signature!=mBitmapFileHeader.bfType)
|
||
{
|
||
cleanup();
|
||
return FALSE;
|
||
}
|
||
createPalette();
|
||
decodeImage();
|
||
return TRUE;
|
||
}
|
||
|
||
WORD Bitmap::isValidBitmap(String pathFileName)const
|
||
{
|
||
HFILE hFile;
|
||
OFSTRUCT ofStruct;
|
||
BITMAPFILEHEADER bitmapFileHeader;
|
||
|
||
if(pathFileName.isNull())return FALSE;
|
||
if(HFILE_ERROR==(hFile=::OpenFile(pathFileName,&ofStruct,OF_READ)))return FALSE;
|
||
::_lread(hFile,&bitmapFileHeader,sizeof(BITMAPFILEHEADER));
|
||
::_lclose(hFile);
|
||
if(Signature!=bitmapFileHeader.bfType)return FALSE;
|
||
return TRUE;
|
||
}
|
||
|
||
WORD Bitmap::setPalette(HPALETTE hPalette)
|
||
{
|
||
PALETTEENTRY FAR *lpPaletteEntry;
|
||
BITMAPINFOHEADER bitmapInfoHeader;
|
||
|
||
if(!isOkay()||!hPalette)return FALSE;
|
||
lpPaletteEntry=new PALETTEENTRY[MaxColors];
|
||
mMaxColors=::GetPaletteEntries(hPalette,0,MaxColors,(PALETTEENTRY FAR*)lpPaletteEntry);
|
||
::memcpy(&bitmapInfoHeader,mpBitmapInfo,sizeof(BITMAPINFOHEADER));
|
||
bitmapInfoHeader.biClrUsed=mMaxColors;
|
||
bitmapInfoHeader.biClrImportant=mMaxColors;
|
||
::GlobalUnlock(mhGlobalBitmapInfo);
|
||
::GlobalFree(mhGlobalBitmapInfo);
|
||
mhGlobalBitmapInfo=::GlobalAlloc(GMEM_FIXED|GMEM_ZEROINIT,sizeof(BITMAPINFOHEADER)+(sizeof(RGBQUAD)*mMaxColors));
|
||
mpBitmapInfo=(BITMAPINFO FAR *)::GlobalLock(mhGlobalBitmapInfo);
|
||
::memcpy(mpBitmapInfo,&bitmapInfoHeader,sizeof(BITMAPINFOHEADER));
|
||
for(int i=0;i<mMaxColors;i++)
|
||
{
|
||
mpBitmapInfo->bmiColors[i].rgbRed=lpPaletteEntry[i].peRed;
|
||
mpBitmapInfo->bmiColors[i].rgbGreen=lpPaletteEntry[i].peGreen;
|
||
mpBitmapInfo->bmiColors[i].rgbBlue=lpPaletteEntry[i].peBlue;
|
||
}
|
||
delete lpPaletteEntry;
|
||
return TRUE;
|
||
}
|
||
|
||
void Bitmap::createPalette(void)
|
||
{
|
||
RGBQUAD FAR *pRGBQuad;
|
||
LOGPALETTE FAR *pLogicalPalette;
|
||
PALETTEENTRY FAR *pPaletteEntry;
|
||
BITMAPINFOHEADER bitmapInfoHeader;
|
||
HGLOBAL hGlobalPalette;
|
||
|
||
if(mhPalette)::DeleteObject(mhPalette);
|
||
::_lread(mhFile,&bitmapInfoHeader,sizeof(BITMAPINFOHEADER));
|
||
if(!(mMaxColors=(WORD)bitmapInfoHeader.biClrUsed))
|
||
mMaxColors=1 << bitmapInfoHeader.biBitCount;
|
||
mhGlobalBitmapInfo=::GlobalAlloc(GMEM_FIXED|GMEM_ZEROINIT,
|
||
sizeof(BITMAPINFOHEADER)+(sizeof(RGBQUAD)*mMaxColors));
|
||
mpBitmapInfo=(BITMAPINFO FAR *)::GlobalLock(mhGlobalBitmapInfo);
|
||
::memcpy(mpBitmapInfo,&bitmapInfoHeader,sizeof(BITMAPINFOHEADER));
|
||
hGlobalPalette=::GlobalAlloc(GMEM_FIXED|GMEM_ZEROINIT,
|
||
sizeof(LOGPALETTE)+(mMaxColors*sizeof(PALETTEENTRY)));
|
||
pLogicalPalette=(LOGPALETTE FAR *)::GlobalLock(hGlobalPalette);
|
||
pLogicalPalette->palNumEntries=mMaxColors;
|
||
pLogicalPalette->palVersion=0x300;
|
||
for(int i=0;i<mMaxColors;i++)
|
||
{
|
||
pRGBQuad=(RGBQUAD FAR *)&mpBitmapInfo->bmiColors[i];
|
||
::_lread(mhFile,pRGBQuad,sizeof(RGBQUAD));
|
||
pPaletteEntry=(PALETTEENTRY FAR *)&pLogicalPalette->palPalEntry[i];
|
||
pPaletteEntry->peRed=pRGBQuad->rgbRed;
|
||
pPaletteEntry->peGreen=pRGBQuad->rgbGreen;
|
||
pPaletteEntry->peBlue=pRGBQuad->rgbBlue;
|
||
pPaletteEntry->peFlags=0;
|
||
}
|
||
mhPalette=::CreatePalette((LOGPALETTE FAR *)pLogicalPalette);
|
||
::GlobalUnlock(hGlobalPalette);
|
||
::GlobalFree(hGlobalPalette);
|
||
}
|
||
|
||
void Bitmap::decodeImage(void)
|
||
{
|
||
switch(mpBitmapInfo->bmiHeader.biCompression)
|
||
{
|
||
case BI_RGB :
|
||
mSizeImage=((((mpBitmapInfo->bmiHeader.biWidth*
|
||
mpBitmapInfo->bmiHeader.biBitCount)+31)&~31)>>3)*
|
||
mpBitmapInfo->bmiHeader.biHeight;
|
||
mhGlobalImage=::GlobalAlloc(GMEM_FIXED|GMEM_ZEROINIT,mSizeImage);
|
||
mpImage=(UHUGE*)::GlobalLock(mhGlobalImage);
|
||
::_llseek(mhFile,(mBitmapFileHeader.bfOffBits),0);
|
||
::_hread(mhFile,mpImage,mSizeImage);
|
||
break;
|
||
case BI_RLE4 :
|
||
cleanup();
|
||
::MessageBox(::GetFocus(),(LPSTR)"BI_RLE4 Is not implemented at this time.\nPlease try an uncompressed bitmap.",(LPSTR)"ERROR",MB_ICONEXCLAMATION);
|
||
break;
|
||
case BI_RLE8 :
|
||
cleanup();
|
||
::MessageBox(::GetFocus(),(LPSTR)"BI_RLE8 Is not implemented at this time.\nPlease try an uncompressed bitmap.",(LPSTR)"ERROR",MB_ICONEXCLAMATION);
|
||
break;
|
||
}
|
||
}
|
||
|
||
WORD Bitmap::displayBitmap(HWND hDisplayWindow,HDC hDC,int isActive,int conforming)const
|
||
{
|
||
RECT rect;
|
||
HPALETTE hOldPalette;
|
||
WORD width;
|
||
WORD height;
|
||
int suppliedDC;
|
||
|
||
if(!isOkay()||!hDisplayWindow)return FALSE;
|
||
if(Read!=mCurrentMode)return FALSE;
|
||
width=(WORD)mpBitmapInfo->bmiHeader.biWidth;
|
||
height=(WORD)mpBitmapInfo->bmiHeader.biHeight;
|
||
::GetClientRect(hDisplayWindow,(RECT FAR *)&rect);
|
||
if(!hDC){suppliedDC=FALSE;hDC=::GetDC(hDisplayWindow);}
|
||
if(isActive)hOldPalette=::SelectPalette(hDC,mhPalette,FALSE);
|
||
else hOldPalette=::SelectPalette(hDC,mhPalette,TRUE);
|
||
::RealizePalette(hDC);
|
||
if(conforming)
|
||
::StretchDIBits(hDC,0,0,rect.right,rect.bottom,0,0,width,height,mpImage,(BITMAPINFO *)mpBitmapInfo,DIB_RGB_COLORS,SRCCOPY);
|
||
else
|
||
::StretchDIBits(hDC,0,0,width,height,0,0,width,height,mpImage,(BITMAPINFO *)mpBitmapInfo,DIB_RGB_COLORS,SRCCOPY);
|
||
if(isActive)::SelectPalette(hDC,hOldPalette,FALSE);
|
||
else ::SelectPalette(hDC,hOldPalette,TRUE);
|
||
if(!suppliedDC)::ReleaseDC(hDisplayWindow,hDC);
|
||
return TRUE;
|
||
}
|
||
|
||
WORD Bitmap::saveBitmap(void)const
|
||
{
|
||
BITMAPFILEHEADER bitmapFileHeader;
|
||
|
||
if(!isOkay())return FALSE;
|
||
if(Write!=mCurrentMode)return FALSE;
|
||
::memset(&bitmapFileHeader,0,sizeof(BITMAPFILEHEADER));
|
||
bitmapFileHeader.bfType=Signature;
|
||
bitmapFileHeader.bfSize=sizeof(BITMAPFILEHEADER)+
|
||
sizeof(BITMAPINFOHEADER)+(sizeof(RGBQUAD)*mMaxColors)+mSizeImage;
|
||
bitmapFileHeader.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+(sizeof(RGBQUAD)*mMaxColors);
|
||
::_lwrite(mhFile,(char*)&bitmapFileHeader,sizeof(BITMAPFILEHEADER));
|
||
::_lwrite(mhFile,(char*)mpBitmapInfo,sizeof(BITMAPINFOHEADER)+(sizeof(RGBQUAD)*mMaxColors));
|
||
::_hwrite(mhFile,(char*)mpImage,mSizeImage);
|
||
return FALSE;
|
||
}
|
||
|
||
void Bitmap::cleanup(void)
|
||
{
|
||
if(HFILE_ERROR!=mhFile)
|
||
{::_lclose(mhFile);mhFile=HFILE_ERROR;}
|
||
if(mhPalette)
|
||
{::DeleteObject(mhPalette);mhPalette=0;}
|
||
if(mhGlobalImage)
|
||
{while(::GlobalUnlock(mhGlobalImage));::GlobalFree(mhGlobalImage);
|
||
mhGlobalImage=0;}
|
||
if(mhGlobalBitmapInfo)
|
||
{while(::GlobalUnlock(mhGlobalBitmapInfo));
|
||
::GlobalFree(mhGlobalBitmapInfo);mhGlobalBitmapInfo=0;}
|
||
}
|
||
|
||
void Bitmap::copyBits(UHUGE *destination,UHUGE *source,unsigned long length)const
|
||
{
|
||
for(unsigned long count=0;count<length;count++)
|
||
*destination++=*source++;
|
||
}
|
||
|