www.pudn.com > 图像处理源代码.rar > image.cpp


#include "stdafx.h" 
#include "image.h" 
 
long int myPower(int x,int y) 
{ 
	long int power=1; 
	for(int k=0;kbfType!=0x4D42) 
	{ 
		MessageBox(hwnd,"所选文件不是BMP文件","错误",MB_OK); 
		bmpfile.Close(); 
		delete bmpfh; 
		return NULL; 
	} 
		 
	//检查文件头的SIZE是否与系统所示的SIZE一致 
	CFileStatus status; 
	if(!bmpfile.GetStatus(status) ||  
		(unsigned long)status.m_size!=bmpfh->bfSize ) 
	{ 
		MessageBox(hwnd,"该文件的大小不一致,可能被损坏!","错误",MB_OK); 
		bmpfile.Close(); 
		delete bmpfh; 
		return NULL; 
	} 
 
	//读信息头 
	bmpinfoh = new BITMAPINFOHEADER; 
	bmpfile.Read(bmpinfoh,BMPINFOHEADER_SIZE); 
	MYIMAGE *imgbuf=new MYIMAGE; 
 
	//如果图象的高度值为负,表示该图象由上到下显示,暂时不处理 
	if(bmpinfoh->biHeight<0) 
	{ 
		MessageBox(hwnd,"bmpinfoh->biHeight小于0,暂时不能处理!","错误",MB_OK); 
		bmpfile.Close(); 
		delete bmpfh; 
		delete bmpinfoh; 
		return NULL; 
	} 
 
	//暂时不处理压缩类型为BI_RL4,BI_RL8,BI_RGB以外的图象 
	if (   bmpinfoh->biCompression != BI_RLE4  
		&& bmpinfoh->biCompression != BI_RLE8  
		&& bmpinfoh->biCompression != BI_RGB ) 
	{ 
		MessageBox(hwnd,"尚未处理该类型压缩图象。","错误",MB_OK); 
		bmpfile.Close(); 
		delete bmpfh; 
		delete bmpinfoh; 
		return NULL; 
	} 
 
	switch (bmpinfoh->biBitCount) 
	{ 
	case 1: 
		imgbuf->ColorTabNumber =2; 
		break; 
 
	case 4: 
		imgbuf->ColorTabNumber=16; 
		break; 
 
	case 8: 
		imgbuf->ColorTabNumber=256; 
		break; 
 
	case 24: 
		imgbuf->ColorTabNumber=0; 
		break; 
		 
	default: 
		msg="现在还无法处理该BMP文件,BitCount="; 
		msg1=""; 
		itoa(bmpinfoh->biBitCount,msg1,10); 
		strcat(msg,msg1); 
		MessageBox(hwnd,msg,"错误",MB_OK); 
		bmpfile.Close(); 
		msg1=""; 
		msg=""; 
		delete bmpfh; 
		delete bmpinfoh; 
		return NULL; 
	} 
	//若实际使用颜色数不为0,则颜色表项数为实际使用颜色数 
	if(bmpinfoh->biClrUsed != 0 ) 
		imgbuf->ColorTabNumber=bmpinfoh->biClrUsed; 
 
	//图象属性赋值 
	imgbuf->Height =bmpinfoh->biHeight; 
	imgbuf->Width = bmpinfoh->biWidth; 
	imgbuf->BitCount =bmpinfoh->biBitCount ;		 
 
	//若颜色表项数大于0,则读取颜色表 
	if(imgbuf->ColorTabNumber >0) 
	{ 
		imgbuf->ColorTab =new RGBQUAD[imgbuf->ColorTabNumber]; 
		bmpfile.Read(imgbuf->ColorTab ,imgbuf->ColorTabNumber*sizeof(RGBQUAD)); 
		imgbuf->ImgData =new BYTE[imgbuf->Height * imgbuf->Width]; 
	} 
	else	//对24位图象,不需颜色表 
	{ 
		imgbuf->ColorTab = NULL; 
		imgbuf->ImgData = new BYTE[imgbuf->Height * imgbuf->Width * 3]; 
	} 
		 
	//计算未压缩情况的每行图象的字节数,必须为4的倍数 
	unsigned long bytesperline=(bmpinfoh->biWidth*bmpinfoh->biBitCount+31)/32*4; 
	BYTE *pline=new BYTE[bytesperline]; 
 
	//将文件指针移到图象阵列开始位置 
	bmpfile.Seek(bmpfh->bfOffBits,CFile::begin); 
		 
	if(bmpinfoh->biCompression == BI_RGB)	//未压缩图象,生成IMAGE中的ImgData 
	{   
		for(int vert=0;vertHeight;vert++) 
		{ 
			int hori; 
 
			//读一行数据到ImgData中 
			bmpfile.Read(pline,bytesperline); 
			switch(imgbuf->BitCount) 
			{ 
			case 24:	//24位图象数据 
				//将实际用于图象显示的字节数COPY到ImgData中 
				memcpy(&(imgbuf->ImgData[vert* imgbuf->Width*3]),pline,imgbuf->Width * 3); 
				break; 
	 
			case 8: //8位图象数据 
				memcpy(&(imgbuf->ImgData[vert* imgbuf->Width]),pline,imgbuf->Width); 
				break; 
 
			case 4:	//4位图象数据	 
				for(hori=0;horiWidth ;hori++) 
					if(hori & 0x01 != 0) 
						imgbuf->ImgData[vert*imgbuf->Width+hori]=pline[hori/2]&0x0F; 
					else 
						imgbuf->ImgData[vert*imgbuf->Width+hori]=pline[hori/2]>>4; 
				break; 
 
			case 1:	//1位图象数据 
				for(hori=0;horiWidth ;hori++) 
				{ 
					BYTE data=pline[hori/8]; 
					data >>= (7-(hori & 7)); 
					data &= 0x01; 
					imgbuf->ImgData[vert*imgbuf->Width+hori]=data; 
				} 
				break; 
			 
			default: 
				break; 
			}	//switch 
		}	//for 
	} 
	else if(bmpinfoh->biCompression == BI_RLE8)		//8位压缩图象 
	{ 
		BOOL endimage=FALSE;	//图象结束标志 
 
		for(int vert=0;vertbiHeight ;vert++) 
		{ 
			unsigned int cbyte=0;		//记录当前行已完成的字节数 
			BYTE *first,*next;	//读取的字节对 
			BOOL endofline=FALSE;	//行结束标志 
 
			first=new BYTE; 
			next=new BYTE; 
			while( ! endofline  && !endimage) 
			{	 
				bmpfile.Read(first,1); 
				bmpfile.Read (next,1); 
				if(*first !=0 )		//将next字节复制first次 
				{ 
					strnset((char*)&(imgbuf->ImgData[vert*imgbuf->Width+cbyte]), 
							*next,*first); 
					cbyte+=(*first); 
				} else  
					switch(*next){ 
					case 0:	//行结束 
						endofline=TRUE; 
						break; 
					case 1: //图象结束  
						endimage=TRUE; 
						break; 
					case 2:	//位置偏移,程序未做处理 
						bmpfile.Seek (2,CFile::current); 
						break; 
					default:	//后面next个字节不压缩 
						int readsize=((*next)+1)/2*2;	//所读字节必须为2的倍数 
						char* tmpstr=new char[readsize]; 
						bmpfile.Read(tmpstr,readsize); 
						memcpy(&(imgbuf->ImgData[vert*imgbuf->Width+cbyte]),tmpstr,*next); 
						cbyte += (*next); 
						delete tmpstr; 
						break; 
					}	//switch 
			}	//while 
		}	//for纵向循环  
	} 
	else if(bmpinfoh->biCompression == BI_RLE4)		//4位压缩图象 
	{ 
		BOOL endimage=FALSE;	//图象结束标志 
 
		for(int vert=0;vertbiHeight ;vert++) 
		{ 
			unsigned int cbyte=0;		//记录当前行已完成的字节数 
			BYTE *first,*next,data;	//读取的字节对 
			BOOL endofline=FALSE;	//行结束标志 
 
			first=new BYTE; 
			next=new BYTE; 
			while( ! endofline  && !endimage) 
			{	 
				bmpfile.Read(first,1); 
				bmpfile.Read (next,1); 
				if(*first !=0 )		//将next字节复制first次 
					for(int x=0;x<(*first);x++){ 
						if(x&1 != 0)	data = (*next) & 0x0F; 
						else	data = (*next) >> 4	; 
						imgbuf->ImgData [vert*imgbuf->Width+cbyte] = data; 
						cbyte++; 
					} 
				else  
					switch(*next){ 
					case 0:	//行结束 
						endofline=TRUE; 
						break; 
					case 1: //图象结束  
						endimage=TRUE; 
						break; 
					case 2:	//位置偏移,程序未做处理 
						bmpfile.Seek (2,CFile::current); 
						break; 
					default:	//后面next个象素不压缩 
						int readsize=((*next)+7)/8*4;	//所读字节必须为2的倍数 
						char* tmpstr=new char[readsize]; 
						bmpfile.Read(tmpstr,readsize); 
						for(int x=0;x<(*next);x++){ 
							if(x&1 != 0)	data = tmpstr[x/2] & 0x0F; 
							else	data = tmpstr[x/2] >> 4	; 
							imgbuf->ImgData [vert*imgbuf->Width+cbyte] = data; 
							cbyte++; 
						} 
						delete tmpstr; 
						break; 
					}	//switch 
			}	//while 
		}	//for纵向循环  
	} 
	//关闭图象文件,删除文件头、信息头 
	bmpfile.Close(); 
	delete bmpfh;	 
	delete bmpinfoh; 
	delete pline; 
 
	return imgbuf; 
} 
 
MYIMAGE* ReadPcx(CString FileName,HWND hwnd) 
{ 
	//MessageBox("PCX文件显示暂时没做!SORRY!"); 
	CFile pcxfile; 
 
	if(!pcxfile.Open(FileName,CFile::modeRead))	//打开文件 
	{ 
		MessageBox(hwnd,"不能打开文件","错误",MB_OK); 
		return NULL; 
	} 
	 
	//PCX图象文件头部分 
	PCXFILEHEADER *pcxfh=new PCXFILEHEADER; 
	pcxfile.Read(pcxfh,PCXFILEHEADER_SIZE); 
 
	MYIMAGE *imgbuf=new MYIMAGE; 
 
	//读取图象文件的位数、高、宽 
	imgbuf->BitCount = pcxfh->BitCount * pcxfh->ColorPlanes ; 
	imgbuf->Height = pcxfh->Ymax - pcxfh->Ymin + 1; 
	imgbuf->Width = pcxfh->Xmax - pcxfh->Xmin + 1; 
 
	//读取BitCount,并设置颜色表 
	switch (imgbuf->BitCount) { 
 
		int x; 
 
	case 1:	//单色图象,设置其颜色表为2项,一黑一白 
		imgbuf->ColorTabNumber =2; 
		imgbuf->ColorTab=new RGBQUAD[2]; 
		imgbuf->ColorTab [0].rgbBlue = 0x00; 
		imgbuf->ColorTab [0].rgbGreen = 0x00; 
		imgbuf->ColorTab [0].rgbRed = 0x00; 
		imgbuf->ColorTab [1].rgbBlue = 0xFF; 
		imgbuf->ColorTab [1].rgbGreen = 0xFF; 
		imgbuf->ColorTab [1].rgbRed = 0xFF; 
		break; 
	case 24://24位真彩色没有颜色表 
		imgbuf->ColorTabNumber = 0; 
		imgbuf->ColorTab=NULL; 
		break; 
	case 4:	//16色,颜色表在文件头中 
		imgbuf->ColorTabNumber =16; 
		imgbuf->ColorTab=new RGBQUAD[16]; 
		for(x=0;xColorTabNumber ;x++) 
		{ 
			imgbuf->ColorTab[x].rgbBlue = pcxfh->Palette [3*x]; 
			imgbuf->ColorTab[x].rgbGreen = pcxfh->Palette [3*x+1]; 
			imgbuf->ColorTab[x].rgbRed = pcxfh->Palette [3*x+2]; 
		} 
		break; 
	case 8:	//256色图象,颜色表在文件最后处的768个字节 
	{ 
		imgbuf->ColorTabNumber =256; 
		imgbuf->ColorTab=new RGBQUAD[256]; 
		BYTE* tmpstr=new BYTE[imgbuf->ColorTabNumber * 3]; 
		pcxfile.Seek( - imgbuf->ColorTabNumber * 3 ,CFile::end); 
		pcxfile.Read(tmpstr,imgbuf->ColorTabNumber * 3); 
		for(x=0;xColorTabNumber ;x++) 
		{ 
			imgbuf->ColorTab[x].rgbBlue = tmpstr [3*x]; 
			imgbuf->ColorTab[x].rgbGreen = tmpstr [3*x+1]; 
			imgbuf->ColorTab[x].rgbRed = tmpstr [3*x+2]; 
		} 
		delete tmpstr; 
		pcxfile.Seek(PCXFILEHEADER_SIZE,CFile::begin); 
		break; 
	} 
	default: 
		MessageBox(hwnd,"PCX不支持的文件","错误",MB_OK); 
		delete imgbuf; 
		delete pcxfh; 
		pcxfile.Close (); 
		return NULL; 
	} 
 
	//初始化图象数据空间 
	if(imgbuf->ColorTabNumber >0) 
		imgbuf->ImgData =new BYTE[imgbuf->Height * imgbuf->Width]; 
	else 
		imgbuf->ImgData = new BYTE[imgbuf->Height * imgbuf->Width * 3]; 
	 
	BYTE* pline = new BYTE[pcxfh->BytePerLine * pcxfh->ColorPlanes];	//存储每行的数据 
 
	for(int vert=imgbuf->Height-1;vert>-1 ;vert--) 
	{ 
		unsigned int cbyte=0;	//当前行已完成字节数 
		BYTE *curbyte = new BYTE; 
		int times; 
		 
		//从文件中解压出一行图象数据,必须为偶数个字节 
		while(cbyte < pcxfh->BytePerLine * pcxfh->ColorPlanes ) 
		{ 
			//读一个字节 
			pcxfile.Read(curbyte,1); 
		 
			if(((*curbyte) & 0xC0) == 0xC0)	//若高2位全为1 
			{ 
				times = (*curbyte) & 0x3F ; 
				pcxfile.Read(curbyte,1); 
				strnset((char*)&pline[cbyte],*curbyte,times); 
				cbyte+=times; 
			} 
			else 
			{ 
				pline[cbyte]=(*curbyte); 
				cbyte++; 
			} 
		} 
	 
		//对一行图象数据按位平面,分别产生每个象素的颜色值 
		switch(imgbuf->BitCount) 
		{ 
			int hori; 
 
		case 1: 
			for(hori=0;horiWidth ;hori++) 
				imgbuf->ImgData[vert*imgbuf->Width+hori]=(pline[hori/8]>>(7-(hori&7)))&0x01; 
			break; 
		case 4: 
			for(hori=0;horiWidth ;hori++) 
			{ 
				int r,g,b,i; 
 
				r=(pline[hori/8]>>(7-(hori&7)))&0x01; 
				g=(pline[hori/8+pcxfh->BytePerLine]>>(7-(hori&7)))&0x01; 
				b=(pline[hori/8+pcxfh->BytePerLine*2]>>(7-(hori&7)))&0x01; 
				i=(pline[hori/8+pcxfh->BytePerLine*3]>>(7-(hori&7)))&0x01; 
				imgbuf->ImgData[vert*imgbuf->Width+hori]=r+g*0x02+b*0x04+i*0x08; 
			} 
			break; 
		case 8: 
			memmove(&(imgbuf->ImgData[vert* imgbuf->Width]),pline,imgbuf->Width); 
			break; 
		case 24: 
			for(hori=0;horiWidth ;hori++) 
			{ 
				imgbuf->ImgData[(vert* imgbuf->Width+hori)*3]=pline[pcxfh->BytePerLine*2 + hori];	//BLUE 
				imgbuf->ImgData[(vert* imgbuf->Width+hori)*3+1]=pline[pcxfh->BytePerLine + hori];	//Green 
				imgbuf->ImgData[(vert* imgbuf->Width+hori)*3+2]=pline[hori];	//Red 
			} 
			break; 
		default: 
			break; 
		} 
	}//for纵向循环 
	delete pline; 
 
	return imgbuf; 
} 
 
BOOL SaveBmp(CString FileName, MYIMAGE *img,BOOL Compression,HWND hwnd) 
{ 
	CFile bmpfile; 
	try{ 
		bmpfile.Open(FileName,CFile::modeCreate | CFile::modeWrite); 
	}catch(...){ 
		MessageBox(hwnd,"文件错误","错误",MB_OK); 
		return FALSE; 
	} 
	 
	//BMP文件头 
	BITMAPFILEHEADER* bmpfh=new BITMAPFILEHEADER;	 
	//BMP文件信息头部分 
	BITMAPINFOHEADER* bmpih=new BITMAPINFOHEADER; 
	 
	//BMP标志 
	bmpfh->bfType = 0x4D42; 
	//保留字 
	bmpfh->bfReserved1 = 0; 
	bmpfh->bfReserved2 = 0; 
 
	//信息头大小 
	bmpih->biSize = BMPINFOHEADER_SIZE; 
	//图象尺寸 
	bmpih->biWidth = img->Width ; 
	bmpih->biHeight = img->Height ; 
	//位平面数 
	bmpih->biPlanes = 1; 
	//每象素所占位数 
	bmpih->biBitCount = img->BitCount ; 
	//压缩类型 
	if(!Compression) 
		bmpih->biCompression = BI_RGB; 
	else if(Compression && img->BitCount == 4)  
		bmpih->biCompression = BI_RLE4; 
	else if(Compression && img->BitCount == 8) 
		bmpih->biCompression = BI_RLE8; 
	else{ 
		MessageBox(hwnd,"压缩类型错误。","错误",MB_OK); 
		delete bmpih; 
		delete bmpfh; 
		return FALSE; 
	} 
	bmpih->biClrImportant = 0; 
	if((img->BitCount != 24) && (img->ColorTabNumber < myPower(2,img->BitCount))) 
		bmpih->biClrUsed = img->ColorTabNumber ; 
	else 
		bmpih->biClrUsed = 0; 
 
 
	//设置物理输出的分辨率 
	bmpih->biXPelsPerMeter= 0x0b12; 
	bmpih->biYPelsPerMeter= 0x0b12; 
 
	int ColorTabSize = 0; 
 
	if(img->ColorTabNumber > 0 ) 
		ColorTabSize = img->ColorTabNumber  * sizeof(RGBQUAD); 
 
	//图象数据位置 
	bmpfh->bfOffBits = BMPFILEHEADER_SIZE + BMPINFOHEADER_SIZE + ColorTabSize ; 
 
	BYTE *pImagebuf; 
	if(bmpih->biCompression == BI_RGB) 
	{ 
		//计算未压缩情况的每行图象的字节数,必须为4的倍数 
		unsigned long bytesperline=(bmpih->biWidth*bmpih->biBitCount+31)/32*4; 
		//记录每行字节数和实际图象使用的字节数的差,即扫描行结束需要填充的字节数 
		int diff;	 
		//图象数据的字节数 
		bmpih->biSizeImage = bytesperline*bmpih->biHeight; 
		pImagebuf=new BYTE[bmpih->biSizeImage ]; 
		 
		switch(bmpih->biBitCount) 
		{ 
			int vert,x; 
		case 24: 
			diff=bytesperline - bmpih->biWidth * 3; 
			for(vert=0;vertbiHeight ;vert++) 
			{ 
				memcpy ( &(pImagebuf[ vert * bytesperline ]), 
					&(img->ImgData [ vert * bmpih->biWidth * 3 ]),bmpih->biWidth * 3); 
				for(x=0;xbiWidth * 3 + x] = 0; 
			} 
			break; 
 
		case 8: 
			diff=bytesperline - bmpih->biWidth; 
			for(vert=0;vertbiHeight ;vert++) 
			{ 
				memcpy ( &(pImagebuf[ vert * bytesperline ]), 
					&(img->ImgData [ vert * bmpih->biWidth ]),bmpih->biWidth ); 
				for(x=0;xbiWidth + x] = 0; 
			} 
			break; 
 
		case 4: 
			for(vert=0 ; vertbiHeight ; vert++) 
				for(x=0;x=bmpih->biWidth ) ? 0 : img->ImgData [vert*bmpih->biWidth + x] ; 
					if((x&1) == 0)	pImagebuf[vert * bytesperline +x/2] = data << 4; 
					else	pImagebuf[vert * bytesperline +x/2] += data; 
				} 
			break; 
 
		case 1: 
			for(vert=0 ; vertbiHeight ; vert++) 
				for(x=0;x=bmpih->biWidth ) ? 0 : img->ImgData [vert*bmpih->biWidth + x] ; 
				 
					if((x&7) == 0)	pImagebuf[vert * bytesperline +x/8] = data << 7; 
					else	pImagebuf[vert * bytesperline +x/8] += data << ( 7 - (x&7)); 
				} 
			break; 
		} 
	} 
	else if(bmpih->biCompression == BI_RLE8) 
	{ 
	//存储为8位压缩格式的处理 
	} 
	else if(bmpih->biCompression == BI_RLE4) 
	{ 
	//存储为4位压缩格式的处理 
	} 
 
 
	//图象数据的字节数 
//	bmpih->biSizeImage = ; 
 
	//文件大小 
	bmpfh->bfSize = BMPFILEHEADER_SIZE + BMPINFOHEADER_SIZE + ColorTabSize + bmpih->biSizeImage; 
 
	bmpfile.Write(bmpfh,BMPFILEHEADER_SIZE); 
	bmpfile.Write(bmpih,BMPINFOHEADER_SIZE); 
	if(ColorTabSize > 0) 
		bmpfile.Write (img->ColorTab ,ColorTabSize); 
	bmpfile.Write (pImagebuf,bmpih->biSizeImage ); 
	bmpfile.Close (); 
	delete bmpfh; 
	delete bmpih; 
	delete pImagebuf; 
	return TRUE; 
} 
 
//24位pcx写 
BOOL SavePcx(CString FileName, MYIMAGE *img,HWND hwnd) 
{ 
	if(img->BitCount != 24) 
	{ 
		MessageBox(hwnd,"暂时不能处理非24位图象的PCX格式保存","错误",MB_OK); 
		return FALSE; 
	} 
 
	CFile pcxfile; 
	try{ 
		pcxfile.Open(FileName,CFile::modeCreate | CFile::modeWrite); 
	}catch(...){ 
		MessageBox(hwnd,"文件错误","错误",MB_OK); 
		return FALSE; 
	} 
	 
	//PCX文件头 
	PCXFILEHEADER* pcxfh=new PCXFILEHEADER;	 
 
	pcxfh->BytePerLine = (img->Width +1)/2*2; 
	pcxfh->Encoding = 1; 
	strnset((char*)pcxfh->Filler,0,58); 
	pcxfh->Hres = 0x48; 
	pcxfh->Vres = 0x48; 
	pcxfh->Manufacture = 10; 
	if(img->BitCount == 24) 
	{ 
		strnset((char*)pcxfh->Palette,0,48); 
		pcxfh->BitCount = 8; 
		pcxfh->ColorPlanes = 3; 
		pcxfh->Version = 5;	 
	} 
	pcxfh->PaletteType = 1; 
	pcxfh->Reserved = 0; 
 
	pcxfh->Xmax = img->Width - 1; 
	pcxfh->Xmin = 0; 
	pcxfh->Ymax = img->Height - 1; 
	pcxfh->Ymin = 0; 
 
	pcxfile.Write (pcxfh,sizeof(PCXFILEHEADER)); 
 
	//每扫描行的总字节数 
	int totalbyte = pcxfh->BytePerLine * pcxfh->ColorPlanes ; 
 
	BYTE *pline=new BYTE[totalbyte]; 
	for(int vert=img->Height-1;vert>=0 ;vert--) 
	{ 
		//将图象数据按位平面排列 
		for(int hori=0;horiBytePerLine;hori++) 
		{ 
			pline[hori]=(hori==img->Width)  
				 ? 0 : img->ImgData[(vert*img->Width+hori)*3+2]; 
 
			pline[hori + pcxfh->BytePerLine]=(hori==img->Width) 
				 ? 0 : img->ImgData[(vert*img->Width+hori)*3+1]; 
 
			pline[hori + pcxfh->BytePerLine * 2]=(hori==img->Width) 
				 ? 0 : img->ImgData[(vert*img->Width+hori)*3]; 
		} 
 
		int cbyte=0;//已完成字节数 
 
		while(cbyte1) || ((pline[cbyte]&0xc0)==0xc0)) 
			{ 
				repeatCount += 0xc0; 
				pcxfile.Write(&repeatCount,1); 
			} 
			pcxfile.Write (&(pline[cbyte]),1); 
			cbyte++; 
		} 
	} 
	delete pcxfh; 
	pcxfile.Close (); 
	return TRUE; 
}