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

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,这个是一个8位的BMP图片。有调色板。

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

工程源代码:
https://download.csdn.net/download/wowocpp/10496451

遇到问题:

1, 如果 printf 打印CString的值:

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

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

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

参考网址:

DIB函数注释
https://blog.csdn.net/u012934099/article/details/23052089

猜你喜欢

转载自blog.csdn.net/wowocpp/article/details/80792908