www.pudn.com > pccode_2006910124551680.rar > Bmpfile.cpp


//	bmpops.cpp : implementation of the BMPFile class 
//	 
//	This handles the reading and writing of BMP files. 
// 
// 
 
#include "stdafx.h" 
#include "bmpfile.h" 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
 
BMPFile::BMPFile() 
{ 
	m_errorText="OK"; 
} 
 
BMPFile::~BMPFile() 
{ 
 
} 
 
//////////////////////////////////////////////////////////////////////////// 
//	write a 24-bit BMP file 
// 
//	image MUST be a packed buffer (DWORD-aligned) 
void BMPFile::SaveBMP(CString fileName,		// output path 
							BYTE * buf,				// BGR buffer 
							int width,				// pixels 
							int height) 
{ 
	short res1=0; 
    short res2=0; 
    long pixoff=54; 
    long compression=0; 
    long cmpsize=0; 
    long colors=0; 
    long impcol=0; 
	char m1='B'; 
	char m2='M'; 
 
	m_errorText="OK"; 
 
	int imagesize=(width*24+31)/32*4*height; 
 
	long bmfsize=sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 
  							imagesize;	 
	long byteswritten=0; 
 
	BITMAPINFOHEADER header; 
  	header.biSize=40; 						// header size 
	header.biWidth=width; 
	header.biHeight=height; 
	header.biPlanes=1; 
	header.biBitCount=24;					// RGB encoded, 24 bit 
	header.biCompression=BI_RGB;			// no compression 
	header.biSizeImage=0; 
	header.biXPelsPerMeter=0; 
	header.biYPelsPerMeter=0; 
	header.biClrUsed=0; 
	header.biClrImportant=0; 
 
	FILE *fp;	 
	fp=fopen(fileName,"wb");//写文件到磁盘 
	if (fp==NULL) { 
		m_errorText="Can't open file for writing"; 
		return; 
	} 
 
	// should probably check for write errors here... 
	 
	fwrite((BYTE  *)&(m1),1,1,fp); byteswritten+=1; 
	fwrite((BYTE  *)&(m2),1,1,fp); byteswritten+=1; 
	fwrite((long  *)&(bmfsize),4,1,fp);	byteswritten+=4; 
	fwrite((int  *)&(res1),2,1,fp); byteswritten+=2; 
	fwrite((int  *)&(res2),2,1,fp); byteswritten+=2; 
	fwrite((long  *)&(pixoff),4,1,fp); byteswritten+=4; 
 
	fwrite((BITMAPINFOHEADER *)&header,sizeof(BITMAPINFOHEADER),1,fp); 
	byteswritten+=sizeof(BITMAPINFOHEADER); 
	 
	int r=fwrite(buf,imagesize,1,fp); // buf is double word aligned. 
	if(r=-1){ 
		m_errorText="Write image data failed!"; 
	} 
 
	fclose(fp); 
} 
 
 
//////////////////////////////////////////////////////////////////////////////////// 
// 
//	1,4,8 bit BMP stuff 
// 
//	if you have a color-mapped image and a color map... 
// 
//	the BMP saving code in SaveColorMappedBMP modified from Programming  
//	for Graphics Files in C and C++, by John Levine. 
 
void BMPFile::SaveBMP(CString fileName, 			// output path 
					  BYTE * colormappedbuffer,	// one BYTE per pixel colormapped image 
					  int width, 
					  int height, 
 					  int bitsperpixel,			// 1, 4, 8 
					  int colors,				// number of colors (number of RGBQUADs) 
					  RGBQUAD *colormap)			// array of RGBQUADs  
{ 
	if(colormap==NULL) 
		return; 
	if(colormappedbuffer==NULL) 
		return; 
 
	int datasize, cmapsize, byteswritten, row, col; 
 
	m_errorText="OK"; 
 
	if (bitsperpixel == 24) { 
		// the routines could be combined, but i don't feel like it 
		m_errorText="We don't do 24-bit files in here, sorry"; 
		return; 
	} else 
		cmapsize = colors * 4; 
 
	datasize = BMP_PIXELSIZE(width, height, bitsperpixel); 
 
	long filesize = BMP_HEADERSIZE + cmapsize + datasize; 
	int res1, res2; 
	res1 = res2 = 0; 
 
	long pixeloffset = BMP_HEADERSIZE + cmapsize; 
 
	int bmisize = 40; 
	long cols = width; 
	long rows = height; 
	WORD planes = 1; 
	long compression =0; 
	long cmpsize = datasize; 
	long xscale = 0; 
	long yscale = 0; 
	long impcolors = colors; 
 
	FILE *fp; 
	fp = fopen(fileName, "wb"); 
	if (fp==NULL) { 
		m_errorText="Can't Open"; 
		return; 
	} 
	char bm[2]; 
	bm[0]='B'; 
	bm[1]='M'; 
 
	// header stuff 
	BITMAPFILEHEADER bmfh; 
	bmfh.bfType=*(WORD *)&bm;  
    bmfh.bfSize= filesize;  
    bmfh.bfReserved1=0;  
    bmfh.bfReserved2=0;  
    bmfh.bfOffBits=pixeloffset;  
 
	fwrite(&bmfh, sizeof (BITMAPFILEHEADER), 1, fp); 
 
 
	BITMAPINFOHEADER bmih; 
	bmih.biSize = bmisize;  
	bmih.biWidth = cols;  
	bmih.biHeight = rows;  
	bmih.biPlanes = planes;  
	bmih.biBitCount =bitsperpixel; 
	bmih.biCompression = compression;  
	bmih.biSizeImage = cmpsize;  
	bmih.biXPelsPerMeter = xscale;  
	bmih.biYPelsPerMeter = yscale;  
	bmih.biClrUsed = colors; 
	bmih.biClrImportant = impcolors; 
	 
	fwrite(&bmih, sizeof (BITMAPINFOHEADER), 1, fp); 
 
	if (cmapsize) { 
		int i; 
		for (i = 0; i< colors; i++) { 
			// following was modified by Yejiaming, USTC. May 30,2002 
			fwrite(&colormap[i],sizeof(RGBQUAD),1,fp); 
//			putc(colormap[i].rgbRed, fp); 
//			putc(colormap[i].rgbGreen, fp); 
//			putc(colormap[i].rgbBlue, fp); 
//			putc(0, fp);	// dummy 
		} 
	} 
 
	byteswritten = BMP_HEADERSIZE + cmapsize; 
 
	for (row = 0; row< (int)height; row++) { 
		int pixbuf=0; 
		int nbits = 0; 
 
		for (col =0 ; col < (int)width; col++) { 
			int offset = row * width + col;	// offset into our color-mapped RGB buffer 
			BYTE pval = *(colormappedbuffer + offset); 
 
			pixbuf = (pixbuf << bitsperpixel) | pval; 
 
			nbits += bitsperpixel; 
 
			if (nbits > 8) { 
				m_errorText="Error : nBits > 8????"; 
				fclose(fp); 
				return; 
			} 
 
			if (nbits == 8) { 
				putc(pixbuf, fp); 
				pixbuf=0; 
				nbits=0; 
				byteswritten++; 
			} 
		} // cols 
 
		if (nbits > 0) { 
			// the following one sentence was added by Yejiaming, USTC. May 30,2002 
			pixbuf=pixbuf << (8-nbits); 
			putc(pixbuf, fp);		// write partially filled byte 
			byteswritten++; 
		} 
 
		// DWORD align 
		while ((byteswritten -pixeloffset) & 3) { 
			putc(0, fp); 
			byteswritten++; 
		} 
 
	}	//rows 
 
	if (byteswritten!=filesize) { 
		m_errorText="byteswritten != filesize"; 
	} 
 
	fclose(fp); 
} 
 
// Following functions was added by Yejiaming,USTC. 2001.10 
 
void BMPFile::DisplayBMP(CDC* pDC, BYTE *buffer, int width, int height, int x, int y, int dstWidth, int dstHeight) 
{ 
	if(pDC==NULL)  
		return; 
	if(buffer==NULL) 
		return; 
	BITMAPINFOHEADER bmiHeader; 
	bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 
	bmiHeader.biWidth = width; 
	bmiHeader.biHeight = height; 
	bmiHeader.biPlanes = 1; 
	bmiHeader.biBitCount = 24; 
	bmiHeader.biCompression = BI_RGB; 
	bmiHeader.biSizeImage = 0; 
	bmiHeader.biXPelsPerMeter = 0; 
	bmiHeader.biYPelsPerMeter = 0; 
	bmiHeader.biClrUsed = 0; 
	bmiHeader.biClrImportant = 0; 
 
	pDC->SetStretchBltMode(COLORONCOLOR); 
	StretchDIBits(pDC->m_hDC, 
	    		  x,y, 
				  dstWidth, 
				  dstHeight, 
				  0,0, 
				  bmiHeader.biWidth, 
				  bmiHeader.biHeight, 
				  buffer, 
				  (LPBITMAPINFO)&bmiHeader, 
				  DIB_RGB_COLORS, 
				  SRCCOPY);  
 
} 
 
void BMPFile::RGB2Gray(int width, int height, BYTE *pInput, BYTE *pOutput) 
{ 
	if(pInput==NULL) 
		return; 
	int widthbytes=(width*24+31)/32*4; 
	int row,col,rowoff,coloff,step=0; 
	BYTE bb,gg,rr; 
	for(row=0;row>7); 
			step++; 
		} 
	} 
} 
 
void BMPFile::Gray2RGB(int width, int height, BYTE *pInput, BYTE *pOutput) 
{ 
	if(pInput==NULL) 
		return; 
	int widthbytes=(width*24+31)/32*4; 
	int row,col,rowoff,coloff,step=0; 
	BYTE tmpGray; 
	for(row=0;rowbiCompression!=BI_RGB){ 
		m_errorText="This is a compressed iamge! Ignore it!"; 
		delete [] pBMIH; 
		pBMIH=NULL; 
		fclose(pFile); 
		return NULL; 
	} 
 
	// 输出 
	width=pBMIH->biWidth; 
	height=pBMIH->biHeight; 
	bitcount=pBMIH->biBitCount; 
	widthbytes=(width*24+31)/32*4;// 输出为24位图像数据,double word aligned! 
 
 
	// 读取图像数据,每行以四字节为边界 
	int widthbytes1=(width*bitcount+31)/32*4; 
	int imagesize=widthbytes1*height; 
	LPBYTE pData=new BYTE[imagesize]; 
	if(!pData){ 
		m_errorText="Allocate memory failed!"; 
		delete [] pBMIH; 
		pBMIH=NULL; 
		fclose(pFile); 
		return NULL; 
	} 
 
	r=fread(pData,imagesize,1,pFile); 
	if(r==-1){ 
		m_errorText="Read Image Data Error!";  
		delete [] pBMIH; 
		delete [] pData; 
		pData=NULL; 
		pBMIH=NULL; 
		fclose(pFile);  
		return NULL; 
	} 
	if(bitcount==24){ 
		delete [] pBMIH; 
		pBMIH=NULL; 
		fclose(pFile); 
		return pData; 
	} 
 
	int outsize=widthbytes*height; // 24 bit,Double word aligned! 
	LPBYTE pOutBuf=new BYTE[outsize]; 
	if(!pOutBuf){ 
		m_errorText="Allocate memory failed!"; 
		delete [] pData; 
		delete [] pBMIH; 
		pData=NULL; 
		pBMIH=NULL; 
		fclose(pFile); 
		return NULL; 
	} 
 
	int i,j; 
	if(bitcount==32){ 
		for(i=0; i>5)<<3); //green 
		        pOutBuf[offset2+2]=(BYTE)(((temp & 0x7c00)>>10)<<3); // red 
			} 
		} 
	} 
	if(bitcount==1 || bitcount==4 || bitcount==8){ 
		RGBQUAD* prgb=(RGBQUAD*)((BYTE*)pBMIH+sizeof(BITMAPINFOHEADER)); 
		for(i=0; i>(8-bitcount-s*bitcount))&mask; 
 
				pOutBuf[offset2+2]=prgb[index].rgbRed; 
				pOutBuf[offset2+1]=prgb[index].rgbGreen; 
				pOutBuf[offset2+0]=prgb[index].rgbBlue; 
			} 
		} 
	} 
 
	delete [] pData;	 
	delete [] pBMIH; 
	pData=NULL; 
	pBMIH=NULL; 
	fclose(pFile); 
 
	return pOutBuf; 
} 
 
// Output: 24 bit-per-pixel, double word aligned 
// lpvMem指向BITMAPINFOHEADER 结构 
BYTE* BMPFile::AttachMemory(LPVOID lpvMem, int &width, int &height, int &bitcount, int &widthbytes) 
{ 
	// assumes contiguous BITMAPINFOHEADER, color table, image data 
	// color table could be zero length 
	LPBITMAPINFOHEADER lpBMIH = (LPBITMAPINFOHEADER) lpvMem; 
	// Output 
	width=lpBMIH->biWidth; 
	height=lpBMIH->biHeight; 
	bitcount=lpBMIH->biBitCount; 
	widthbytes=(width*24+31)/32*4;// 24 Bit-per-pixel,double word aligned! 
	int outsize=widthbytes*height;// out image size 
 
	BYTE* pImageData=new BYTE[outsize]; // out buf 
	if(!pImageData){ 
		m_errorText="Allocate memory failed!"; 
		return NULL; 
	} 
 
	if(bitcount==24){ 
		memcpy(pImageData,(BYTE*)lpvMem+sizeof(BITMAPINFOHEADER),outsize); 
		return pImageData; 
	} 
 
	int widthbytes1=(width*bitcount+31)/32*4;// src image  
	int imagesize=widthbytes1*height; 
	BYTE* pSrcData=new BYTE[imagesize]; 
	if(!pSrcData){ 
		m_errorText="Allocate memory failed!"; 
		delete [] pImageData; 
		pImageData=NULL; 
		return NULL; 
	} 
 
	int i,j; 
	if(bitcount==32){ 
		memcpy(pSrcData,(BYTE*)lpvMem+sizeof(BITMAPINFOHEADER),imagesize); 
		for(i=0; i>5)<<3); //green 
		        pImageData[offset2+2]=(BYTE)(((temp & 0x7c00)>>10)<<3); // red 
			} 
		} 
	} 
	if(bitcount==1 || bitcount==4 || bitcount==8){ 
		int entry; 
		if(lpBMIH->biClrUsed==0) 
			entry=1<biClrUsed; 
		VERIFY(entry<=256); 
 
		RGBQUAD* prgb=(RGBQUAD*)((BYTE*)lpvMem+sizeof(BITMAPINFOHEADER)); 
		int offset=sizeof(BITMAPINFOHEADER)+entry*sizeof(RGBQUAD); 
		memcpy(pSrcData,(BYTE*)lpvMem+offset,imagesize); 
 
		for(i=0; i>(8-bitcount-s*bitcount))&mask; 
 
				pImageData[offset2+2]=prgb[index].rgbRed; 
				pImageData[offset2+1]=prgb[index].rgbGreen; 
				pImageData[offset2+0]=prgb[index].rgbBlue; 
			} 
		} 
	} 
 
	delete [] pSrcData;	 
	pSrcData=NULL; 
 
	return pImageData; 
} 
 
// Output: 24 bit-per-pixel, double word aligned 
BYTE* BMPFile::AttachMapFile(CString filename,int& width,int& height,int& bitcount,int& widthbytes) 
{ 
	// if we open the same file twice, Windows treats it as 2 separate files 
	HANDLE hFile = ::CreateFile(filename, GENERIC_READ, 
		                        FILE_SHARE_READ, 
		                        NULL,  
								OPEN_EXISTING,  
								FILE_ATTRIBUTE_NORMAL,  
								NULL); 
	ASSERT(hFile != INVALID_HANDLE_VALUE); 
 
	HANDLE hMap = ::CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL); 
 	if(hMap == NULL) { 
		m_errorText="Empty bitmap file"; 
		CloseHandle(hFile); 
		return NULL; 
	} 
 
	LPVOID lpvFile = ::MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0); // map whole file 
	ASSERT(lpvFile != NULL); 
 
	LPBITMAPFILEHEADER pBMFH=(LPBITMAPFILEHEADER)lpvFile; 
 
	if(pBMFH->bfType != 0x4d42) { 
		m_errorText="Invalid bitmap file"; 
		::UnmapViewOfFile(lpvFile); 
		::CloseHandle(hMap); 
		::CloseHandle(hFile); 
		hMap=NULL; 
		hFile = NULL; 
		return NULL; 
	} 
 
	LPBYTE lpvMem=(BYTE*)lpvFile+sizeof(BITMAPFILEHEADER); 
 
	BYTE* pImageData=AttachMemory(lpvMem,width,height,bitcount,widthbytes); 
 
	::UnmapViewOfFile(lpvFile); 
	::CloseHandle(hMap); 
	::CloseHandle(hFile); 
	hMap=NULL; 
	hFile=NULL; 
 
	return pImageData; 
} 
 
void BMPFile::CopyToMapFile(CString filename,BYTE* pData,int width,int height,int bitcount) 
{ 
	// 在这里不考虑颜色表,因为存的是24位BMP文件 
 
	int imagesize=(width*24+31)/32*4*height; 
 
	BITMAPFILEHEADER bmfh; 
	bmfh.bfType = 0x4d42;  // 'BM' 
	bmfh.bfSize = imagesize + sizeof(BITMAPINFOHEADER)+sizeof(BITMAPFILEHEADER); 
	bmfh.bfReserved1 = bmfh.bfReserved2 = 0; 
	bmfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); 
 
	HANDLE hFile = ::CreateFile(filename,  
		                        GENERIC_WRITE | GENERIC_READ,  
								0,  
								NULL, 
		                        CREATE_ALWAYS,  
								FILE_ATTRIBUTE_NORMAL,  
								NULL); 
	ASSERT(hFile != INVALID_HANDLE_VALUE); 
	 
	int filesize =  sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) +imagesize; // 文件头+信息头+图像数据大小 
	HANDLE hMap = ::CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, filesize, NULL); 
	ASSERT(hMap != NULL); 
 
	LPVOID lpvFile = ::MapViewOfFile(hMap, FILE_MAP_WRITE, 0, 0, 0); // map whole file 
	ASSERT(lpvFile != NULL); 
 
	LPBYTE lpbCurrent = (LPBYTE) lpvFile; // 同一内存 
	memcpy(lpbCurrent,&bmfh,sizeof(BITMAPFILEHEADER)); 
	lpbCurrent+=sizeof(BITMAPFILEHEADER); 
 
	BITMAPINFOHEADER bmih; 
	bmih.biBitCount=24; 
	bmih.biWidth=width; 
	bmih.biHeight=height; 
	bmih.biPlanes=1; 
	bmih.biSize=sizeof(BITMAPINFOHEADER); 
	bmih.biClrImportant=0; 
	bmih.biClrUsed=0; 
	bmih.biCompression=BI_RGB; 
	bmih.biSizeImage=0; 
	bmih.biXPelsPerMeter=0; 
	bmih.biYPelsPerMeter=0; 
	memcpy(lpbCurrent,&bmih,sizeof(BITMAPINFOHEADER)); 
	lpbCurrent+=sizeof(BITMAPINFOHEADER); 
 
	memcpy(lpbCurrent,pData,imagesize); 
	 
	::UnmapViewOfFile(lpvFile); 
	::CloseHandle(hMap); 
	::CloseHandle(hFile); 
	hMap=NULL; 
	hFile=NULL; 
}