这段带码只对有的图可以,有的图就是斜的,灰的,还有串位的,应真么改啊void CBitmap2View::OnDraw(CDC* pDC)
{
CBitmap2Doc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
if(str!=""){    //str是文件名
CWnd *m_pMainWnd;
    m_pMainWnd = AfxGetMainWnd();
m_pMainWnd->SetWindowText("显示图片");//改变窗口标题 CFile cf;//文件变量,用来对文件操作
CFileException e;//出错处理
    BITMAPFILEHEADER bmfh;//BMP文件头变量
BITMAPINFOHEADER bmih;//BMP文件信息变量
    RGBTRIPLE *rgb;//24位真彩色数据格式
if (!cf.Open((LPCTSTR)str,CFile::modeRead, &e))//找到文件后,打开文件
{
MessageBox("Can not open the file!","24Open File");
return;
}
cf.SeekToBegin();
cf.Read(&bmfh,sizeof(bmfh));//读取文件头
    cf.Read(&bmih,sizeof(bmih));//读取文件信息头
TRACE("\n%d\n",bmih.biBitCount);
rgb = new RGBTRIPLE[bmih.biWidth*bmih.biHeight];
cf.SeekToBegin();
cf.Seek(54,CFile::begin);//bmp图,54字节后为象素数据 //读取文件数据
if (cf.GetLength()>64*1024)
{
cf.ReadHuge(rgb,bmih.biWidth*bmih.biHeight*3);
}
else
{
cf.Read(rgb,bmih.biWidth*bmih.biHeight);
}
// cf.Read(rgb,bmih.biHeight*dwBytes);
//在屏幕上打点显示图像
for (int i=0; i<bmih.biHeight;i++)
{
for (int j=0; j<bmih.biWidth; j++)
{
         pDC->SetPixel(j,bmih.biHeight-i,RGB(rgb[i*bmih.biWidth+j].rgbtRed,rgb[i*bmih.biWidth+j].rgbtGreen,rgb[i*bmih.biWidth+j].rgbtBlue));
}
} cf.Close();//关闭文件
delete rgb;//释放内存
pDC->TextOut(0,0,"24位真彩色图!");
ReleaseDC(pDC);
     }
}

解决方案 »

  1.   

    bmp图片每行的象素存储时要是4的整数倍数,
    注意到这个就应该不是斜的了!!#define WIDTHBYTES(bits)    (((bits) + 31) / 32 * 4)
      

  2.   

    解决这个问题,你必须了解位图中数据在内存中的存储方式:你用(cf.Seek(54,CFile::begin);//bmp图,54字节后为象素数据)得到的指针是最后一行像素的首地址;
    另外,位图数据中的一行的字节宽度并不是简单的表示为图像的宽度乘像素结构的大小,而是能被4倍整除的最接近width*sizeof(RGB),用宏 WIDTHBYTES(bits)得到;
    关于DIB位图的操作请使用MFC提供的API函数库 其定义在MSDN例子:DIBLOOK 中的dibapi.h,DIBAPI.CPP,myfile.cpp三个文件中.
    还有,在显示位图的时候,不要使用SetPixel(),效率太低,而应当使用API函数SetDIBitsToDevice()具体参数,请查找MSDN
      

  3.   

    又是行填充的问题,行填充算法:
    LPBITMAPFILEHEADER lpfh = (LPBITMAPFILEHEADER)pBuf;
    LPBITMAPINFOHEADER lpih = (LPBITMAPINFOHEADER)(pBuf+sizeof(*lpfh));
    DWORD noRowLength = ((lpih->biWidth*lpih->biBitCount+31)&~31)>>3;
    这样得到的才是每行的字节数。
      

  4.   

    两个地方修改一下,一个地方是读取文件,一次性读入最好,别读两次
    然后利用位图结构找到像素数据。
    注意24位的图象没有颜色表,你读颜色表里的会出错的,直接读就可以了,自己
    用SetPixel()计算bgr顺序的颜色值,记得是bgr不是rgb.
    还有保证每一行是四的整数倍!!
      

  5.   

    计算每行的像素的字节数不能用bmih.biWidth
    先计算其实际的大小:
    DWORD noRowLength = ((lpih->biWidth*lpih->biBitCount+31)&~31)>>3
    用 noRowLength代替bmih.biWidth就可以了
      

  6.   

    啊,
    我这么改的DWORD noRowLength = ((bmih.biWidth*bmih.biBitCount+31)&~31)>>3;
    bmih.biWidth=noRowLength;
    for (int i=0; i<bmih.biHeight;i++)
    {
    for (int j=0; j<bmih.biWidth; j++)
    {
             pDC->SetPixel(j,bmih.biHeight-i,RGB(rgb[i*bmih.biWidth+j].rgbtRed,rgb[i*bmih.biWidth+j].rgbtGreen,rgb[i*bmih.biWidth+j].rgbtBlue));
    }
    不行!然后我又这样改DWORD noRowLength = ((bmih.biWidth*bmih.biBitCount+31)&~31)>>3;
    bmih.biWidth=noRowLength;
    if (cf.GetLength()>64*1024)
    {
    cf.ReadHuge(rgb,bmih.biWidth*bmih.biHeight*3);//
    }
    else
    {
    cf.Read(rgb,bmih.biWidth*bmih.biHeight);
    }
    for (int i=0; i<bmih.biHeight;i++)
    {
    for (int j=0; j<bmih.biWidth; j++)
    {
    还是不行啊
      

  7.   

    路过,帮你写个试试看(只用于24Bit):
    =============================================
    void CBitmap2View::ReadAndShow(CDC* pDC,CString& BmpName)
    {
        CFile file;
        if(!file.Open(BmpName,CFile::modeRead))
            return;
        DWORD dwStart = file.GetPosition();
        BITMAPFILEHEADER bmfh;
        BITMAPINFOHEADER bmih;
        //以下为了方便,省略鉴定..(要鉴定可自己加上)
        file.Read(&bmfh,sizeof(BITMAPFILEHEADER));
        file.Read(&bmih,sizeof(BITMAPINFOHEADER));
        //计算24Bit图象位数据大小
        DWORD dwLen = bmfh.bfSize - bmfh.bfOffBits;
        //申请内存空间
        BYTE *pData = (BYTE *)malloc(dwLen);
        if(!pData)
            return;
        //读入位数据
        file.Seek(dwStart + bmfh.bfOffBits,CFile::begin)
        file.ReadHuge(pData,dwLen);
        file.Close();
        //建一幅空白hbitmap
        void *pBits;
        HBITMAP hBitmap = CreateDIBSection(pDC->m_hDC,(CONST BITMAPINFO *)&bmih,
                                           DIB_RGB_COLORS,&pBits,NULL,0);
        //copy bits data
        memcpy(pBits,pData,dwLen);
        GdiFlush();
        free(pData);
        //now ok..attach to CBitmap then show it..
        CDC *m_pMemDC = new CDC;
        m_pMemDC->CreateCompatibleDC(pDC);
        CBitmap Bitmap,*pOldBitmap;
        Bitmap.Attach(hBitmap);
        pOldBitmap = m_pMemDC->SelectObject(&Bitmap);
        //show it..
        pDC->BitBlt(0,0,bmih.biWidth,bmih.biHeight,m_pMemDC,0,0,SRCCOPY);
        //玩完,释放..
        m_pMemDC->SelectObject(pOldBitmap);
        Bitmap.Detach();
        delete m_pMemDC;
        DeleteObject(hBitmap);
        //ok,good luck,byebye~~~
        //夜渐已深..驱不散,星光引路催促归家,但是我心......
    }
      

  8.   

    ??????????谢谢, lambochan(打杂),用BitBlt()我也会,
    只是……
    这个程序很难吗,没人能改好吗?
      

  9.   

    哦?真的喜欢用SetPixel()么?那偶帮你改改..
    =======================
    //在:rgb = new RGBTRIPLE[bmih.biWidth*bmih.biHeight];
    //这句前面加上判断就ok..    //计算Bmp扫描行字节数
        DWORD BytesPerLine = bmih.biWidth * 3;
        if(BytesPerrLine % 4 != 0)
            BytesPerLine = (BytesPerLine / 4 + 1) * 4;//四字节对齐;
        DWORD dwLen = BytesPerLine * bmih.biHeight;
        rgb = new RGBTRIPLE[dwLen];
        //..............
        //.........
      

  10.   

    sorry,偶看漏了,原来你使用的是RGBTRIPLE结构而不是BYTE,所以偶上面写的属于误导,kaka~~
    不过,用这个结构来读,确实比较麻烦,因为需四字节对齐,而这个结构是3字节的。
    试改如下:
    ================================================    //计算Bmp扫描行字节数
        DWORD BytesPerLine = bmih.biWidth * 3;
        if(BytesPerLine % 4 != 0)
            BytesPerLine = (BytesPerLine / 4 + 1) * 4;//四字节对齐;
        DWORD dwLen = BytesPerLine * bmih.biHeight;
        //申请内存空间
        BYTE *pData = (BYTE *)malloc(dwLen);
        if(!pData)
            return;
        cf.SeekToBegin();
        cf.Seek(54,CFile::begin);//bmp图,54字节后为象素数据
        cf.ReadHuge(pData,dwLen);//先一次读入到内存,然后再转换到RGBTRIPLE数组    rgb = new RGBTRIPLE[bmih.biWidth*bmih.biHeight];//原来的这句是正确的
        //转换
        BYTE *pLine = NULL;
        BYTE *pDesLine = NULL;    for(int Q = 0;Q < bmih.biHeight;++Q)
        {
            //copy one scanline
            pLine = &pData[Q * BytesPerLine];
            pDesLine = &((BYTE *)rgb)[Q * bmih.biWidth];
            memcpy(pDesLine,pLine,bmih.biWidth * 3);
        }
        free(pData);    //然后
        for (int i=0; i<bmih.biHeight;i++)
        {
            for (int j=0; j<bmih.biWidth; j++)
            {
                //.............=========================================================
    这次应该没读取错误了,keke..
    没办法,偶几乎不使用RGBTRIPLE
      

  11.   

    BYTE *pLine = NULL;
        BYTE *pDesLine = NULL;    for(int Q = 0;Q < bmih.biHeight;++Q)
        {
            //copy one scanline
            pLine = &pData[Q * BytesPerLine];
            pDesLine = &((BYTE *)rgb)[Q * bmih.biWidth * 3];//?强制转换需乘3?
            //kaka~~偶也蒙了,讨厌的RGBTRIPLE  >_<
            memcpy(pDesLine,pLine,bmih.biWidth * 3);
        }
      

  12.   

    wo  懂了,
    cf.Seek(54,CFile::begin);//bmp图,54字节后为象素数据
        cf.ReadHuge(pData,dwLen);//
    这句错了,
    谢谢各位了,
    尤其是lambochan(打杂),谢谢你了