545 lines
18 KiB
C++
545 lines
18 KiB
C++
#include <common/bminfo.hpp>
|
|
#include <common/bitmap.hpp>
|
|
#include <common/array.hpp>
|
|
#include <common/memfile.hpp>
|
|
#include <bsptree/rgbtree.hpp>
|
|
#define MaxBlock 64000L
|
|
|
|
Bitmap::Bitmap(void)
|
|
: mhFile(HFILE_ERROR), mCurrentMode(Idle), mMaxColors(0), mImageExtent(0),
|
|
mBlockSize(MaxBlock), mWidth(0), mHeight(0)
|
|
{
|
|
}
|
|
|
|
Bitmap::Bitmap(const Bitmap &someBitmap)
|
|
: mMaxColors(someBitmap.mMaxColors), mFileName(someBitmap.mFileName),
|
|
mImageExtent(someBitmap.mImageExtent), mBlockSize(someBitmap.mBlockSize),
|
|
mhFile(HFILE_ERROR), mCurrentMode(Write), mWidth(0), mHeight(0)
|
|
{
|
|
if(!someBitmap.isOkay())return;
|
|
copyBitmap(someBitmap);
|
|
}
|
|
|
|
Bitmap::Bitmap(const String &pathFileName)
|
|
: mhFile(HFILE_ERROR), mMaxColors(0), mCurrentMode(Read), mImageExtent(0),
|
|
mBlockSize(MaxBlock), mWidth(0), mHeight(0)
|
|
{
|
|
processBitmap(pathFileName);
|
|
}
|
|
|
|
Bitmap::Bitmap(const String &pathFileName,HGLOBAL hGlobalImage,HGLOBAL hGlobalBitmapInfo)
|
|
: mhFile(HFILE_ERROR), mMaxColors(0), mCurrentMode(Write), mImageExtent(0),
|
|
mBlockSize(MaxBlock), mWidth(0), mHeight(0)
|
|
{
|
|
DWORD sizeBitmapInfo;
|
|
DWORD sizeBitmapImage;
|
|
BITMAPINFO FAR *lpSourceBitmapInfo;
|
|
UHUGE *lpSourceImage;
|
|
|
|
if(!hGlobalImage||!hGlobalBitmapInfo)return;
|
|
if(pathFileName.isNull())return;
|
|
mFileName=pathFileName;
|
|
sizeBitmapInfo=::GlobalSize(hGlobalBitmapInfo);
|
|
sizeBitmapImage=::GlobalSize(hGlobalImage);
|
|
reserveInfo(sizeBitmapInfo);
|
|
lpSourceBitmapInfo=(BITMAPINFO FAR*)::GlobalLock(hGlobalBitmapInfo);
|
|
copyBits((UHUGE*)getInfoPtr(),(UHUGE*)lpSourceBitmapInfo,sizeBitmapInfo);
|
|
::GlobalUnlock(hGlobalBitmapInfo);
|
|
mImageExtent=imageExtent();
|
|
if(mImageExtent!=sizeBitmapImage)mImageExtent=sizeBitmapImage;
|
|
reserveData(mImageExtent);
|
|
lpSourceImage=(UHUGE*)::GlobalLock(hGlobalImage);
|
|
copyBits(getDataPtr(),lpSourceImage,mImageExtent);
|
|
::GlobalUnlock(hGlobalImage);
|
|
if(!(mMaxColors=(WORD)getInfoPtr()->bmiHeader.biClrUsed))mMaxColors=1<<getInfoPtr()->bmiHeader.biBitCount;
|
|
mWidth=getInfoPtr()->bmiHeader.biWidth;
|
|
mHeight=getInfoPtr()->bmiHeader.biHeight;
|
|
setPalette();
|
|
}
|
|
|
|
Bitmap::Bitmap(const String &pathFileName,BitmapInfo &infoData,GlobalData<BYTE> &imageData)
|
|
: mhFile(HFILE_ERROR), mMaxColors(0), mCurrentMode(Write), mImageExtent(0),
|
|
mBlockSize(MaxBlock), mWidth(0), mHeight(0)
|
|
{
|
|
DWORD sizeBitmapInfo;
|
|
DWORD sizeBitmapImage;
|
|
BITMAPINFO FAR *lpSourceBitmapInfo;
|
|
UHUGE *lpSourceImage;
|
|
|
|
if(!imageData.size())return;
|
|
if(pathFileName.isNull())return;
|
|
mFileName=pathFileName;
|
|
sizeBitmapInfo=(sizeof(BITMAPINFO)-sizeof(RGBQUAD))+(infoData.rgbColors()*sizeof(RGBQUAD));
|
|
sizeBitmapImage=imageData.size();
|
|
reserveInfo(sizeBitmapInfo);
|
|
copyBits((UHUGE*)getInfoPtr(),(UHUGE*)((BITMAPINFO*)infoData),sizeBitmapInfo);
|
|
mImageExtent=imageExtent();
|
|
if(mImageExtent!=sizeBitmapImage)mImageExtent=sizeBitmapImage;
|
|
reserveData(mImageExtent);
|
|
copyBits(getDataPtr(),(BYTE*)&imageData[0],mImageExtent);
|
|
if(BitmapInfo::Bit8==getInfoPtr()->bmiHeader.biBitCount&&!(mMaxColors=(WORD)getInfoPtr()->bmiHeader.biClrUsed))mMaxColors=1<<getInfoPtr()->bmiHeader.biBitCount;
|
|
mWidth=getInfoPtr()->bmiHeader.biWidth;
|
|
mHeight=getInfoPtr()->bmiHeader.biHeight;
|
|
if(BitmapInfo::Bit8==getInfoPtr()->bmiHeader.biBitCount)setPalette();
|
|
}
|
|
|
|
Bitmap::Bitmap(const String &pathFileName,WORD bitmapWidth,WORD bitmapHeight,WORD bitmapColors,WORD bitCount)
|
|
: mhFile(HFILE_ERROR), mMaxColors(bitmapColors), mCurrentMode(Write),
|
|
mImageExtent(0), mBlockSize(MaxBlock), mWidth(0), mHeight(0)
|
|
{
|
|
BITMAPINFOHEADER bitmapInfoHeader;
|
|
LONG rgbQuadBytes(bitmapColors*sizeof(RGBQUAD));
|
|
UHUGE *lpPtr;
|
|
|
|
if(!bitmapWidth||!bitmapHeight||!bitmapColors||pathFileName.isNull())return;
|
|
getRequiredWidth(bitmapWidth,bitmapHeight);
|
|
mFileName=pathFileName;
|
|
bitmapInfoHeader.biSize=sizeof(BITMAPINFOHEADER);
|
|
mWidth=bitmapInfoHeader.biWidth=bitmapWidth;
|
|
mHeight=bitmapInfoHeader.biHeight=bitmapHeight;
|
|
bitmapInfoHeader.biPlanes=Planes;
|
|
bitmapInfoHeader.biBitCount=bitCount;
|
|
bitmapInfoHeader.biCompression=BI_RGB;
|
|
bitmapInfoHeader.biSizeImage=0;
|
|
bitmapInfoHeader.biXPelsPerMeter=0;
|
|
bitmapInfoHeader.biYPelsPerMeter=0;
|
|
bitmapInfoHeader.biClrUsed=bitmapColors;
|
|
bitmapInfoHeader.biClrImportant=bitmapColors;
|
|
reserveInfo(0,bitmapColors);
|
|
copyBits((UHUGE*)getInfoPtr(),(UHUGE*)&bitmapInfoHeader,sizeof(BITMAPINFOHEADER));
|
|
lpPtr=((UHUGE*)getInfoPtr())+sizeof(BITMAPINFOHEADER);
|
|
setBits(lpPtr,0,rgbQuadBytes);
|
|
mImageExtent=imageExtent();
|
|
lpPtr=reserveData(mImageExtent);
|
|
setBits(lpPtr,0,mImageExtent);
|
|
}
|
|
|
|
Bitmap::~Bitmap()
|
|
{
|
|
closeFile();
|
|
}
|
|
|
|
WORD Bitmap::operator+=(const BitmapOverlay &someBitmapOverlay)
|
|
{
|
|
Bitmap &sourceBitmap=((BitmapOverlay&)someBitmapOverlay).bitmap();
|
|
Point placementPoint(((BitmapOverlay&)someBitmapOverlay).placementPoint());
|
|
UHUGE *lpSrcData;
|
|
UHUGE *lpDstData;
|
|
UHUGE *lpSrcPtr;
|
|
UHUGE *lpDstPtr;
|
|
LONG srcWidth;
|
|
LONG srcHeight;
|
|
LONG dstWidth;
|
|
LONG dstHeight;
|
|
LONG copyRows;
|
|
LONG copyCols;
|
|
|
|
if(!isOkay()||!sourceBitmap.isOkay())return FALSE;
|
|
mCurrentMode=Write;
|
|
srcWidth=copyCols=sourceBitmap.getInfoPtr()->bmiHeader.biWidth;
|
|
srcHeight=copyRows=sourceBitmap.getInfoPtr()->bmiHeader.biHeight;
|
|
dstWidth=getInfoPtr()->bmiHeader.biWidth;
|
|
dstHeight=getInfoPtr()->bmiHeader.biHeight;
|
|
if(placementPoint.x()<0)placementPoint.x(0);
|
|
if(placementPoint.y()<0)placementPoint.y(0);
|
|
if(placementPoint.x()>=dstWidth)return FALSE;
|
|
if(placementPoint.y()>=dstHeight)return FALSE;
|
|
if((LONG)placementPoint.x()+srcWidth>dstWidth)copyCols=dstWidth-placementPoint.x();
|
|
if((LONG)placementPoint.y()+srcHeight>dstHeight)copyRows=dstHeight-placementPoint.y();
|
|
upsideDown();
|
|
sourceBitmap.upsideDown();
|
|
lpSrcData=sourceBitmap.getDataPtr();
|
|
lpDstData=getDataPtr();
|
|
for(LONG srcRow=0;srcRow<copyRows;srcRow++)
|
|
{
|
|
lpSrcPtr=(lpSrcData+(srcWidth*srcRow));
|
|
lpDstPtr=(lpDstData+(((srcRow+(LONG)placementPoint.y())*dstWidth)+(LONG)placementPoint.x()));
|
|
copyBits(lpDstPtr,lpSrcPtr,copyCols);
|
|
}
|
|
upsideDown();
|
|
sourceBitmap.upsideDown();
|
|
return TRUE;
|
|
}
|
|
|
|
void Bitmap::upsideDown(void)
|
|
{
|
|
LONG width(getInfoPtr()->bmiHeader.biWidth);
|
|
LONG height(getInfoPtr()->bmiHeader.biHeight);
|
|
UHUGE *lpSrc=getDataPtr();
|
|
UHUGE *lpDst;
|
|
HGLOBAL hGlobalTemp;
|
|
|
|
hGlobalTemp=::GlobalAlloc(GMEM_ZEROINIT|GMEM_MOVEABLE,width*height);
|
|
lpDst=(UHUGE*)::GlobalLock(hGlobalTemp);
|
|
for(LONG rowIndex=0;rowIndex<height;rowIndex++)
|
|
copyBits(lpDst+(rowIndex*width),(lpSrc+(height-rowIndex)*width)-width,width);
|
|
if(BitmapData::Keep==getDataType())copyBits(lpSrc,lpDst,width*height);
|
|
else setData(hGlobalTemp,lpDst);
|
|
}
|
|
|
|
void Bitmap::copyBitmap(const Bitmap &someBitmap)
|
|
{
|
|
DWORD sizeBitmapInfo;
|
|
DWORD sizeBitmapData;
|
|
|
|
sizeBitmapInfo=::GlobalSize(someBitmap.getInfoHnd());
|
|
sizeBitmapData=::GlobalSize(someBitmap.getDataHnd());
|
|
reserveData(sizeBitmapData);
|
|
reserveInfo(sizeBitmapInfo);
|
|
copyBits((UHUGE*)reserveInfo(sizeBitmapInfo),(UHUGE*)someBitmap.getInfoPtr(),sizeBitmapInfo);
|
|
copyBits((UHUGE*)reserveData(sizeBitmapData),(UHUGE*)someBitmap.getDataPtr(),sizeBitmapData);
|
|
mWidth=getInfoPtr()->bmiHeader.biWidth;
|
|
mHeight=getInfoPtr()->bmiHeader.biHeight;
|
|
mBitmapPalette=someBitmap.getPalette();
|
|
}
|
|
|
|
WORD Bitmap::operator=(const String &pathFileName)
|
|
{
|
|
int returnCode;
|
|
|
|
mCurrentMode=Read;
|
|
returnCode=processBitmap(pathFileName);
|
|
return returnCode;
|
|
}
|
|
|
|
Bitmap &Bitmap::operator=(const Bitmap &someBitmap)
|
|
{
|
|
if(!someBitmap.isOkay())return *this;
|
|
if(getDataType()==BitmapData::Keep)return *this;
|
|
mCurrentMode=someBitmap.mCurrentMode;
|
|
mMaxColors=someBitmap.mMaxColors;
|
|
mFileName=someBitmap.mFileName;
|
|
mImageExtent=someBitmap.mImageExtent;
|
|
copyBitmap(someBitmap);
|
|
return *this;
|
|
}
|
|
|
|
WORD Bitmap::processBitmap(const 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){closeFile();return FALSE;}
|
|
readPalette();
|
|
decodeImage();
|
|
closeFile();
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL Bitmap::isValidBitmap(const 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;
|
|
}
|
|
|
|
HPALETTE Bitmap::getPalette(void)const
|
|
{
|
|
return mBitmapPalette.getPalette();
|
|
}
|
|
|
|
WORD Bitmap::setPalette(HPALETTE hPalette,WORD remapBitmap)
|
|
{
|
|
BITMAPINFOHEADER bitmapInfoHeader;
|
|
|
|
if(!isOkay()||!hPalette)return FALSE;
|
|
PurePalette purePalette(hPalette);
|
|
if(mBitmapPalette==purePalette)return FALSE;
|
|
if(remapBitmap)mapPalette(purePalette);
|
|
mBitmapPalette=purePalette;
|
|
mMaxColors=mBitmapPalette.paletteEntries();
|
|
::memcpy(&bitmapInfoHeader,getInfoPtr(),sizeof(BITMAPINFOHEADER));
|
|
reserveInfo(0,mMaxColors);
|
|
::memcpy(getInfoPtr(),&bitmapInfoHeader,sizeof(BITMAPINFOHEADER));
|
|
getInfoPtr()->bmiHeader.biClrUsed=0;
|
|
getInfoPtr()->bmiHeader.biClrImportant=0;
|
|
for(int itemIndex=0;itemIndex<mMaxColors;itemIndex++)
|
|
{
|
|
getInfoPtr()->bmiColors[itemIndex].rgbRed=mBitmapPalette[itemIndex].red();
|
|
getInfoPtr()->bmiColors[itemIndex].rgbGreen=mBitmapPalette[itemIndex].green();
|
|
getInfoPtr()->bmiColors[itemIndex].rgbBlue=mBitmapPalette[itemIndex].blue();
|
|
getInfoPtr()->bmiColors[itemIndex].rgbReserved=0;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
void Bitmap::mapPalette(PurePalette &purePalette)
|
|
{
|
|
Array<RGBIndex> rgbIndexVector;
|
|
WORD paletteEntries;
|
|
RGBTree paletteTree;
|
|
RGBColor rgbColor;
|
|
RGBIndex rgbIndex;
|
|
|
|
paletteEntries=purePalette.paletteEntries();
|
|
rgbIndexVector.size(paletteEntries);
|
|
for(int paletteIndex=0;paletteIndex<paletteEntries;paletteIndex++)
|
|
{
|
|
rgbColor=purePalette[paletteIndex];
|
|
rgbIndex=RGBIndex(rgbColor,paletteIndex);
|
|
rgbIndexVector[paletteIndex]=rgbIndex;
|
|
}
|
|
paletteTree.insertItems(rgbIndexVector);
|
|
for(int mapIndex=0;mapIndex<mImageExtent;mapIndex++)
|
|
{
|
|
paletteIndex=*(getDataPtr()+mapIndex);
|
|
rgbColor=mBitmapPalette[paletteIndex];
|
|
RGBIndex searchIndex(rgbColor,paletteIndex);
|
|
if(paletteTree.searchItem(searchIndex,RGBTree::SearchNearest))
|
|
*(getDataPtr()+mapIndex)=searchIndex.paletteIndex();
|
|
}
|
|
}
|
|
|
|
void Bitmap::setPalette(void)
|
|
{
|
|
RGBColor rgbColor;
|
|
|
|
if(!isOkay())return;
|
|
for(int paletteIndex=0;paletteIndex<mMaxColors;paletteIndex++)
|
|
{
|
|
rgbColor.red(getInfoPtr()->bmiColors[paletteIndex].rgbRed);
|
|
rgbColor.green(getInfoPtr()->bmiColors[paletteIndex].rgbGreen);
|
|
rgbColor.blue(getInfoPtr()->bmiColors[paletteIndex].rgbBlue);
|
|
mBitmapPalette.setPaletteColor(paletteIndex,rgbColor,PaletteEntry::NullFlag);
|
|
}
|
|
return;
|
|
}
|
|
|
|
void Bitmap::readPalette(void)
|
|
{
|
|
RGBQUAD FAR *lpRGBQuad;
|
|
BITMAPINFOHEADER bitmapInfoHeader;
|
|
|
|
if(HFILE_ERROR==mhFile||Read!=mCurrentMode)return;
|
|
::_lread(mhFile,&bitmapInfoHeader,sizeof(BITMAPINFOHEADER));
|
|
if(!(mMaxColors=(WORD)bitmapInfoHeader.biClrUsed))mMaxColors=1<<bitmapInfoHeader.biBitCount;
|
|
reserveInfo(0,mMaxColors);
|
|
::memcpy(getInfoPtr(),&bitmapInfoHeader,sizeof(BITMAPINFOHEADER));
|
|
mWidth=getInfoPtr()->bmiHeader.biWidth;
|
|
mHeight=getInfoPtr()->bmiHeader.biHeight;
|
|
getRequiredWidth(mWidth,mHeight);
|
|
|
|
for(int i=0;i<mMaxColors;i++)
|
|
{
|
|
lpRGBQuad=(RGBQUAD FAR *)&(getInfoPtr()->bmiColors[i]);
|
|
::_lread(mhFile,lpRGBQuad,sizeof(RGBQUAD));
|
|
mBitmapPalette.setPaletteColor(i,RGBColor(lpRGBQuad->rgbRed,lpRGBQuad->rgbGreen,lpRGBQuad->rgbBlue),PaletteEntry::NullFlag);
|
|
}
|
|
}
|
|
|
|
void Bitmap::decodeImage(void)
|
|
{
|
|
switch(getInfoPtr()->bmiHeader.biCompression)
|
|
{
|
|
case BI_RGB :
|
|
mImageExtent=imageExtent();
|
|
reserveData(mImageExtent);
|
|
::_llseek(mhFile,(mBitmapFileHeader.bfOffBits),0);
|
|
::_hread(mhFile,getDataPtr(),mImageExtent);
|
|
break;
|
|
case BI_RLE4 :
|
|
closeFile();
|
|
::MessageBox(::GetFocus(),(LPSTR)"BI_RLE4 is not supported at this time.\nPlease try an uncompressed bitmap.",(LPSTR)"ERROR",MB_ICONEXCLAMATION);
|
|
break;
|
|
case BI_RLE8 :
|
|
closeFile();
|
|
::MessageBox(::GetFocus(),(LPSTR)"BI_RLE8 is not supported at this time.\nPlease try an uncompressed bitmap.",(LPSTR)"ERROR",MB_ICONEXCLAMATION);
|
|
break;
|
|
}
|
|
}
|
|
|
|
HBITMAP Bitmap::createBitmap(PureDevice &somePureDevice)
|
|
{
|
|
HBITMAP hBitmap;
|
|
|
|
if(!isOkay())return FALSE;
|
|
hBitmap=::CreateDIBitmap(somePureDevice,(BITMAPINFOHEADER FAR*)getInfoPtr(),
|
|
CBM_INIT,getDataPtr(),(BITMAPINFO FAR*)getInfoPtr(),DIB_RGB_COLORS);
|
|
return hBitmap;
|
|
}
|
|
|
|
WORD Bitmap::displayBitmap(HWND hDisplayWindow,HDC hDC,int isActive,int conforming)const
|
|
{
|
|
RECT windowRect;
|
|
HPALETTE hOldPalette;
|
|
WORD windowWidth;
|
|
WORD windowHeight;
|
|
int suppliedDC;
|
|
|
|
if(!isOkay()||!::IsWindow(hDisplayWindow))return FALSE;
|
|
::GetClientRect(hDisplayWindow,(RECT FAR *)&windowRect);
|
|
windowWidth=windowRect.right;
|
|
windowHeight=windowRect.bottom;
|
|
if(!hDC){suppliedDC=FALSE;hDC=::GetDC(hDisplayWindow);}
|
|
if(isActive)hOldPalette=::SelectPalette(hDC,mBitmapPalette.getPalette(),FALSE);
|
|
else hOldPalette=::SelectPalette(hDC,mBitmapPalette.getPalette(),TRUE);
|
|
::RealizePalette(hDC);
|
|
if(conforming)::StretchDIBits(hDC,0,0,windowRect.right,windowRect.bottom,0,0,
|
|
width(),height(),getDataPtr(),(BITMAPINFO *)getInfoPtr(),DIB_RGB_COLORS,SRCCOPY);
|
|
else
|
|
{
|
|
::StretchDIBits(hDC,0,0,width()>windowWidth?windowWidth:width(),
|
|
height()>windowHeight?windowHeight:height(),0,0,width(),height(),
|
|
getDataPtr(),(BITMAPINFO *)getInfoPtr(),DIB_RGB_COLORS,SRCCOPY);
|
|
}
|
|
if(isActive)::SelectPalette(hDC,hOldPalette,FALSE);
|
|
else ::SelectPalette(hDC,hOldPalette,TRUE);
|
|
if(!suppliedDC)::ReleaseDC(hDisplayWindow,hDC);
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL Bitmap::draw(PureDevice &pureDevice,const Rect &dstRect,const Point &srcPoint)
|
|
{
|
|
if(!isOkay())return FALSE;
|
|
::StretchDIBits(pureDevice,dstRect.left(),dstRect.top(),dstRect.right(),dstRect.bottom(),srcPoint.x(),srcPoint.y(),dstRect.right(),dstRect.bottom(),getDataPtr(),(BITMAPINFO *)getInfoPtr(),DIB_RGB_COLORS,SRCCOPY);
|
|
return TRUE;
|
|
}
|
|
|
|
bool Bitmap::saveBitmap(void)
|
|
{
|
|
BITMAPFILEHEADER bitmapFileHeader;
|
|
OFSTRUCT ofStruct;
|
|
|
|
if(!isOkay())return false;
|
|
if((HFILE_ERROR==mhFile)&&(HFILE_ERROR==(mhFile=::OpenFile(mFileName,&ofStruct,OF_WRITE|OF_CREATE))))return false;
|
|
::memset(&bitmapFileHeader,0,sizeof(BITMAPFILEHEADER));
|
|
bitmapFileHeader.bfType=Signature;
|
|
bitmapFileHeader.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)+(sizeof(RGBQUAD)*(mMaxColors-1))+mImageExtent;
|
|
bitmapFileHeader.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)+(sizeof(RGBQUAD)*(mMaxColors-1));
|
|
::_lwrite(mhFile,(char*)&bitmapFileHeader,sizeof(BITMAPFILEHEADER));
|
|
::_lwrite(mhFile,(char*)getInfoPtr(),sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)+(sizeof(RGBQUAD)*(mMaxColors-1)));
|
|
::_hwrite(mhFile,(char*)getDataPtr(),mImageExtent);
|
|
closeFile();
|
|
return true;
|
|
}
|
|
|
|
bool Bitmap::saveBitmap(MemFile &memFile)
|
|
{
|
|
BITMAPFILEHEADER bitmapFileHeader;
|
|
OFSTRUCT ofStruct;
|
|
|
|
if(!isOkay())return false;
|
|
if((HFILE_ERROR==mhFile)&&(HFILE_ERROR==(mhFile=::OpenFile(mFileName,&ofStruct,OF_WRITE|OF_CREATE))))return false;
|
|
::memset(&bitmapFileHeader,0,sizeof(BITMAPFILEHEADER));
|
|
bitmapFileHeader.bfType=Signature;
|
|
bitmapFileHeader.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)+(sizeof(RGBQUAD)*(mMaxColors-1))+mImageExtent;
|
|
bitmapFileHeader.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)+(sizeof(RGBQUAD)*(mMaxColors-1));
|
|
if(!memFile.write((char*)&bitmapFileHeader,sizeof(BITMAPFILEHEADER)))return false;
|
|
if(!memFile.write((char*)getInfoPtr(),sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)+(sizeof(RGBQUAD)*(mMaxColors-1))))return false;
|
|
if(!memFile.write((char*)getDataPtr(),mImageExtent))return false;
|
|
return true;
|
|
}
|
|
|
|
bool Bitmap::saveBitmap(const String &pathFileName)
|
|
{
|
|
if(!isOkay())return false;
|
|
mFileName=pathFileName;
|
|
return saveBitmap();
|
|
}
|
|
|
|
void Bitmap::copyBits(UHUGE *destination,UHUGE *source,unsigned long length)const
|
|
{
|
|
for(unsigned long count=0;count<length;count++)*destination++=*source++;
|
|
}
|
|
|
|
void Bitmap::setBits(UHUGE *lpChar,unsigned char charValue,unsigned long length)const
|
|
{
|
|
for(unsigned long count=0;count<length;count++)*lpChar++=charValue;
|
|
}
|
|
|
|
void Bitmap::getRequiredWidth(WORD &desiredWidth,WORD desiredHeight)
|
|
{
|
|
DWORD imageExtent;
|
|
|
|
imageExtent=(((((LONG)desiredWidth*8)+31)&~31)>>3)*(LONG)desiredHeight;
|
|
if(imageExtent==(LONG)desiredWidth*(LONG)desiredHeight)return;
|
|
desiredWidth=(WORD)(imageExtent/(LONG)desiredHeight);
|
|
}
|
|
|
|
void Bitmap::getRequiredWidth(DWORD &desiredWidth,DWORD desiredHeight)
|
|
{
|
|
DWORD imageExtent;
|
|
|
|
imageExtent=(((((LONG)desiredWidth*8)+31)&~31)>>3)*(LONG)desiredHeight;
|
|
if(imageExtent==(LONG)desiredWidth*(LONG)desiredHeight)return;
|
|
desiredWidth=(WORD)(imageExtent/(LONG)desiredHeight);
|
|
}
|
|
|
|
Bitmap &Bitmap::rotateRight(void)
|
|
{
|
|
Bitmap tempBitmap(mFileName,height(),width());
|
|
|
|
tempBitmap.setPalette(getPalette(),FALSE);
|
|
for(int rowIndex=0;rowIndex<height();rowIndex++)
|
|
for(int colIndex=0;colIndex<width();colIndex++)
|
|
tempBitmap.setByte(colIndex,(height()-1)-rowIndex,getByte(rowIndex,colIndex));
|
|
*this=tempBitmap;
|
|
return *this;
|
|
}
|
|
|
|
Bitmap &Bitmap::rotateLeft(void)
|
|
{
|
|
Bitmap tempBitmap(mFileName,height(),width());
|
|
|
|
tempBitmap.setPalette(getPalette(),FALSE);
|
|
for(int rowIndex=0;rowIndex<height();rowIndex++)
|
|
for(int colIndex=0;colIndex<width();colIndex++)
|
|
tempBitmap.setByte((width()-1)-colIndex,rowIndex,getByte(rowIndex,colIndex));
|
|
*this=tempBitmap;
|
|
return *this;
|
|
}
|
|
|
|
WORD Bitmap::getRow(WORD row,char FAR *lpRowData)
|
|
{
|
|
if(!isOkay()||row>=height()||!lpRowData)return FALSE;
|
|
UHUGE *lpImage=getDataPtr()+mImageExtent;
|
|
copyBits((UHUGE*)lpRowData,(lpImage-(((LONG)row*(LONG)width())+(LONG)width())),width());
|
|
return TRUE;
|
|
}
|
|
|
|
WORD Bitmap::setRow(WORD row,char FAR *lpRowData)
|
|
{
|
|
if(!isOkay()||row>=height()||!lpRowData)return FALSE;
|
|
UHUGE *lpImage=getDataPtr()+mImageExtent;
|
|
copyBits((UHUGE*)(lpImage-(((LONG)row*(LONG)width())+(LONG)width())),(UHUGE*)lpRowData,width());
|
|
return TRUE;
|
|
}
|
|
|
|
WORD Bitmap::getCol(WORD col,char FAR *lpColData)
|
|
{
|
|
if(!isOkay()||col>=width()||!lpColData)return FALSE;
|
|
UHUGE *lpImage=getDataPtr()+mImageExtent;
|
|
lpImage=(lpImage-(LONG)width())+(LONG)col;
|
|
for(short rowIndex=0;rowIndex<height();rowIndex++)
|
|
{
|
|
*lpColData=*lpImage;
|
|
lpImage-=(LONG)width();
|
|
lpColData++;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
WORD Bitmap::setCol(WORD col,char FAR *lpColData)
|
|
{
|
|
if(!isOkay()||col>=width()||!lpColData)return FALSE;
|
|
UHUGE *lpImage=getDataPtr()+mImageExtent;
|
|
lpImage=(lpImage-(LONG)width())+(LONG)col;
|
|
for(short rowIndex=0;rowIndex<height();rowIndex++)
|
|
{
|
|
*lpImage=*lpColData;
|
|
lpImage-=(LONG)width();
|
|
lpColData++;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|