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;
}