www.pudn.com > dip_1_1_bmp2jpeg.rar > Image.cpp
/***************************************************************/ /*文件名: image.cpp */ /*文件描述: */ /*相关文件: image.h */ /*主要函数: read and write and Displan */ /*提交日期: 作 者:王瑞 张洪明 */ /*编 辑 器: Visual C++ */ /*版权: 先进人及通信联合实验室 */ /*版权说明:任何使用必须保留版权信息和历史纪录信息 */ /*修改纪录: */ /*日 期 版本 修改人 修改内容 */ /***************************************************************/ #include "stdafx.h" #include "math.h" #include// for GlobalAllocPtr #include "image.h" IMPLEMENT_SERIAL(CImage, CObject, 0) /////////////////////////////////////////////////////////////////// CImage::CImage(): m_bIsDIB(TRUE),m_dwLength(0L), m_pDib (NULL),m_pData(NULL) { m_pPal =new CPalette; } /////////////////////////////////////////////////////////////////// CImage::CImage(const CImage& img)//copy constructor { m_bIsDIB=img.m_bIsDIB; m_dwLength=img.m_dwLength; m_pDib=0; if(img.m_pDib){ m_pDib=(BYTE*) GlobalAllocPtr(GHND, m_dwLength); if(!m_pDib) { AfxMessageBox("Unable to allocate DIB memory"); return; } memcpy(m_pDib,img.m_pDib,m_dwLength); m_pData = (BYTE*) m_pDib + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * img.NumColors(); } m_pPal=new CPalette; CreateDIBPalette(); } /////////////////////////////////////////////////////////////////// CImage::CImage(CImage& img, CPoint start, CSize size) { int bpp; int bytepp; long hdlen;/*size of the DIB header info*/ LPBITMAPINFOHEADER pBMIH; ASSERT(img.m_pDib); WORD dww=img.Width(); WORD dwh=img.Height(); if(( (size.cx+start.x)>dww )||( (size.cy+start.y)>dwh )) { CRect rect1 = CRect(CPoint(0,0),CSize(dww-1,dwh-1)); CRect rect = CRect(start,size); rect &= rect1; start.x = rect.left; start.y = rect.top; size.cx = rect.right - rect.left; size.cy = rect.bottom - rect.top; } img.Data(); m_bIsDIB = FALSE; hdlen = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * img.NumColors(); bpp = img.Bits(); bytepp = bpp / 8; ASSERT(bpp != 16 && bpp != 32); DWORD bypeinoneline = ByteNumForOneLine((WORD)size.cx, bpp);//Bytes per line m_dwLength = hdlen + bypeinoneline * size.cy; if (!AllocateMemory( )){ return; } memcpy(m_pDib, img.m_pDib, hdlen); pBMIH = BMInfoHdPtr(); pBMIH->biWidth = size.cx; pBMIH->biHeight = size.cy; pBMIH->biSizeImage = size.cx * size.cy * bytepp; m_pData = (BYTE*)(m_pDib + hdlen); BYTE* p1, *p2; long t1, t2; t1 = dww * bytepp; t2 = size.cx * bytepp; p1 = ( BYTE* ) ( img.m_pData + (start.y * dww + start.x) * bytepp); p2 = m_pData; for(int i=0 ; i<(int)size.cy; i++) { memcpy(p2 , p1 , t2); p1 += t1; p2 += t2; } Dib(); img.Dib(); m_pPal=new CPalette; CreateDIBPalette(); } /////////////////////////////////////////////// /*the constructor used to create a DIB of size 'size' with no initializing image data*/ CImage::CImage(CSize size,int NumColor,int Bits) { LPBITMAPINFOHEADER pBMIH; m_dwLength = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * NumColor; if (!AllocateMemory()) return; DWORD dwBytes = Transform((WORD)size.cx); m_dwLength += dwBytes * size.cy * Bits / 8; if (!AllocateMemory(TRUE)){ return; } pBMIH=BMInfoHdPtr(); pBMIH->biSize = sizeof(BITMAPINFOHEADER); pBMIH->biWidth = size.cx; pBMIH->biHeight = size.cy; pBMIH->biSizeImage = size.cx*size.cy; pBMIH->biPlanes = 1; pBMIH->biBitCount = Bits; // 1, 4, 8, or 24 pBMIH->biCompression = BI_RGB; pBMIH->biXPelsPerMeter = 0; pBMIH->biYPelsPerMeter = 0; pBMIH->biClrUsed = 0; pBMIH->biClrImportant = 0; m_pData = (BYTE*)(m_pDib + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * NumColor); SetDIB(); m_pPal=new CPalette; CreateGreyPalette(); } /////////////////////////////////////////////////////////////////// //part copy constructor CImage& CImage::operator=(const CImage& img) { m_bIsDIB=img.m_bIsDIB; m_dwLength=img.m_dwLength; if(img.m_pDib){ TRY { if(m_pDib){ m_pDib = (BYTE*) GlobalReAllocPtr(m_pDib, m_dwLength, GHND); }else { m_pDib=(BYTE*) GlobalAllocPtr(GHND, m_dwLength); } } CATCH (CMemoryException, e) { AfxMessageBox("Unable to allocate DIB memory"); return *this; } END_CATCH memcpy(m_pDib,img.m_pDib,m_dwLength); m_pData = (BYTE*)((BYTE*) m_pDib + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * img.NumColors()); }else { GlobalFree(m_pDib); m_pDib=0; } if(m_pPal) delete m_pPal; m_pPal=new CPalette; CreateDIBPalette(); return *this; } /////////////////////////////////////////////////////////////////// CImage::~CImage() { if(m_dwLength != 0L) GlobalFreePtr(m_pDib); // free the DIB memory if(m_pPal) delete m_pPal; } /////////////////////////////////////////////////////////////////// void CImage::Serialize(CArchive& ar) { ar.Flush(); if (ar.IsStoring()) { WriteToFile(ar.GetFile()); } else { ReadFromFile(ar.GetFile()); } } /////////////////////////////////////////////////////////////////// BOOL CImage::WriteAsBMP(CFile* pFile) { Dib(); BITMAPFILEHEADER bmfHdr; // Header for Bitmap file LPBITMAPINFOHEADER pBMIH=BMInfoHdPtr(); // Pointer to DIB info structure if (m_pDib == NULL) return FALSE; /* Fill in file type (first 2 bytes must be "BM" for a bitmap) */ bmfHdr.bfType = 0x4d42; // "BM" // Calculate the file size by adding the DIB size to sizeof(BITMAPFILEHEADER) bmfHdr.bfSize = m_dwLength + sizeof(BITMAPFILEHEADER); bmfHdr.bfReserved1 = 0; bmfHdr.bfReserved2 = 0; bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + pBMIH->biSize + NumColors()*sizeof(RGBQUAD); WORD hdLength=sizeof(BITMAPINFOHEADER) + NumColors()*sizeof(RGBQUAD); TRY { // Write the file header pFile->Write((BYTE*)&bmfHdr, sizeof(BITMAPFILEHEADER)); // Write the DIB header pFile->Write(m_pDib, hdLength); // Write the DIB bits pFile->Write(m_pData, m_dwLength-hdLength); } CATCH (CFileException, e) { AfxMessageBox("Write error--possible disk full condition"); return FALSE; } END_CATCH return TRUE; } /////////////////////////////////////////////////////////////////// /* The MakeBitmap() CDC* pDoc : Device Context bmSize : Change the parameter and return it Function: Replaces the DC's old existing bitmap with the new one construced from this DIB Return Value: the old bitmap in DC */ //////////////////////////////////////////////////////// CBitmap* CImage::MakeBitmap(CDC* pDC, CSize& bmSize) { BITMAP bm; DWORD dwFore, dwBack; LPBITMAPINFOHEADER pBMIH = BMInfoHdPtr(); LPBITMAPINFO pBMI = BMInfoPtr(); // checks to see whether DIB buffer is properly loaded if (m_dwLength == 0L) { bmSize.cx = bmSize.cy = 0; return NULL; } // this code conditions the DC for mono or color SetPalette(pDC); int nPlanes = pDC->GetDeviceCaps(PLANES); int nBitsPixel = pDC->GetDeviceCaps(BITSPIXEL); CBitmap* pConfigBitmap = new CBitmap; char bits[100]; if (pBMIH->biBitCount == 1) { pConfigBitmap->CreateBitmap(1, 1, 1, 1, bits); } else { pConfigBitmap->CreateBitmap(1, 1, nPlanes, nBitsPixel, bits); } CBitmap* pOriginalBitmap = (CBitmap*) pDC->SelectObject(pConfigBitmap); // CreateDIBitmap "switches bits" for mono bitmaps, depending on colors, // so we'll fool it if (GetMonoColors(dwFore, dwBack)) { SetMonoColors(0L, 0xFFFFFFL); } //the following CreateDIBitmap() creates a DDB from this DIB //#ifdef _WIN32 HBITMAP hBitmap = ::CreateDIBitmap(pDC->GetSafeHdc(), pBMIH, CBM_INIT, (CONST BYTE*) m_pData, pBMI, DIB_RGB_COLORS); //#else // HBITMAP hBitmap = ::CreateDIBitmap(pDC->GetSafeHdc(), pBMIH, // CBM_INIT, (BYTE*) m_pData, pBMI, DIB_RGB_COLORS); //#endif if (hBitmap == NULL) { TRACE("null bitmap\n"); delete pDC->SelectObject(pOriginalBitmap); // delete config bitmap return NULL; // untested error logic } SetMonoColors(dwFore, dwBack); // Can't use CBitmap::FromHandle here because we need to // delete the object later CBitmap* pBitmap = new CBitmap; pBitmap->Attach(hBitmap); pBitmap->GetObject(sizeof(bm), &bm); bmSize.cx = bm.bmWidth; bmSize.cy = bm.bmHeight; delete pDC->SelectObject(pBitmap); // delete configuration bitmap return pOriginalBitmap; } /////////////////////////////////////////////////////////////////// //create a DIBpalette according to the palette info in the inforhead of object BOOL CImage::CreateDIBPalette() { LPLOGPALETTE lpPal; // pointer to a logical palette LPBITMAPINFO pBMI = BMInfoPtr(); int i; // loop index WORD wNumColors; // number of colors in color table BOOL bResult=FALSE; /* if handle to DIB is invalid, return FALSE */ if (!m_pDib) return FALSE; /* get the number of colors in the DIB */ Dib(); wNumColors = NumColors(); if (wNumColors != 0) { /* allocate memory block for logical palette */ /* if not enough memory, clean up and return NULL */ lpPal = (LPLOGPALETTE) GlobalAllocPtr(GHND, sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * wNumColors); if (lpPal == 0) return FALSE; /* set version and number of palette entries */ lpPal->palVersion = 0x300; lpPal->palNumEntries = wNumColors; for (i = 0; i < (int)wNumColors; i++) { lpPal->palPalEntry[i].peRed = pBMI->bmiColors[i].rgbRed; lpPal->palPalEntry[i].peGreen = pBMI->bmiColors[i].rgbGreen; lpPal->palPalEntry[i].peBlue = pBMI->bmiColors[i].rgbBlue; lpPal->palPalEntry[i].peFlags = 0; } /* create the palette and get handle to it */ if(m_pPal)delete m_pPal; m_pPal=new CPalette; bResult = m_pPal->CreatePalette(lpPal); GlobalFreePtr(lpPal); } return bResult; } BOOL CImage::GetColorImage(BYTE* pData,DWORD dwWidth,DWORD dwHeight) { ImageClear(); LPBITMAPINFOHEADER pBMIH; //make the number of bytes in one line can be divided exactly by 4 DWORD dwBytes = Transform(dwWidth);//bytes per line DWORD dwDataLength = dwBytes*dwHeight*3; m_dwLength =dwDataLength+sizeof(BITMAPINFOHEADER) +sizeof(RGBQUAD) * 0; if (!AllocateMemory()) { return FALSE; } pBMIH=BMInfoHdPtr(); pBMIH->biSize = sizeof(BITMAPINFOHEADER); pBMIH->biWidth = dwWidth; pBMIH->biHeight = dwHeight; pBMIH->biPlanes = 1; pBMIH->biBitCount = 24; pBMIH->biCompression = BI_RGB; pBMIH->biSizeImage = 0; pBMIH->biXPelsPerMeter = 0; pBMIH->biYPelsPerMeter = 0; pBMIH->biClrUsed = 0; pBMIH->biClrImportant = 0; m_pData = (BYTE*) m_pDib + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * NumColors(); CreateGreyPalette(); TRY { memcpy(m_pData,pData,dwDataLength); } CATCH (CFileException, e) { AfxMessageBox("Data transfer error!"); GlobalFreePtr(m_pDib); // free the DIB memory return FALSE; } END_CATCH SetDIB(FALSE); Dib(); return TRUE; } /////////////////////////////////////////////////////////////////// BOOL CImage::CreateGreyPalette() { LPLOGPALETTE lpPal; // pointer to a logical palette LPBITMAPINFO pBMI = BMInfoPtr(); HANDLE hLogPal; // handle to a logical palette int i; // loop index WORD wNumColors=NumColors(); // number of colors in color table BOOL bResult=FALSE; /* allocate memory block for logical palette */ hLogPal = ::GlobalAlloc(GHND, sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * wNumColors); /* if not enough memory, clean up and return NULL */ if (hLogPal == 0) return FALSE; lpPal = (LPLOGPALETTE) ::GlobalLock((HGLOBAL) hLogPal); /* set version and number of palette entries */ lpPal->palVersion = 0x300; lpPal->palNumEntries = wNumColors; //set the grey value of palette for (i = 0; i < (int)wNumColors; i++) { lpPal->palPalEntry[i].peRed = i; lpPal->palPalEntry[i].peGreen = i; lpPal->palPalEntry[i].peBlue = i; lpPal->palPalEntry[i].peFlags = 0; pBMI->bmiColors[i].rgbRed=i; pBMI->bmiColors[i].rgbGreen=i; pBMI->bmiColors[i].rgbBlue=i; } /* create the palette and get handle to it */ if(m_pPal)delete m_pPal; m_pPal=new CPalette; bResult = m_pPal->CreatePalette(lpPal); ::GlobalUnlock((HGLOBAL) hLogPal); ::GlobalFree((HGLOBAL) hLogPal); return bResult; } /////////////////////////////////////////////////////////////////// //create a grey DIB according to the color bmp //and creat a grey palette according to the //inforhead of the color bmp BOOL CImage::CreateGreyDib() { BYTE y[256]; WORD i, j, w, h; DWORD dwL; BOOL bResult = FALSE; LPBITMAPINFO pBMI; if ( !m_pDib ) return FALSE; w = Width(); h = Height(); dwL = w * h; pBMI = BMInfoPtr(); switch(Bits()) { case 8: { Data(); for (i = 0; i < NumColors() ; i++) { y[i] = (BYTE)( float( pBMI->bmiColors[i] . rgbRed) * 0.3 + float( pBMI->bmiColors[i] . rgbGreen)* 0.59 + float( pBMI->bmiColors[i] . rgbBlue) * 0.11); if(y[i] > 255) y[i] = 255; } CreateGreyPalette(); for(DWORD d=0 ; d Data(); for(i=0; i GetSafeHdc(), origin.x, origin.y, (WORD) pBMIH->biWidth, (WORD) pBMIH->biHeight, 0, 0, 0, (WORD) pBMIH->biHeight, m_pData, pBMI, DIB_RGB_COLORS)) { return FALSE; } return TRUE; } /////////////////////////////////////////////////////////////////// BOOL CImage::Stretch(CDC* pDC, CPoint origin, CSize size) const { // direct to device--bypass the GDI bitmap LPBITMAPINFOHEADER pBMIH = BMInfoHdPtr(); LPBITMAPINFO pBMI = BMInfoPtr(); if (!m_pDib) { return FALSE; // nothing to display } if (!::StretchDIBits(pDC->GetSafeHdc(), origin.x, origin.y, size.cx, size.cy, 0, 0, (WORD) pBMIH->biWidth, (WORD) pBMIH->biHeight, m_pData, pBMI, DIB_RGB_COLORS, SRCCOPY)) { return FALSE; } return TRUE; } /////////////////////////////////////////////////////////////////// WORD CImage::Bits() const { ASSERT(m_pDib); return ((LPBITMAPINFOHEADER)m_pDib)->biBitCount; } /////////////////////////////////////////////////////////////////// DWORD CImage::Length() const { return m_dwLength; } /////////////////////////////////////////////////////////////////// CSize CImage::Size() const { ASSERT(m_pDib); LPBITMAPINFOHEADER pBMIH = BMInfoHdPtr(); return CSize((int) pBMIH->biWidth, (int) pBMIH->biHeight); } /////////////////////////////////////////////////////////////////// WORD CImage::Height() const { ASSERT(m_pDib); return (WORD)(((LPBITMAPINFOHEADER)m_pDib)->biHeight); } /////////////////////////////////////////////////////////////////// WORD CImage::Width() const { ASSERT(m_pDib); return (WORD) (((LPBITMAPINFOHEADER)m_pDib)->biWidth); } /////////////////////////////////////////////////////////////////// //return the number of entries in the color pallete WORD CImage::NumColors() const { ASSERT(m_pDib); LPBITMAPINFOHEADER pBMIH = BMInfoHdPtr(); if(m_pDib==NULL) return NULL; if(pBMIH->biClrUsed!=0) return (WORD)pBMIH->biClrUsed; switch(pBMIH->biBitCount) { case 1: return 2; case 4: return 16; case 8: return 256; default: return 0; } } /////////////////////////////////////////////////////////////////// LPBITMAPINFOHEADER CImage::BMInfoHdPtr() const { return (LPBITMAPINFOHEADER)m_pDib; } /////////////////////////////////////////////////////////////////// LPBITMAPINFO CImage::BMInfoPtr() const { return (LPBITMAPINFO)m_pDib; } /////////////////////////////////////////////////////////////////// RGBQUAD* CImage::BMColorTblPtr() const { return (RGBQUAD*)((int)m_pDib+sizeof(BITMAPINFOHEADER)); } /////////////////////////////////////////////////////////////////// void CImage::SetDIB(BOOL Flag) { if(Flag) m_bIsDIB=TRUE; else m_bIsDIB=FALSE; } /////////////////////////////////////////////////////////////////// // To convert the non-DIB to DIB type BYTE* CImage::Dib() { if(!m_pDib) return NULL; if(m_bIsDIB) return m_pData; WORD i, j; BYTE *p1, *p2; WORD bpp = Bits(); WORD bytepp = bpp / 8; WORD w = Width(); WORD h = Height(); long lBpl = w * bytepp; WORD halfline = h / 2; //reverse the order of scanning //for(i=0 ; i 0; i--) { p1 = m_pData + i * dwBNFOL; p2 = m_pData + i * lBpl; memmove(p1, p2, lBpl); memset(p1+lBpl, 0x00, (dwBNFOL - lBpl)); } SetDIB(); return m_pData; } ///////////////////////////////////////// //implement the reverse function of dib() BYTE* CImage::Data() { if(!m_pDib) return NULL; if(!m_bIsDIB) return m_pData; WORD i,j; BYTE *p1, *p2; WORD bpp = Bits();//bpp WORD Bytepp = bpp / 8; WORD w = Width(); WORD h = Height(); WORD halfline= h/2; LPBITMAPINFOHEADER pBMIH = BMInfoHdPtr( ); if(pBMIH->biCompression!=BI_RGB) { AfxMessageBox("Con't process compressed image"); return NULL; } if((w * bpp) % 32) { long t = w * Bytepp; DWORD dwBNFOL = ByteNumForOneLine(w, bpp); p2 = p1 = m_pData; for(i=0; i m_hObject) return FALSE; VERIFY(pDC->SelectPalette(m_pPal,bBackground)); return(pDC->RealizePalette()); } /////////////////////////////////////////////////////////////////// void CImage::SetMonoColors(DWORD dwForeground, DWORD dwBackground) { if (Bits() != 1) { return; } unsigned long far* pPalette = (unsigned long far*) BMColorTblPtr(); *pPalette = dwForeground; *(++pPalette) = dwBackground; return; } /////////////////////////////////////////////////////////////////// BOOL CImage::GetMonoColors(DWORD& dwForeground, DWORD& dwBackground) { if (Bits() != 1) { return FALSE; } unsigned long far* pPalette = (unsigned long far*) BMColorTblPtr(); dwForeground = *pPalette; dwBackground = *(++pPalette); return TRUE; } /////////////////////////////////////////////////////////////////// BOOL CImage::AllocateMemory(BOOL bRealloc) // bRealloc default = FALSE { if (bRealloc) { m_pDib = (BYTE*) GlobalReAllocPtr(m_pDib, m_dwLength, GHND); } else { m_pDib = (BYTE*) GlobalAllocPtr(GHND, m_dwLength); } if (!m_pDib) { AfxMessageBox("Unable to allocate DIB memory"); m_dwLength = 0L; return FALSE; } return TRUE; } /*Record of Modify * Date Operator Modify * 1999.4.9 S.S.G if the width of the bitmap can not be inter-divided by 8 * We must alloc enough additional memory!! and some situations * must be processed */ BOOL CImage::ReadFromBMP(CFile * pFile) { BITMAPFILEHEADER bmfHdr; // Header for Bitmap file BITMAPINFOHEADER bmhdr; //header for bitmap info long biWidth; long biHeight; ASSERT(m_dwLength == 0L); // DIB must be empty if ((pFile->Read((BYTE*)&bmfHdr, sizeof(bmfHdr)) != sizeof(bmfHdr))) { AfxMessageBox("Read error"); return FALSE; } if (bmfHdr.bfType != 0x4d42) { AfxMessageBox("Invalid bitmap file"); return FALSE; } //1999.4.9 added if ((pFile->Read((BYTE*)&bmhdr, sizeof(bmhdr)) != sizeof(bmhdr))) { AfxMessageBox("Read error"); return FALSE; } if(bmhdr.biSize != sizeof(bmhdr)) { AfxMessageBox("Invalid bitmap file"); return FALSE; } if(bmhdr.biBitCount == 16 && bmhdr.biBitCount == 32) { AfxMessageBox("Sorry! Current version only support\n 8bpp and 24bpp BMP!"); return FALSE; } if(bmhdr.biCompression != BI_RGB ) { AfxMessageBox("Sorry! Current version do NOT support\n compressed BMP!"); return FALSE; } biWidth = bmhdr.biWidth; biHeight= abs(bmhdr.biHeight); DWORD dwBytes = ByteNumForOneLine(biWidth, bmhdr.biBitCount); //->| m_dwLength = pFile->GetLength(); m_dwLength -= sizeof(BITMAPFILEHEADER); /*1999.4.9 added the following line*/ //add the needed extent memory!!! m_dwLength += (dwBytes - (bmhdr.biBitCount / 8) * bmhdr.biWidth) * bmhdr.biHeight; if (!AllocateMemory()) { return FALSE; } pFile->Seek(sizeof(BITMAPFILEHEADER), CFile::begin); TRY { pFile->Read(m_pDib, m_dwLength); } CATCH (CFileException, e) { AfxMessageBox("Read error"); GlobalFreePtr(m_pDib); // free the DIB memory return FALSE; } END_CATCH m_pData = (BYTE*) m_pDib + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * NumColors(); CreateDIBPalette(); SetDIB(); return TRUE; } BOOL CImage::ReadFromPGM(CFile * pFile) { // file assumed to be open LPBITMAPINFOHEADER pBMIH; char ch; WORD w, h, i=0, j=0; char str[10]; CString sfilehead; ASSERT(m_dwLength == 0); DWORD dwFileLength = pFile->GetLength(); DWORD dwDataPos=0; pFile->Seek(0,CFile::begin); TRY { pFile->Read(sfilehead.GetBuffer(30), 30); } CATCH (CFileException, e) { AfxMessageBox("Read error"); return FALSE; } END_CATCH sfilehead.ReleaseBuffer(); if(sfilehead == "") { AfxMessageBox("Invalid PGM image file"); return false; } if(sfilehead.GetAt(0) != 'P'||sfilehead.GetAt(1) != '5') { AfxMessageBox("Invalid PGM image file"); return false; } int tt = 0; dwDataPos = 0; while(tt != 3) { if(sfilehead.GetAt(dwDataPos) == '\n') tt++; dwDataPos++; if(dwDataPos > 30) { AfxMessageBox("The format is wrong!"); return false; } } dwFileLength -= dwDataPos; i=0; ch=sfilehead.GetAt(i++); while(ch!='\n') ch=sfilehead.GetAt(i++); j=0; ch=sfilehead.GetAt(i++); while(ch!=' ') { str[j++]=ch; ch=sfilehead.GetAt(i++);} str[j]='\0'; w=atoi(str); j=0; ch=sfilehead.GetAt(i++); while(ch!='\n') {str[j++]=ch; ch=sfilehead.GetAt(i++);} str[j]='\0'; h=atoi(str); if( DWORD(w*h) > dwFileLength) { AfxMessageBox("w*h != DataLength, The image data is wrong!"); return false; } //make the number of bytes in one line can be divided exactly by 4 DWORD dwBytes = Transform(w);//bytes per line m_dwLength = DWORD(dwBytes * h) + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256; if (!AllocateMemory()) { AfxMessageBox("Allocmemory Error"); return FALSE;} pBMIH=BMInfoHdPtr(); pBMIH->biSize = sizeof(BITMAPINFOHEADER); pBMIH->biWidth = w; pBMIH->biHeight = h; pBMIH->biPlanes = 1; pBMIH->biBitCount = 8; pBMIH->biCompression = BI_RGB; pBMIH->biSizeImage = 0; pBMIH->biXPelsPerMeter = 0; pBMIH->biYPelsPerMeter = 0; pBMIH->biClrUsed = 0; pBMIH->biClrImportant = 0; m_pData = (BYTE*) m_pDib + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * NumColors(); pFile->Seek(dwDataPos/*+1 980518 modified!!*/,CFile::begin); long dd; TRY { dd = pFile->Read(m_pData, DWORD(w * h)); //pFile->Read(m_pData, dwFileLength); } CATCH (CFileException, e) { AfxMessageBox("Read error"); GlobalFreePtr(m_pDib); // free the DIB memory return FALSE; } END_CATCH CreateGreyPalette(); SetDIB(FALSE); Dib(); return TRUE; } BOOL CImage::WriteAsPGM(CFile * pFile) { WORD w, h; char cWidth[5]; char cHeight[5]; char* PgmHead = new char[30]; Data(); strcpy(PgmHead, "P5\n"); if (m_pDib == NULL) return FALSE; if(Bits() != 8) { AfxMessageBox("It is not 8-greylevel image!"); return false; } w = Width(); h = Height(); itoa(w,cWidth,10); itoa(h,cHeight,10); strcat(PgmHead,cWidth); strcat(PgmHead," "); strcat(PgmHead,cHeight); strcat(PgmHead,"\n255\n"); // Calculate the file size by adding the DIB size to sizeof(BITMAPFILEHEADER) WORD hdLength = sizeof(BITMAPINFOHEADER) + NumColors()*sizeof(RGBQUAD); TRY { pFile->Write(PgmHead,strlen(PgmHead)); pFile->Write(m_pData, (long)w*h); } CATCH (CFileException, e) { AfxMessageBox("Write error--possible disk full condition"); return FALSE; } END_CATCH Dib(); delete PgmHead; return TRUE; } BOOL CImage::WriteAsData(CFile* pFile) { WORD w = Width(); WORD h = Height(); BYTE* pData = Data(); TRY { pFile->Write(pData, (long)w*h); } CATCH (CFileException, e) { AfxMessageBox("Write error--possible disk full condition"); return FALSE; } END_CATCH Dib(); return TRUE; } BOOL CImage::ReadFromFile(CFile * pFile) { BOOL bReturn; CString FileName=pFile->GetFilePath(); m_strFileName = FileName; int nPointPos=FileName.Find("."); FileName.MakeLower(); FileName=FileName.Mid(nPointPos+1); bReturn = FALSE; if(FileName=="bmp") return ReadFromBMP(pFile); if(FileName=="pgm") return ReadFromPGM(pFile); if(FileName == "img") return ReadFromIMG(pFile); if(FileName == "dat") return ReadFromDAT(pFile); if(ReadFromPGM(pFile)) return TRUE; return FALSE; } BOOL CImage::ReadFromFile(CString filename) { /* * * CString ext = filename; int nPointPos=ext.Find("."); ext.MakeLower(); ext=ext.Mid(nPointPos+1); */ CFile* pFile = new CFile(); //CFileException e; LPCTSTR file_name = filename; if(!pFile->Open(file_name,CFile::modeRead)) { AfxMessageBox("In CImage::ReadFromFile(),Can not opent the file!"); return false; } //pFile->Open(filename,CFile::modeRead); BOOL b = ReadFromFile(pFile); pFile->Close(); delete pFile; return b; } BOOL CImage::WriteToFile(CFile * pFile) { CString FileName=pFile->GetFileName(); int nPointPos=FileName.Find("."); FileName.MakeLower(); FileName=FileName.Mid(nPointPos+1); if(FileName=="bmp") return WriteAsBMP(pFile); if(FileName=="pgm") return WriteAsPGM(pFile); if(FileName=="bin") return WriteAsData(pFile); if(FileName=="txt") { CString temp = pFile->GetFilePath(); pFile -> Close(); BOOL b = SaveAsText(temp, FALSE); pFile -> Open(temp, CFile::modeWrite); return b; } return WriteAsPGM(pFile); } BOOL CImage::WriteToFile(CString filename) { CFile* pFile = new CFile; if(!pFile->Open(filename,CFile::modeWrite|CFile::modeCreate)) { AfxMessageBox("In CImage::WriteToFile(),Can not opent the file!"); return false; } BOOL b = WriteToFile(pFile); pFile->Close(); delete pFile; return b; } void CImage::ImageClear() { if (m_pDib) GlobalFreePtr(m_pDib); // free the DIB memory m_pDib = NULL; m_pData = NULL; m_pPal = NULL;// wr add m_bIsDIB = TRUE; m_dwLength = 0L; } DWORD CImage::Transform(WORD width) { DWORD dwBytes = (width * 8) / 32; if ((width * 8) % 32) { dwBytes ++; } dwBytes *= 4; //bytes per line return dwBytes; } BOOL CImage::ReadFromIMG(CFile* pFile) { int bpp; LPBITMAPINFOHEADER pBMIH; DWORD dwFileLength = pFile->GetLength(); WORD w,h; pFile->Read((WORD* )&w,sizeof(WORD)); pFile->Read((WORD* )&h,sizeof(WORD)); dwFileLength -= 2 * sizeof(WORD); bpp = int(dwFileLength / (w * h)); if(bpp != 1 && bpp != 3)/* 8 or 24 */ { AfxMessageBox("Wrong Data!"); return false; } DWORD dwBytes = Transform(w);//bytes per line m_dwLength = DWORD(dwBytes * h * bpp) + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256; if (!AllocateMemory()) { AfxMessageBox("Allocmemory Error"); return FALSE;} pBMIH=BMInfoHdPtr(); pBMIH->biSize = sizeof(BITMAPINFOHEADER); pBMIH->biWidth = w; pBMIH->biHeight = h; pBMIH->biPlanes = 1; pBMIH->biBitCount = 8 * bpp; pBMIH->biCompression = BI_RGB; pBMIH->biSizeImage = 0; pBMIH->biXPelsPerMeter = 0; pBMIH->biYPelsPerMeter = 0; pBMIH->biClrUsed = 0; pBMIH->biClrImportant = 0; m_pData = (BYTE*) m_pDib + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * NumColors(); CreateGreyPalette(); TRY { pFile->Read(m_pData, dwFileLength); } CATCH (CFileException, e) { AfxMessageBox("Read error"); GlobalFreePtr(m_pDib); // free the DIB memory return FALSE; } END_CATCH SetDIB(true); Dib(); return TRUE; } BOOL CImage::ReadFromDAT(CFile* pFile) { LPBITMAPINFOHEADER pBMIH; DWORD dwFileLength = pFile->GetLength(); WORD w,h; ///////just for MIT facebase!!! w = 256; h = 240; if(dwFileLength != (DWORD)(w * h)) { AfxMessageBox("Wrong Data!"); return false; } DWORD dwBytes = Transform(w);//bytes per line m_dwLength = DWORD(dwBytes * h) + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256; if (!AllocateMemory()) { AfxMessageBox("Allocmemory Error"); return FALSE;} pBMIH=BMInfoHdPtr(); pBMIH->biSize = sizeof(BITMAPINFOHEADER); pBMIH->biWidth = w; pBMIH->biHeight = h; pBMIH->biPlanes = 1; pBMIH->biBitCount = 8; pBMIH->biCompression = BI_RGB; pBMIH->biSizeImage = 0; pBMIH->biXPelsPerMeter = 0; pBMIH->biYPelsPerMeter = 0; pBMIH->biClrUsed = 0; pBMIH->biClrImportant = 0; m_pData = (BYTE*) m_pDib + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * NumColors(); CreateGreyPalette(); TRY { pFile->Read(m_pData, dwFileLength); } CATCH (CFileException, e) { AfxMessageBox("Read error"); GlobalFreePtr(m_pDib); // free the DIB memory return FALSE; } END_CATCH SetDIB(false); Dib(); return TRUE; } /////////////////the property of the image//////////////// BYTE CImage::Get8NeiborAver(BYTE* pGreyData, WORD w, WORD h, CPoint pos) { double temp; int x = pos.x; int y = pos.y; int t = y * w + x; if(x == 0 && y != 0) { temp = pGreyData[t-w] + pGreyData[t-w+1] + pGreyData[t+1] + pGreyData[t+w] + pGreyData[t+w+1]; temp /= 5; return (BYTE)temp; } if(x != 0 && y == 0) { temp = pGreyData[t-1] + pGreyData[t+1] + pGreyData[t+w-1] + pGreyData[t+w] + pGreyData[t+w+1]; temp /= 5; return (BYTE)temp; } if(x == 0 && y != 0) { temp = pGreyData[t+1] + pGreyData[t+w] + pGreyData[t+w+1]; temp /= 3; return (BYTE)temp; } if(x == w-1 && y != h-1) { temp = pGreyData[t-w-1] + pGreyData[t-w] + pGreyData[t-1] + pGreyData[t+w-1] + pGreyData[t+w]; temp /= 5; return (BYTE)temp; } if(x != w-1 && y == h-1) { temp = pGreyData[t-w-1] + pGreyData[t-w] + pGreyData[t-w+1] + pGreyData[t-1] + pGreyData[t+1]; temp /= 5; return (BYTE)temp; } if(x = w-1 && y == h-1) { temp = pGreyData[t-w-1] + pGreyData[t-w] + pGreyData[t-1]; temp /= 3; return (BYTE)temp; } temp = pGreyData[t-w-1] + pGreyData[t-w] + pGreyData[t-w+1] + pGreyData[t-1] + pGreyData[t+1] + pGreyData[t+w-1] + pGreyData[t+w] + pGreyData[t+w+1]; temp /= 8; return (BYTE)temp; } DWORD CImage::ByteNumForOneLine(WORD nDIBWidth, int nBpp) { DWORD dwBytes = (nDIBWidth * nBpp) / 32; if ((nDIBWidth * nBpp) % 32) dwBytes ++; dwBytes *= 4;//bytes per line return dwBytes; } /////////////////////////////////////////////// /* * SSG, 1999.6. 2 * Save the data as text */ /////////////////////////////////////////////// BOOL CImage::SaveAsText(CString filename, BOOL bIsBinary) { int w; long l, size; char buf[20]; CFile f; BYTE *pData; pData = Data(); if (m_pDib == NULL) return FALSE; if(Bits() != 8) { AfxMessageBox("It is not 8-greylevel image!"); return false; } w = Width(); size = w * Height(); f.Open(filename, CFile::modeCreate | CFile::modeWrite ); if(bIsBinary) { for(l=0; l = (DWORD)(scrW * scrH)) break; sum += scrImage[scrOff + n]; num++; } } if(num!=0) destImage[destOff + j] = (BYTE)(sum / num); else destImage[destOff + j] = (BYTE)sum; } } } //////////////////////////////////////////////////////////////////////// //author: ssg //Modified version based on the one from Liu Ming Bao //Para1: BYTE* image: the source image data poiter //Para2: BYTE* rimage: the resulting image data poiter //Para3,4: int w, h: source image's width and height in pixel //para5: float cscale: the scale to shrink ////////////////////////////////////////////////////////////////////////// void CImage::ShrinkImage(BYTE *scrImage, BYTE* destImage, WORD w, WORD h, float cscale) { DWORD i, j, m, n, scrOff, destOff, destw, desth; DWORD num,sum; double step_w, step_h,tm, tn; destw = (WORD) (w * cscale); desth = (WORD) (h * cscale); step_w = (double)w / destw; step_h = (double)h / desth; for (i=0; i < desth; i++) { tm=i*step_h; destOff = destw * i; for (j=0; j < destw; j++) { sum=0; num = 0; tn=j*step_w; for (m = (WORD)tm + 1; m <= (WORD)(tm + step_h); m++) { scrOff=w*m; for (n = (WORD)tn + 1; n <= (WORD)(tn + step_w); n++) { sum += scrImage[scrOff+n]; if(scrOff >= (DWORD)(w * h)) break; num++; } } if(num!=0) destImage[destOff + j] = (BYTE)(sum/num); else destImage[destOff + j]=(BYTE)sum; } } }