哪位朋友会用C++读取BMP图像,不要急于MFC类的,我就是想把图像数据矩阵在DOS黑屏下显示出来,或者存成图像数据矩阵。如果谁有源程序可以发到我邮箱xiaopingai8@163.com,本人非常感谢。有没有更简单一点的呢?比如针对灰度图像的,图像读进去后,将数据矩阵显示出来,高手帮帮忙
#include<math.h>#include <iomanip.h> #include <stdlib.h>#include <windows.h>#include <stdio.h>#include <stdlib.h>#include <iostream.h>#include <fstream.h>//---------------------------------------------------------------------------------------//以下该模块是完成BMP图像(彩色图像是24bit RGB各8bit)的像素获取,并存在文件名为xiang_su_zhi.txt中unsigned char *pBmpBuf;//读入图像数据的指针int bmpWidth;//图像的宽int bmpHeight;//图像的高RGBQUAD *pColorTable;//颜色表指针int biBitCount;//图像类型,每像素位数//-------------------------------------------------------------------------------------------//读图像的位图数据、宽、高、颜色表及每像素位数等数据进内存,存放在相应的全局变量中bool readBmp(char *bmpName) { FILE *fp=fopen(bmpName,"rb");//二进制读方式打开指定的图像文件 if(fp==0) return 0; //跳过位图文件头结构BITMAPFILEHEADER fseek(fp, sizeof(BITMAPFILEHEADER),0); //定义位图信息头结构变量,读取位图信息头进内存,存放在变量head中 BITMAPINFOHEADER head; fread(&head, sizeof(BITMAPINFOHEADER), 1,fp); //获取图像宽、高、每像素所占位数等信息 bmpWidth = head.biWidth; bmpHeight = head.biHeight; biBitCount = head.biBitCount;//定义变量,计算图像每行像素所占的字节数(必须是4的倍数) int lineByte=(bmpWidth * biBitCount/8+3)/4*4;//灰度图像有颜色表,且颜色表表项为256 if(biBitCount==8) { //申请颜色表所需要的空间,读颜色表进内存 pColorTable=new RGBQUAD[256]; fread(pColorTable,sizeof(RGBQUAD),256,fp); } //申请位图数据所需要的空间,读位图数据进内存 pBmpBuf=new unsigned char[lineByte * bmpHeight]; fread(pBmpBuf,1,lineByte * bmpHeight,fp); fclose(fp);//关闭文件 return 1;//读取文件成功}//-----------------------------------------------------------------------------------------//给定一个图像位图数据、宽、高、颜色表指针及每像素所占的位数等信息,将其写到指定文件中bool saveBmp(char *bmpName, unsigned char *imgBuf, int width, int height, int biBitCount, RGBQUAD *pColorTable){ //如果位图数据指针为0,则没有数据传入,函数返回 if(!imgBuf) return 0; //颜色表大小,以字节为单位,灰度图像颜色表为1024字节,彩色图像颜色表大小为0 int colorTablesize=0; if(biBitCount==8) colorTablesize=1024; //待存储图像数据每行字节数为4的倍数 int lineByte=(width * biBitCount/8+3)/4*4; //以二进制写的方式打开文件 FILE *fp=fopen(bmpName,"wb"); if(fp==0) return 0; //申请位图文件头结构变量,填写文件头信息 BITMAPFILEHEADER fileHead; fileHead.bfType = 0x4D42;//bmp类型 //bfSize是图像文件4个组成部分之和 fileHead.bfSize= sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + colorTablesize + lineByte*height; fileHead.bfReserved1 = 0; fileHead.bfReserved2 = 0; //bfOffBits是图像文件前3个部分所需空间之和 fileHead.bfOffBits=54+colorTablesize; //写文件头进文件 fwrite(&fileHead, sizeof(BITMAPFILEHEADER),1, fp); //申请位图信息头结构变量,填写信息头信息 BITMAPINFOHEADER head; head.biBitCount=biBitCount; head.biClrImportant=0; head.biClrUsed=0; head.biCompression=0; head.biHeight=height; head.biPlanes=1; head.biSize=40; head.biSizeImage=lineByte*height; head.biWidth=width; head.biXPelsPerMeter=0; head.biYPelsPerMeter=0; //写位图信息头进内存 fwrite(&head, sizeof(BITMAPINFOHEADER),1, fp); //如果灰度图像,有颜色表,写入文件 if(biBitCount==8) fwrite(pColorTable, sizeof(RGBQUAD),256, fp); //写位图数据进文件 fwrite(imgBuf, height*lineByte, 1, fp); //关闭文件 fclose(fp); return 1;}//----------------------------------------------------------------------------------------//以下为像素的读取函数void xiang_su_du_qu(){ //读入指定BMP文件进内存 char readPath[]="nv.BMP"; readBmp(readPath); //输出图像的信息 cout<<"width="<<bmpWidth<<" height="<<bmpHeight<<" biBitCount="<<biBitCount<<endl; //循环变量,图像的坐标 //每行字节数 int lineByte=(bmpWidth*biBitCount/8+3)/4*4; //循环变量,针对彩色图像,遍历每像素的三个分量 int m=0,n=0,count_xiang_su=0; //将图像左下角1/4部分置成黑色 ofstream outfile("图像像素.txt",ios::in|ios::trunc); if(biBitCount==8) //对于灰度图像 { //------------------------------------------------------------------------------------//以下完成图像的分割成8*8小单元,并把像素值存储到指定文本中。由于BMP图像的像素数据是从//左下角:由左往右,由上往下逐行扫描的 int L1=0; int hang=63; int lie=0; //int L2=0; //int fen_ge=8; for(int fen_ge_hang=0;fen_ge_hang<8;fen_ge_hang++)//64*64矩阵行循环 { for(int fen_ge_lie=0;fen_ge_lie<8;fen_ge_lie++)//64*64列矩阵循环 { //-------------------------------------------- for(L1=hang;L1>hang-8;L1--)//8*8矩阵行 { for(int L2=lie;L2<lie+8;L2++)//8*8矩阵列 { m=*(pBmpBuf+L1*lineByte+L2); outfile<<m<<" "; count_xiang_su++; if(count_xiang_su%8==0)//每8*8矩阵读入文本文件 { outfile<<endl; } } } //--------------------------------------------- hang=63-fen_ge_hang*8;//64*64矩阵行变换 lie+=8;//64*64矩阵列变换 //该一行(64)由8个8*8矩阵的行组成 } hang-=8;//64*64矩阵的列变换 lie=0;//64*64juzhen } } //double xiang_su[2048]; //ofstream outfile("xiang_su_zhi.txt",ios::in|ios::trunc); if(!outfile) { cout<<"open error!"<<endl; exit(1); } else if(biBitCount==24){//彩色图像 for(int i=0;i<bmpHeight;i++) { for(int j=0;j<bmpWidth;j++) { for(int k=0;k<3;k++)//每像素RGB三个分量分别置0才变成黑色 { //*(pBmpBuf+i*lineByte+j*3+k)-=40; m=*(pBmpBuf+i*lineByte+j*3+k); outfile<<m<<" "; count_xiang_su++; if(count_xiang_su%8==0) { outfile<<endl; } //n++; } n++; }} cout<<"总的像素个素为:"<<n<<endl; cout<<"----------------------------------------------------"<<endl; } //将图像数据存盘 char writePath[]="nvcpy.BMP";//图片处理后再存储 saveBmp(writePath, pBmpBuf, bmpWidth, bmpHeight, biBitCount, pColorTable); //清除缓冲区,pBmpBuf和pColorTable是全局变量,在文件读入时申请的空间 delete []pBmpBuf; if(biBitCount==8) delete []pColorTable;}void main(){ xiang_su_du_qu();}
可以看下如下的操作: 1、图片文件是有固定格式的,像BMP图片是文件头+位图的颜色数据。文件头一般在读取的时候是使用下面的代码: BITMAPFILEHEADER fileheader={0}; fread(&fileheader,sizeof(fileheader),1,fp); if(fileheader.bfType!=0x4D42) // 判断是否为BMP图片 { fclose(fp); return ; } BITMAPINFOHEADER head; fread(&head,sizeof(BITMAPINFOHEADER),1,fp); long bmpWidth = head.biWidth; //获取图片的宽 long bmpHeight = head.biHeight; //获取图片的宽 WORD biBitCount = head.biBitCount; if(biBitCount != 24) // 是否为24位位图 { ::AfxMessageBox(_T("请选择24位位图!")); fclose(fp); return ; }2、文件读到这里了就要读到位图的颜色数据了,那么在读取前,需要知道数据的大小,这样才能把分配具体大学的缓冲区,之后把数据完整的读取到缓冲区内。那么计算位图数据的大小一般用下面的代码去做。int totalSize = (bmpWidth *biBitCount/8+3)/4*4*bmpHeight; BYTE *pBmpBuf = new BYTE[totalSize];3、在这些工作做完之后,就使用fread命令直接读取文件内容即可,直到读到文件结束。整个具体的代码实现如下: FILE *fp=NULL; int ret = fopen_s(&fp,"D:\\11.bmp","rb"); if(fp==0) { return ; } BITMAPFILEHEADER fileheader={0}; fread(&fileheader,sizeof(fileheader),1,fp); if(fileheader.bfType!=0x4D42) { fclose(fp); return ; } BITMAPINFOHEADER head; fread(&head,sizeof(BITMAPINFOHEADER),1,fp); long bmpWidth = head.biWidth; long bmpHeight = head.biHeight; WORD biBitCount = head.biBitCount; if(biBitCount != 24) { ::AfxMessageBox(_T("请选择24位位图!")); fclose(fp); return ; } int totalSize = (bmpWidth *biBitCount/8+3)/4*4*bmpHeight; BYTE *pBmpBuf = new BYTE[totalSize]; size_t size = 0; while(true) { int iret = fread(&pBmpBuf[size],1,1,fp); if(iret == 0) break; size = size + iret; } fclose(fp); int i,j; CClientDC dc(this); int pitch=bmpWidth%4; for(i=0;i<bmpHeight;i++) { int realPitch=i*pitch; for(j=0;j<bmpWidth;j++) { dc.SetPixel(j,i,RGB( pBmpBuf[(i*bmpWidth+j)*3+2+realPitch], pBmpBuf[(i*bmpWidth+j)*3+1+realPitch], pBmpBuf[(i*bmpWidth+j)*3+realPitch])); } } delete [] pBmpBuf; pBmpBuf = NULL; return ;
你好,我把问题补充一下,希望对你有帮助。如果还是不行,你再问我。在你如下的程序段中://读取头文件 fseek( rfile , sizeof(short) ,SEEK_SET ); fread( pointfh ,sizeof(BITMAPFILEHEADER) , 1 , rfile ); //读取信息头文件fseek( rfile , sizeof(BITMAPFILEHEADER)+sizeof(short) ,SEEK_SET ); fread( pointih ,sizeof(BITMAPINFOHEADER),1, rfile );//读位图信息pointimage=(char*)calloc(ih.biSizeImage*3, sizeof(char));fseek(rfile,fh.bfOffBits,SEEK_SET);//头指针移动到位图区fread(pointimage,sizeof(char),ih.biSizeImage*3,rfile);第一句中,我觉得不要加sizeof(short),而是将其改为0。因为文件的前sizeof(BITMAPFILEHEADER)个字节就是 文件信息头,紧接其后的sizeof(BITMAPINFOHEADER)个字节是位图信息头,所以在你的第三条语句中,也应去掉sizeof(short)。另外,biSizeImage就是位图像素信息实际占用的存储空间长度,不需要乘以3,所以在上面第5和第7句中应将“*3”去掉。这时你在运行一下试试。还有,24位位图每个像素用3个字节表示。你的256像素*256像素的图像的实际占用的字节数应是256*256*3 = 196608,这正是biSizeImage的值!bmp文件分为四个部分:文件信息头、位图信息头、调色板、位图信息数据。你在读信息头文件后,应该读调色板数据。对于真彩色图像,因为没有调色板,所以不用读;但对于其他的图像就需要读了。这是你的代码存在的问题之一。解决办法是根据biBitCount的值判断调色板的大小:若biBitCount为1,调色板大小为2*sizeof(RGBQUAD)字节;若为4,调色板16*sizeof(RGBQUAD);若为8,调色板256*sizeof(RGBQUAD);若为24,调色板为0。另外,位图信息数据每行存储的字节数一定是4字节的整数倍,不足的时候补0。比如你的图像每行只有一个像素,一个像素用三个字节存储,那么在实际存储该图像时需要在每行多补充一个字节,以使其达到4字节的整数倍。biSizeImage的值就是图像信息数据实际存储的字节数,读的时候直接读这么多字节的数据就行了,不需要乘以3。你的代码在读信图信息时并没考虑这一点,这是存在的问题之二。图像每行存储的实际字节数:nBytesPerLine = biSizeImage / biHeight,这个值在后续的处理中可能会用到。你说读取的分辨率是3780,是指每米有3780个像素,单位是像素/米。而那个96的单位可能不是像素/米。希望对你有帮助。
数据在黑屏下显示数据量会很大,故存为dat文件;#include <windows.h>#include <stdio.h>/*输入的指令必须如下格式: command xx.bmp width heightcommand 编译之后的程序名称xx.bmp 需要获取像素值的bmp文件名,需输入扩展名width,height bmp文件的大小*/int main(int argc,char* argv[]){ int x,y,i; unsigned char *px; HBITMAP map; FILE* pout; x=atoi(argv[2]);//得到bmp文件的大小信息 y=atoi(argv[3]); px=new unsigned char[x*y]; map=(HBITMAP)LoadImage(NULL,argv[1],IMAGE_BITMAP,x,y,LR_LOADFROMFILE);//装载bmp文件 GetBitmapBits(map,x*y,px);//获取像素值信息 pout=fopen("pixeldata.dat","wb"); for(i=0;i<x*y;i++) { if((i%4)!=3)//因为bmp文件为每个像素分配了4Byte的空间,分别为R,G,B,保留,估输出时不写出第四个Byte的值(必为0) fwrite(&px[i],sizeof(unsigned char),1,pout); } fclose(pout); return 0;}
用c++的readfile函数就可以读bmp文件的,只是的先知道bmp文件的结构,这样才知道读出来的是文件的描述信息还是图像的信息。。。bmp文件的结构包括四部分,前三部分存了图像的各种信息,最后一部分才是图像的色彩信息。。它们的具体的数据结构,请来这里看:http://book.csdn.net/bookfiles/780/10078023501.shtml