win32 MFC 对话框 显示 BMP 文件(二) 可显示单色BMP图

本文介绍如何在Windows 7系统中利用Visual Studio 2010的MFC对话框加载并显示BMP图片。通过具体代码示例展示了不同位深BMP图片的读取和显示过程,包括24位真彩色图片和单色图片。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

win7 64 vs2010
使用vs2010 创建一个MFC 对话框 添加 两个按钮,其实两个按钮的 实现的代码 类似 ,只是 分配内存的地方
一个是用的malloc ,一个是用的HeapAlloc。

看一下具体一个按钮的点击事件:

void CbmpTestBDlg::OnBnClickedBtnBmpTest()
{
    // TODO: 在此添加控件通知处理程序代码


    CString strFileName;
    CString strPathName ;

    LPTSTR  lpstrPath = NULL;
    TCHAR   tszTempPath[_MAX_PATH];

    ZeroMemory(tszTempPath, MAX_PATH);

    GetCurrentDirectory(MAX_PATH, tszTempPath);

    lpstrPath = tszTempPath;



    CFileDialog filedlg(TRUE, NULL, NULL,
                        OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
                        _T("图像(*.bmp)|*.bmp"));

    filedlg.m_ofn.lpstrInitialDir=lpstrPath ; //打开当前文件夹所在目录

    if (filedlg.DoModal() == IDOK){  
        strFileName = filedlg.GetFileName();
        strPathName = filedlg.GetPathName();
    }
    else{

        return;
    }

    printf("strFileName : %S\r\n",strFileName.GetString());

    printf("strPathName : %S\r\n",strPathName.GetString());


    int numQuad;        //调色板的数量 
    int flag;           //是否已打开文件
    int LineBytes;      //LineBytes为每一行的字节数
    BITMAPINFO* pbi;    //BITMAPINFOHEADER  bmiHeader;  RGBQUAD bmiColors[1];  
    BYTE* lpBuf;        //像素数据 B G R 0
    RGBQUAD * quad;     //调色板,每个4字节
    BITMAPINFOHEADER bi;//文件信息 40字节
    BITMAPFILEHEADER bf;//文件头   14字节

    CString filename;
    CFile file;

    BOOL bResult;

    filename=strPathName;

    printf("filename : %S\r\n",filename.GetString());

    if(file.Open(filename,CFile::modeRead|CFile::shareDenyNone,NULL)==0)
    { //读取文件失败
      AfxMessageBox(L"无法打开文件!",MB_OK,0);
      return ;      
    }
    else
    {   file.Read(&bf,sizeof(bf));  //读取文件头,14字节
        if(bf.bfType!=0x4d42)
        {  AfxMessageBox(L"非位图,打开失败!",MB_OK,0);
           return ;
        }
        if(file.GetLength()!=bf.bfSize)
        {
           AfxMessageBox(L"文件损坏,打开失败!",MB_OK,0);
           return ;
        }
        //读取文件信息
        file.Read(&bi,sizeof(bi));     

        printf("bi.biBitCount =%d\r\n",bi.biBitCount);

        if(bi.biBitCount>=24)  //真彩色24或32位,如真彩色图,是不需要调色板的,BITMAPINFOHEADER后直接是位图数据
        {    
            numQuad=0;
        }
        else //2的bi.biBitCount次幂,
        {  
            numQuad=1<<bi.biBitCount; 
        }


        quad=(RGBQUAD*)malloc(numQuad*sizeof(RGBQUAD));
        printf("quad = 0x%x\r\n",quad);
        memset(quad,0,numQuad*sizeof(RGBQUAD));
        if(numQuad!=0){
            file.Read(quad,sizeof(RGBQUAD)*numQuad);
        }



        pbi=(BITMAPINFO*)malloc(sizeof(BITMAPINFOHEADER)+numQuad*sizeof(RGBQUAD));

        printf("pbi = 0x%x\r\n",pbi);

        printf("numQuad = %d \r\n",numQuad);

        memset(pbi,0,sizeof(BITMAPINFOHEADER)+numQuad*sizeof(RGBQUAD));
        memcpy(pbi,&bi,sizeof(bi));

        if(numQuad > 0){

            pbi->bmiColors->rgbRed = 0xFF;
            pbi->bmiColors->rgbBlue = 0xFF ;
            pbi->bmiColors->rgbGreen = 0xFF ;
        }

    //  memcpy(pbi+sizeof(bi),quad,numQuad*sizeof(RGBQUAD));

        //LineBytes为每一行的字节数
        LineBytes=(DWORD)(bi.biWidth*bi.biBitCount+31)*4/32;

        //读取数据
        bi.biSizeImage=bf.bfSize-bf.bfOffBits;
        lpBuf=(BYTE*)malloc(bi.biSizeImage);
            printf("lpBuf = 0x%x\r\n",lpBuf);
        memset(lpBuf,0,bi.biSizeImage);

        file.Read(lpBuf,bi.biSizeImage);        

        //关闭文件
        file.Close();
        flag=1;  //文件已读取标志



    }

     CDC *pDC = GetDC();

     printf("bi.biWidth = %d\r\n",bi.biWidth);
     printf("bi.biHeight = %d\r\n",bi.biHeight);

    if(flag==1) //显示位图
    {   
        SetDIBitsToDevice(pDC->m_hDC,0,0,bi.biWidth,bi.biHeight,0,0,0,bi.biHeight,lpBuf,pbi,DIB_RGB_COLORS);        
    }

    free(quad);

    free(pbi);
    free(lpBuf);
}

运行例子1:

这里写图片描述

运行log:

strFileName : UserImages.bmp
strPathName : E:\VC\workplace\bmpTestB\bmpTestB\UserImages.bmp
filename : E:\VC\workplace\bmpTestB\bmpTestB\UserImages.bmp
bi.biBitCount =24
quad = 0x26b75a8
pbi = 0x2addd78
numQuad = 0
lpBuf = 0x2adffe8
bi.biWidth = 176
bi.biHeight = 15

该图片原图名字为:UserImages.bmp,这个是一个24位的BMP图片。没有调色板。

原图截图如下:(需要原始图片的,请到最后的代码工程下载链接中去找)

这里写图片描述

运行例子2:

这里写图片描述

运行log 如下:

Hello
strFileName : Kitty.bmp
strPathName : E:\VC\workplace\bmpTestB\bmpTestB\Kitty.bmp
filename : E:\VC\workplace\bmpTestB\bmpTestB\Kitty.bmp
bi.biBitCount =1
quad = 0xb0fc20
pbi = 0x9bf120
numQuad = 2
lpBuf = 0xb0fc58
bi.biWidth = 101
bi.biHeight = 46

该图片原图名字为:Kitty.bmp,这个是一个单色的BMP图片。有调色板。

原图截图如下:(需要原始图片的,请到最后的代码工程下载链接中去找)
这里写图片描述

工程源代码:
https://download.youkuaiyun.com/download/wowocpp/10496451

遇到问题:

1, 如果 printf 打印CString的值:

printf("%S\r\n", Str.GetString());    // 不用加_T S 大写

2,例子2 中显示的 单色BMP图 是 反显的
这个方法应该不是很正规。

3, 0x000000 表示 黑色,0xFFFFFF 表示白色

参考网址:

DIB函数注释
https://blog.youkuaiyun.com/u012934099/article/details/23052089

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值