logo资料库

数字图像处理+将24位真彩色BMP图像转化成8位BMP灰度图像.doc

第1页 / 共12页
第2页 / 共12页
第3页 / 共12页
第4页 / 共12页
第5页 / 共12页
第6页 / 共12页
第7页 / 共12页
第8页 / 共12页
资料共12页,剩余部分请下载后查看
数字图像处理 实验报告 实验一: 实验名称:彩色图转换成灰度图 实验任务:将 24 位真彩色 BMP 图像转化成 8 位 BMP 灰度图像 编程环境:MFC 设计思路:读入图像信息,将图像信息放入内存中。重新申请内存空间存放 8 位 256 级灰度 图像。并设置一个调色板,用来存放 256 级灰度级,以便于生成灰度图像时用的颜色信息。 用指针得到每个像素点的颜色值,并用原来 24 位的颜色转换成 8 位的灰度级,放入新的图 像信息中。最后保存灰度图。 主要模块: 主函数: 确定要打开和保存的文件名,调用转换函数和保存图片函数,最后释放指针 转换函数: BYTE* ConvertTo8Bit(CString strFileName, DWORD *dwFileLength, BYTE
*lpNewBmpData) 将指定的文件读入,取得 BMP 图像的文件头,文件信息头,文件大小,读 取文件数据信息。重新申请空间存放新图像的信息,设置新图像的文件头的信息,并设置一 个它的颜色表,存放 256 级灰度。将得到的原图的每个像素点的颜色值转换成新图像的灰度 值,存放在新的头像信息中。 保存函数: BOOL SaveFile(CString strFileName, DWORD dwFileLength) 将新的图像信息写入,先写位图头信息,再把实际数据写入。 void CMyDlg::OnOK() { CString strOpenFileName,strSaveFileName; strOpenFileName="24.bmp"; strSaveFileName="灰度.bmp"; DWORD dwFileLength; lpNewBmpInfo = (BITMAPINFO*)ConvertTo8Bit( strOpenFile Name, &dwFileLength, lpNewBmpData); if( !lpNewBmpInfo ){ printf( "转换出错,程序退出!\n"); return ;} if(!SaveFile(strSaveFileName, dwFileLength) ){ printf( "保存文件出错!" ); return ;} if( lpNewBmpData != NULL) delete []lpNewBmpData; if( lpNewBmpInfo != NULL ) delete []lpNewBmpInfo; if( lpOldBmp != NULL ) delete []lpOldBmp;} BYTE* CMyDlg::ConvertTo8Bit(CString strFileName, DWORD *dwFileLength, BYTE *lpNewBmpData) { CDC *pDC=m_image.GetDC(); CRect m_rect; m_image.GetClientRect(m_rect); if( lpNewBmpData != NULL ){ delete []lpNewBmpData; lpNewBmpData = NULL;} hFile HANDLE = ::CreateFile(strFileName,GENERIC_READ, FILE_SHARE_READ,NULL,OPEN_EXISTI NG,FILE_ATTRIBUTE_NORMAL,NULL); if(hFile == 0){ printf("不能打开文件,请重新选择!\n"); return NULL;} DWORD dwWriteNum; // BITMAPFILEHEADER Bmp_file_head; 文件头 ReadFile(hFile,&Bmp_file_head,14,&dwWrit eNum,NULL);//读取文件头,共 14 个字节 if((Bmp_file_head.bfType!='MB')||(dwWriteN um != sizeof(BITMAPFILEHEADER))){ printf("不是 BMP 位图文件或数据有误!\n"); return NULL;} *dwFileLength=GetFileSize(hFile,NULL)-siz eof(BITMAPFILEHEADER); // 获 取 文 件 的 长度 BYTE *lpOldBmp; lpOldBmp= new BYTE[*dwFileLength]; //存放原 24 位位图像,包括图像的信息头、 调色板和像素数据 ReadFile(hFile,lpOldBmp,*dwFileLengt //读取图像数据 h,&dwWriteNum,NULL); BYTE*lpOldBmpData = lpOldBmp + //指 sizeof(BITMAPINFOHEADER) ; 向图像数据的实际位置,其调色板为 0 BITMAPINFO*lpOldBmpInfo = (BITMAPINFO*)lpOldBmp; if(lpOldBmpInfo->bmiHeader.biBitCount!= 24){ printf( "此图像非 24 位位图!"); return NULL;} Int nScanWidth;//转换后其每行扫描宽度 int nLineWidth;//将其转换成 8 位位图后 每行宽度(即每行字节数) nSrcWidth,nSrcHeight; int height=nSrcHeight=lpOldBmpInfo->bmi
Header.biHeight; //原 24 位位图高度 1]*0.587+color[0]*0.114); width=nSrcWidth=lpOldBmpInfo->bmiH pDC->SetPixel(j,height-i,RGB(dwColor eader.biWidth; //原 24 位位图宽度 nLineWidth = nSrcWidth*3/4*4; if(nLineWidthbmiHeader=lpOldBmpI nfo->bmiHeader; lpNewBmpInfo->bmiHeader.biBitCount=8; //数据起始位置为原位图信息头起始+ 位图信息头大小+彩色表大小 lpNewBmpData=(BYTE*)lpNewBmpInfo+si zeof(BITMAPINFOHEADER)+256* sizeof(RGBQUAD); i,j; int //为其相应的彩色表赋值 for(i=0;i<256;i++) lpNewBmpInfo->bmiColors[i].rgbRed=i; { lpNewBmpInfo->bmiColors[i].rgbGreen=i; lpNewBmpInfo->bmiColors[i].rgbBlue=i; lpNewBmpInfo->bmiColors[i].rgbReserved=0; //保留位} for(i=0;i255) dwColorTemp=255; if( dwColorTemp< 0 ) dwColorTemp = 0; lpNewBmpData[i*nScanWidth+j]=(BYT } } E)dwColorTemp; lpNewBmpData[nScanWidth*nSrcHeight]=0; lpNewBmpData[nScanWidth*nSrcHeight+1] =0; if( !CloseHandle( hFile ) ) printf("关闭文件时失败"); return (BYTE*)lpNewBmpInfo;} CMyDlg::SaveFile(CString BOOL strFileName,DWORD dwFileLength) {HANDLE = CreateFile( strFileName, GENERIC_WRITE, FILE_SHARE_WRITE,NULL,CREATE_AL WAYS,FILE_ATTRIBUTE_NORMAL, NULL); hSaveFile if( !hSaveFile ){ printf( "创建文件出错\n"); return FALSE;} DWORD dwWriteNum; BITMAPFILEHEADER BFH; BFH.bfType = 'MB'; BFH.bfSize = dwFileLength + sizeof(BITMAPFILEHEADER); BFH.bfOffBits=sizeof(BITMAPFILEHEADE R) + sizeof(BITMAPINFOHEADER) + 256* sizeof(RGBQUAD); //256 为 调 色 表 颜 色 数 (0-255) BFH.bfReserved1 = BFH.bfReserved2 = 0; //写位图头信息 WriteFile( hSaveFile, sizeof(BITMAPFILEHEADER), &dwWriteNum, NULL); &BFH, //写实际数据 WriteFile( hSaveFile, lpNewBmpInfo, dwFileLength, &dwWriteNum, NULL); CloseHandle( hSaveFile ); return TRUE;}
实验前:(24 位真彩图) 实验后:(8 位灰度图) 实验二: 实验名称:图片颜色去反。 实验任务:将一张 8 位的灰度图,颜色取反,产生底片效果。 设计思路:将灰度图的文件头和数据信息读入内存,然后将每个像素的值取反,然后将文件 头和新的像素值写入另一个图片文件中。 主要模块: 主函数:读入图片名称,调用转换函数和保存函数。 转换函数: BYTE* Reverse(DWORD *dwFileLength, BYTE *lpNewBmpData) 将指定的文件读入,取得 BMP 图像的文件头,文件信息头,文件大小, 读取文件数据信息。重新申请空间存放新图像的信息,设置新图像的文件头的信息,并设置
一个它的颜色表,存放 256 级灰度。将得到的原图的每个像素点的颜色值转换成新图像的灰 度值,存放在新的头像信息中。 保存函数: BOOL SaveFile(CString strFileName, DWORD dwFileLength) 将新的图像信息写入,先写位图头信息,再把实际数据写入。 void CMyDlg::OnButton1() { DWORD dwFileLength; CString strSaveFileName="底片.bmp"; lpNewBmpInfo = (BITMAPINFO*)Reverse(&dwFileLength, lpNewBmpData); if( !lpNewBmpInfo ){ printf( "转换出错,程序退出!\n"); return ; } if( // 位图信息头 if(fileheader.bfType!=0x4D42){ pDC->TextOut(100,200," 无 位 图 文 件请选择位图文件"); fclose(fp); return NULL; } fread(&info.bmiHeader,sizeof(BITMAPINFO HEADER),1,fp); // 颜色表 long width=info.bmiHeader.biWidth; // 位图的宽度,以像素为单位 !SaveFile( strSaveFileName, long height=info.bmiHeader.biHeight; dwFileLength) ){ printf( "保存文件出错!" ); return ; } if( lpNewBmpData != NULL) delete []lpNewBmpData; if( lpNewBmpInfo != NULL ) delete []lpNewBmpInfo; if( lpOldBmp != NULL ) delete []lpOldBmp;} CMyDlg::Reverse(DWORD BYTE* *dwFileLength, BYTE *lpNewBmpData) {if( lpNewBmpData != NULL ){ delete []lpNewBmpData; lpNewBmpData = NULL; } CDC *pDC=m_image2.GetDC(); CRect m_rect; m_image2.GetClientRect(m_rect); FILE *fp=fopen("image8.bmp","r"); if(fp==NULL){ pDC->TextOut(100,200,"no file found"); return NULL; // 位图的高度,以像素为单位 int nScanWidth;//转换后其每行扫描宽度 int nLineWidth; //将其转换成 8 位 位图后每行宽度(即每行字节数) nLineWidth = width*3/4*4; if(nLineWidthbmiHeader=info.bmiHeader; lpNewBmpInfo->bmiHeader.biBitCount=8;
//数据起始位置为原位图信息头起 始+位图信息头大小+彩色表大小 lpNewBmpData (BYTE*)lpNewBmpInfo sizeof(BITMAPINFOHEADER) sizeof(RGBQUAD); + //为其相应的彩色表赋值 for(int i=0;i<256;i++) { = + 256* lpNewBmpInfo->bmiColors[i].rgbRed=i; lpNewBmpInfo->bmiColors[i].rgbGreen=i; lpNewBmpInfo->bmiColors[i].rgbBlue=i; lpNewBmpInfo->bmiColors[i].rgbReserved=0; //保留位} if(info.bmiHeader.biBitCount==8){ int pitch; if(width%4==0){ pitch=width; }else{ } } } } lpNewBmpData[nScanWidth*height]=0; lpNewBmpData[nScanWidth*height+1]=0; if( !CloseHandle( fp ) ) printf("关闭文件时失败"); return (BYTE*)lpNewBmpInfo; } BOOL strFileName,DWORD dwFileLength) { CMyDlg::SaveFile(CString HANDLE = CreateFile( strFileName, GENERIC_WRITE, FILE_SHARE_WRITE, hSaveFile NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); pitch=width+4-width%4;} if( !hSaveFile ){ RGBQUAD quad[256]; fseek(fp,fileheader.bfOffBits-sizeof(RGBQU AD)*256,0); fread(quad,sizeof(RGBQUAD)*256,1,fp); if(height>0){ //height>0 表示图片颠倒 for(i=0;iSetPixel(j,height-i,RGB(r,g,b)); lpNewBmpData[i*nScanWidth+j]=(BYTE)R GB(r,g,b); }}} else{for(int i=0;i<0-height;i++){ for(int j=0;jSetPixel(j,i,RGB(r,g,b)); lpNewBmpData[i*nScanWidth+j]=(BYT E)RGB(r,g,b); 实验前(灰度图) BFH.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) 256* sizeof(RGBQUAD); //256 为 调 色 表 颜 色 数 (0-255) BFH.bfReserved1 = BFH.bfReserved2 = 0; + //写位图头信息 WriteFile( hSaveFile, sizeof(BITMAPFILEHEADER), &dwWriteNum, NULL); &BFH, //写实际数据 WriteFile( hSaveFile, lpNewBmpInfo, dwFileLength, &dwWriteNum, NULL); CloseHandle( hSaveFile ); return TRUE; }
实验后(底片效果) 实验三: 实验题目:将 8 位灰度图均衡化(直方图) 实验任务:将 8 为的灰度图利用直方图的得到的效果,进行均衡化处理,是颜色分布均衡 设计思路:读入文件头和数据信息,共有 256 个灰度级,首先计算各级灰度的比例,将每个 级进行摄入运算,再通过舍入后的信息计算对应每个比例的像素个数,最后写入新的图片。 主要模块: void CMyDlg::OnButton2() { FILE *f=fopen("image8.bmp","rb"); fseek(f,0,0);//移动到开头 //----------读 BMP 文件头 BITMAPFILEHEADER *bmph=new CDC *pDC=m_image2.GetDC(); CRect m_rect; m_image2.GetClientRect(m_rect); BITMAPFILEHEADER();
if(fread((char*)bmph,sizeof(BITMAPFIL for(i=0;i<255;i++) EHEADER),1,f)==NULL){ nh[i]=0.0; printf("File read error"); return; } //-----------读 BMP 信息头 BITMAPINFO *bmpi=new BITMAPINFO(); if(fread((char*)bmpi,sizeof(BITMAPINF O),1,f)==NULL){ printf("File read error2"); return; } //--------------读彩色表 long *c=new long[bmph->bfOffBits-sizeof(BITMAPFILE HEADER)-sizeof(BITMAPINFO)]; fread((char*)c,bmph->bfOffBits-sizeof(BITM APFILEHEADER)-sizeof(BITMAPINFO),1,f) ; if(f==NULL //*判断文件是否打开成功 { printf("File open error"); return; } int i,j,wc; long long *count=new long[255]; //每一灰度 级的象素数量统计 for(i=0;i<255;i++) count[i]=0; for(i=0;ibmiHeader.biWidth; int height=bmpi->bmiHeader.biHeight; //用于循环变量 if(width%4==0)//因为 BMP 图像 4 字节对齐 N=bmph->bfSize- wc=width/4*4; bmph->bfOffBits;//象素总数 else unsigned char *image=new unsigned wc=(width/4+1)*4; char[N]; //位图矩阵 unsigned char *newimage=new unsigned char[N];//变换后的位图矩阵 fread(image,N,1,f);//读入位图矩阵 //---------直方图数列初始化 //------直方图数列用来存储正规化后的灰度 double *h=new double[255];//255 个 灰 度级,保存原始图像正规化灰度直方图数据 for(i=0;i<255;i++) h[i]=0.0; double *nh=new double[255];//255 个灰 度级,保存变换后的图像正规化灰度直方图 处理前(灰度图): } long a; long pos=0; for( i=0;iSetPixel(j,height-i,RGB(a,a,a)); pos++; } } if( !CloseHandle( f ) ) printf("关闭文件时失败");
分享到:
收藏