首页 > 代码库 > MFC中BMP图片双显和灰度

MFC中BMP图片双显和灰度

<一>. Bmp图片双显和灰度原理

     为了方便后续的量化采样处理,这里首先要实现bmp图片双显的功能,即在menu的左边显示原图,把原图的文件头数据和信息头数据保存在全局变量数组中;同时建立一个临时的”picture.bmp”图片(默认保存路径在打开原图的位置),以后的操作对临时的图片进行处理。

什么叫灰度图?任何颜色都有红、绿、蓝三原色组成,假如原来某点的颜色为RGB(RGB),那么,我们可以通过下面几种方法,将其转换为灰度:

      浮点算法:Gray=R*0.3+G*0.59+B*0.11;
      整数方法:Gray=(R*30+G*59+B*11)/100;
      移位方法:Gray =(R*28+G*151+B*77)>>8;
      平均值法:Gray=R+G+B/3;(此程序采用算法);
      仅取绿色:Gray=G
    通过上述任一种方法求得Gray后,将原来的RGB(R,G,B)中的R,G,B统一用Gray替换,形成新的颜色RGB(Gray,Gray,Gray),用它替换原来的RGB(R,G,B)就是灰度图了。

2  改变象素矩阵的RGB值,来达到彩色图转变为灰度图

加权平均值算法:根据光的亮度特性,其实正确的灰度公式应当是

      R=G=B=R*0.299+G*0.587+B0.144;

为了提高速度我们做一个完全可以接受的近似,公式变形如下:R=G=B=(R*3+G*6+B)/10  ;

 

<>.MFC实现双显和灰度

 

第一步:建立标记位

 

1.View.cpp文件中显示函数前建立标记位,即:

 

void CBmpDrawView::ShowBitmap(CDC *pDC,CString BmpName)前添加:/*****************************************************//*   numPicture=0时显示提示错误信息                  *//*   numPicture=1时显示1张图片在OnFileOpen中定义     *//*   numPicture=2时显示2张图片和处理在处理函数中定义 */ /*****************************************************//*****************************************************//*   level=0时显示2张图片                            *//*   level=1时显示灰度图片                           *//*   level=3时显示图片采样                           *//*   level=2 4 8 16 32 63时不同量化级量化图片        */ /*****************************************************/int numPicture=0;       //显示图片数 int level=0;            //显示量化等级

2.在View.h中建立处理图像的副本文件和默认路径:

CBitmap m_bitmaplin;//创建临时位图对象进行处理CString BmpNameLin; //保存图像的副本文件 原工程中

3.在View.cpp的OnFileOpen文件打开函数中初始化标记变量:

void CBmpDrawView::OnFileOpen()中添加:if( dlg.DoModal() == IDOK )    {        //获取路径 文件名 扩展文件名        BmpName = dlg.GetPathName();        BmpNameLin = "picture.bmp";                AfxMessageBox("图片打开成功",MB_OK,0);        numPicture=1;        EntName = dlg.GetFileExt();         EntName.MakeLower();    //小写字符串        Invalidate();    }

第二步:报错处理

指的是在没有载入图片(numPicture=0)时就按保存按钮,或双显、灰度、量化、采样按钮,就会提示相应的错误提示。因为在打卡图片OnFileOpen函数中令numPicture=1初始化才能显示图片及处理。

在View.cpp中的函数void CBmpDrawView::OnFileSave()中最前面增加代码如下:

//如果没有导入图片直接点击保存 提示信息    if(numPicture==0){        AfxMessageBox("载入图片后才能保存图片!",MB_OK,0);         return;    }

第三步:增加双显菜单

a.将试图切换到ResourceView界面--选中Menu--在IDR_MAINFRAME中添加菜单“显示”--双击它在菜单属性中选择“弹出”

b.在“显示”的子菜单中添加:

双图显示--ID_SHOW_TWO(ID)--默认属性

灰度图片--ID_SHOW_HD(ID)--默认属性

第四步:实现双显

查看--建立类导向(Ctrl+W)--CBmpDrawView(类名)--ID_SHOW_TWO-- COMMAND(Messages)--默认成员函数名。

添加代码:

/*显示2张图片*/void CBmpDrawView::OnShowTwo() {    // TODO: Add your command handler code here    //如果没有导入图片直接点击显示2张图片 提示信息    if(numPicture==0)    {        AfxMessageBox("载入图片后才能显示2张图片!");        return;    }    AfxMessageBox("显示两张图片!",MB_OK,0);    numPicture = 2;              //全局变量=2显示双图、=1显示一图 、=0无图显示    level=0;                    //level=0双图显示    Invalidate();               //调用Invalidata()每秒调用一次OnDraw画图}

第五步:实现灰度图片

查看--建立类导向(Ctrl+W)--CBmpDrawView(类名)--ID_SHOW_HD(ID)-- COMMAND(Messages)--默认成员函数名。

添加代码:

/*灰度图像就是 R=G=B且为三者的1/3 level=1时灰度图像*/void CBmpDrawView::OnShowHd() {    //如果没有导入图片直接点击灰度 提示信息    if(numPicture==0){        AfxMessageBox("载入图片后才能灰度图片!",MB_OK,0); return;    }    AfxMessageBox("灰度图像!",MB_OK,0);FILE *fpo = fopen(BmpName,"rb");    FILE *fpw = fopen(BmpNameLin,"wb+");    fread(&bfh,sizeof(BITMAPFILEHEADER),1,fpo);    fread(&bih,sizeof(BITMAPINFOHEADER),1,fpo);    fwrite(&bfh,sizeof(BITMAPFILEHEADER),1,fpw);    fwrite(&bih,sizeof(BITMAPINFOHEADER),1,fpw);    /*灰度图像处理r=g=b=(r+g+b)/3*/    int color,red,green,blue;    for( int i=0; i<m_nWidth*m_nHeight; i++ )    {        fread(&red,sizeof(char),1,fpo);        fread(&green,sizeof(char),1,fpo);        fread(&blue,sizeof(char),1,fpo);        color=(red+green+blue)/3;        red=color; green=color; blue=color;        fwrite(&red,sizeof(char),1,fpw);        fwrite(&green,sizeof(char),1,fpw);        fwrite(&blue,sizeof(char),1,fpw);    }    fclose(fpo); fclose(fpw);    numPicture = 2;    level=1;    Invalidate();}

第六步:添加代码在ShowBitmap显示处理修改

/*显示BMP格式图片 双显灰度功能*/void CBmpDrawView::ShowBitmap(CDC *pDC, CString BmpName){        HBITMAP m_hBitmap;    m_hBitmap = (HBITMAP) LoadImage(NULL,BmpName,IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_DEFAULTSIZE|LR_CREATEDIBSECTION);    if( m_bitmap.m_hObject ){ m_bitmap.Detach();}    m_bitmap.Attach(m_hBitmap);        CRect rect;    GetClientRect(&rect);    int m_nWindowWidth = rect.right - rect.left;   //计算客户区宽度    int m_nWindowHeight = rect.bottom - rect.top;  //计算客户区高度            CDC dcBmp;    if( !dcBmp.CreateCompatibleDC(pDC) )           return;        BITMAP m_bmp;    m_bitmap.GetBitmap(&m_bmp);     CBitmap *pbmpOld = NULL;    dcBmp.SelectObject(&m_bitmap);            if(m_nDrawWidth<650 && m_nDrawHeight<650)pDC->StretchBlt(0,0,m_nDrawWidth,m_nDrawHeight,&dcBmp,0,0,m_bmp.bmWidth,m_bmp.bmHeight,SRCCOPY);    elsepDC->StretchBlt(0,0,640,640,&dcBmp,0,0,m_bmp.bmWidth,m_bmp.bmHeight,SRCCOPY);          dcBmp.SelectObject(pbmpOld);                DeleteObject(&m_bitmap);                 dcBmp.DeleteDC();                              /*显示第2张图片*/    if( numPicture == 2 )    {        HBITMAP m_hBitmapChange;        if(level==0)      //显示2张图        {            m_hBitmapChange = (HBITMAP) LoadImage(NULL,BmpName,IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_DEFAULTSIZE|LR_CREATEDIBSECTION);        }        else if(level==1) //灰度图片        {            m_hBitmapChange = (HBITMAP) LoadImage(NULL,BmpNameLin,IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_DEFAULTSIZE|LR_CREATEDIBSECTION);        }                if( m_bitmap.m_hObject ){ m_bitmap.Detach(); }        m_bitmap.Attach(m_hBitmapChange);        CDC dcBmp;        if( !dcBmp.CreateCompatibleDC(pDC) )                   return;                BITMAP m_bmp;                                  m_bitmap.GetBitmap(&m_bmp);                    CBitmap *pbmpOld = NULL;        dcBmp.SelectObject(&m_bitmap);                 /*图片显示调用函数StretchBlt */        if(m_nDrawWidth<650 && m_nDrawHeight<650)pDC->StretchBlt(m_nWindowWidth-m_nDrawWidth,0,m_nDrawWidth,m_nDrawHeight,&dcBmp,0,0,m_bmp.bmWidth,m_bmp.bmHeight,SRCCOPY);        elsepDC->StretchBlt(m_nWindowWidth-640,0,640,640,&dcBmp,0,0,m_bmp.bmWidth,m_bmp.bmHeight,SRCCOPY);  //显示大小为640*640        dcBmp.SelectObject(pbmpOld);           //恢复临时DC的位图    }}

 

 

 

 

 

 

MFC中BMP图片双显和灰度