在MFC中,不借用其他的库函数读取BMP图像,显示,也可以重新生成

void CReadBMPImageAndShowView::OnOpenimage()
{
    // TODO: 在此添加命令处理程序代码
    CFileDialog log(true,"file",NULL,OFN_HIDEREADONLY,
        "bmp|*.bmp||",NULL);
    if(log.DoModal() == IDOK)
    {
        PathName = log.GetPathName();
    }

    int i=0;
    CFile m_file;
    BITMAPFILEHEADER P_image = {0,0,0,0,0};//文件头参数
    BITMAPINFOHEADER *P_infor = NULL;//信息头参数指针
    PVOID P_colortable = NULL;//定义文件颜色表指针
    PBYTE *tuxiangshuju;  //图像数据指针
    if(m_file.Open(PathName,CFile::modeReadWrite)==0)
    {
        return ;
    }
    // m_file.SeekToBegin();
    if(!m_file.Read(&P_image,sizeof(BITMAPFILEHEADER)))
    {
        return ;
    }
    if(P_image.bfType != MAKEWORD('B','M'))
    {
        return ;
    }
    CString Str = "";
    CString TempStr;
    TempStr.Format("类型%d\n文件大小%ld\n偏移量%ld\n",P_image.bfType,P_image.bfSize,P_image.bfOffBits);
    Str = Str + TempStr;
    /*printf("类型%d\n",P_image.bfType);
    printf("文件大小%ld\n",P_image.bfSize);
    printf("偏移量%ld\n",P_image.bfOffBits);*/
    // m_file.Seek(sizeof(BITMAPFILEHEADER),CFile::begin);
    P_infor = new BITMAPINFOHEADER [sizeof(BITMAPINFOHEADER)];
    if(!m_file.Read(P_infor,sizeof(BITMAPINFOHEADER)))
    {
        delete [] P_infor;
        return ;
    }
    int colorcount = (P_image.bfOffBits - sizeof(BITMAPFILEHEADER) - sizeof(BITMAPINFOHEADER)) / sizeof(RGBQUAD);
    if(colorcount >= 1)             //说明调色板是存在的
    {

        P_colortable = rgb;
//      P_colortable = new BYTE [colorcount * sizeof(RGBQUAD)];
        m_file.Seek(P_image.bfOffBits - sizeof(RGBQUAD) * colorcount,CFile::begin);
        m_file.Read(P_colortable,colorcount * sizeof(RGBQUAD));
    }
    int nwidthcount = quzheng(P_infor->biWidth , P_infor->biBitCount);
    /*printf("每行像素空间字节数%d\n",nwidthcount);
    printf("图像高度%d\n",P_infor->biHeight);
    printf("图像宽度%d\n",P_infor->biWidth);
    printf("每个像素使用的二进制位数%d\n",P_infor->biBitCount);*/
    TempStr.Format("每行像素空间字节数%d\n图像高度%d\n图像宽度%d\n每个像素使用的二进制位数%d\n",
                    nwidthcount,P_infor->biHeight,P_infor->biWidth,P_infor->biBitCount);
    Str += TempStr;
    tuxiangshuju = new PBYTE [(P_infor->biHeight)];
    m_file.Seek(P_image.bfOffBits,CFile::begin);
    for(i = 0;i < (P_infor->biHeight);i++)
    {
        tuxiangshuju[i] = new BYTE[nwidthcount];
        m_file.Read(tuxiangshuju[i],nwidthcount);
    }

    //if(colorcount != 0)   //对于单波段图像
    //{

    //  TempStr.Format("%d",*((BYTE*)P_colortable+25*4));
    //  MessageBox(TempStr);
    //}

//  cleanup();
    FileHeader = P_image;
    InfoHeader = P_infor;
    ImageDate = tuxiangshuju;
    ColorTable = P_colortable;   
    ColorTableCount = colorcount;
// fclose(fp);
    m_file.Close();
//  delete m_file;
    CClientDC dc(this);
    DrawImage(&dc);     //在view中画出来
    MessageBox(Str);
//  Invalidate();
    return;

}
//每一行字节数为四的整数倍
int CReadBMPImageAndShowView::quzheng(LONG Width, DWORD bitCount)
{
    int BitNumOfWidth = (Width * bitCount  + 31) / 32 * 4;
    return BitNumOfWidth;
}
//int SetDIBitsToDevice(HDC hdc, int xDest, int Ydest, DWORD dwWidth, DWORD dwHeight, intXSrc, int Ysrc, UINT uStartScan, UINT cScanLines, CONST VOID *lpvBits, CONST BITMAPINFO *lpbmi, UINT fuColorUse);
//参数定义如下:
//  hdc:设备环境句柄
//  XDest,  YDest  :显示在屏幕上面的左上角点的坐标。
//  dwWidth:图像宽度。
//  dwHeight:图像高度。
//  XSrc ,YSrc : 图像的起始坐标 ,一般此处为 0  0  。      /*其实, XSrc ,YSrc dwWidth dwHeight便是将图像的矩形确定出来*/
//  uStartScan: 指定DIB中的起始扫描线,此处一般为 0 。
//  cScanLInes: 指定参数lpvBits指向的数组中包含的DIB扫描线数目。   /*说白了就是图像的高度*/
//  lpvBits: 指向存储DIB颜色数据的字节类型数组的指针。
//  lpbmi: 指向BITMAPINFO结构的指针,该结构包含有关DIB的信息。
//  fuColorUse: 指向BITMAPINFO结构中的成员bmiColors是否包含明确的RGB值或对调色板进行索引的值。有关更多的信息,请参考下面的备注部分。
//  参数fuColorUse必须是下列值之一,这些值的含义如下:
//      DIB_PAL_COLORS:表示颜色表由16位的索引值数组组成,利用这些值可对当前选中的逻辑调色板进行索引。
//      DIB_RGB_COLORS:表示颜色表包含原义的RGB值。
/*特别注意:由于默认的显示坐标系与我们正常的坐标系是相反的,所以如果仅仅用此函数正常显示出来,图像是倒立的,如何调整见程序*/


void CReadBMPImageAndShowView::DrawImage(CDC* pDC)
{
    if(ImageDate==NULL)
    {
        MessageBox("未获得图像数据");
        return ;
    }

    //生活总是如此的出人意料,就这样碰运气的,也显示出了灰度图像。
    //大概可以理解为非24位真彩需要制定调色板,然后SetDIBitsToDevice函数会从图像数据索引自动调用调色板
    //对于24位真彩来说,SetDIBitsToDevice函数并不调用调色板的数据,直接显示图像数据。
    unsigned char hBitMapInfo[sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)* 256];
    BITMAPINFO *BitMapInfo=(BITMAPINFO *) hBitMapInfo;  
    //for(int i=0;i<256;i++)  
    //{  
    //  BitMapInfo->bmiColors[i].rgbBlue = i;  
    //  BitMapInfo->bmiColors[i].rgbGreen = i; 
    //  BitMapInfo->bmiColors[i].rgbRed = i;
    //  BitMapInfo->bmiColors[i].rgbReserved = i;
    //}
    if(ColorTableCount != 0)
        memcpy(&BitMapInfo->bmiColors,ColorTable,sizeof(RGBQUAD) * 256);
    memcpy(&BitMapInfo->bmiHeader,InfoHeader,sizeof(BITMAPINFOHEADER));
    //通过SetDIBitsToDevice函数将图像数据显示到显示器
    for(int i = 0;i < InfoHeader->biHeight;i++)
    {
        ::SetDIBitsToDevice(*pDC, 0, 0, InfoHeader->biWidth, 
            InfoHeader->biHeight, 0, 0, i, 1,ImageDate[i], (BITMAPINFO*)BitMapInfo, DIB_RGB_COLORS);
    }

    return ;

}
//对图像进行显示的另外一种办法,dc.setpixel(..),利用了双缓冲,但是速度很慢,而且暂时不知道如何显示灰度图像
void CReadBMPImageAndShowView::DrawImage(CDC* pDC)
{
    if(ImageDate==NULL)
    {
        MessageBox("未获得图像数据");
        return ;
    }

    COLORREF color;
    int Width = InfoHeader->biWidth;
    int Height = InfoHeader->biHeight;
    int WidthCount = quzheng(InfoHeader->biWidth , InfoHeader->biBitCount);

    CRect rectClient;
    this->GetClientRect(rectClient);
    CDC memDC;                                              //定义一个显示设备对象
    CBitmap bmp;                                            //定义一个位图对象 
    memDC.CreateCompatibleDC(pDC);                          //建立与屏幕显示兼容的内存显示设备
    bmp.CreateCompatibleBitmap(pDC,Width,Height);           //建立一个与屏幕显示兼容的位图
    memDC.SelectObject(&bmp);                               //将位图选入到内存显示设备中
    memDC.FillSolidRect(rectClient,RGB(255,255,255));
    if(WidthCount != Width) //仅仅用来显示24位真彩
    {
        for(int i = 0;i < Height;++i)
        {
            for(int j = 0;j < WidthCount;j = j + 3)
            {
                color = RGB(ImageDate[i][j + 2],ImageDate[i][j + 1],ImageDate[i][j]);
                memDC.SetPixel(j / 3,Height - i - 1,color);

            }
        }
    }
    else//为灰度图时
    {
        MessageBox("此办法暂时不知道如何显示灰度图");
        bmp.DeleteObject(); 
        memDC.DeleteDC();
        return ;
    }

    //将内存中的图拷贝到屏幕上进行显示 
    pDC->BitBlt(0,0,Width,Height,&memDC,0,0,SRCCOPY);
    //绘图完成后的清理 
    bmp.DeleteObject(); 
    memDC.DeleteDC();


    return ;

}
//重新生成BMP文件
void CReadBMPImageAndShowView::OnCreateimage()
{
    // TODO: 在此添加命令处理程序代码
    CString Str = "";
    CFileDialog log(true,"file",NULL,OFN_HIDEREADONLY,"bmp|*.bmp||",NULL);
    int flag = 0;
    do
    {
        if(flag == 1)
            MessageBox("请输入正确的文件类型");
        if(log.DoModal() == IDOK)
        {
            Str = log.GetFileExt();
            flag = 1;
        }
    } while (Str != "bmp");

    PathName = log.GetPathName();

    //int len = PathName.ReverseFind('.');
    //PathName = PathName.Left(len);
    CFile File;

    if(File.Open(PathName,CFile::modeCreate | CFile::modeReadWrite)==0)
    {
        return ;
    }

    File.Write(&FileHeader,sizeof(BITMAPFILEHEADER));
    File.Write(InfoHeader,sizeof(BITMAPINFOHEADER));
    if(ColorTableCount != 0)
        File.Write(ColorTable,ColorTableCount * sizeof(RGBQUAD));
    int nwidthcount = quzheng(InfoHeader->biWidth , InfoHeader->biBitCount);
    for(int i = 0;i < (InfoHeader->biHeight);i++)
    {
//      ImageDate[i] = new BYTE[nwidthcount];
        File.Write(ImageDate[i],sizeof(BYTE) * nwidthcount);
    }

    File.Close();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值