#include #include #include #include #include #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<bmiHeader.biBitCount; mWidth=getInfoPtr()->bmiHeader.biWidth; mHeight=getInfoPtr()->bmiHeader.biHeight; setPalette(); } Bitmap::Bitmap(const String &pathFileName,BitmapInfo &infoData,GlobalData &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<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;srcRowbmiHeader.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;rowIndexbmiHeader.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;itemIndexbmiColors[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 rgbIndexVector; WORD paletteEntries; RGBTree paletteTree; RGBColor rgbColor; RGBIndex rgbIndex; paletteEntries=purePalette.paletteEntries(); rgbIndexVector.size(paletteEntries); for(int paletteIndex=0;paletteIndexbmiColors[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<bmiHeader.biWidth; mHeight=getInfoPtr()->bmiHeader.biHeight; getRequiredWidth(mWidth,mHeight); for(int i=0;ibmiColors[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>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()||!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=width()||!lpColData)return FALSE; UHUGE *lpImage=getDataPtr()+mImageExtent; lpImage=(lpImage-(LONG)width())+(LONG)col; for(short rowIndex=0;rowIndex