为什么我提取出来的位图为有偏移的现象.看了全部程序也没找出原因!!就是横向有偏移!!象素的点应该是从下自上,从左至右的吧.我现在就是从中间靠左一点开始描一样的!!描到最后再把前面的描上.发生错位了.现象就是这样!!
不知道大家有没有出现这种问题啊??需要帮忙解决!
谢谢了!!

解决方案 »

  1.   

    BMP有个填充象素你有没有考虑到?就是BMP文件规定行的象素数是4的倍数,不足的要填充,你没有考虑这个的话描绘出来的图像就有可能是倾斜的.我给你代码,里面的skip就是计算填充的.
    //------------读灰度BMP文件,返回data 为正向存储的矩阵.
    bool  ReadBMP(char *file,BITMAPFILEHEADER_ *bmph,BITMAPINFO_ *bmpi,unsigned char **data)
    {
            int i,pos;        FILE *f=fopen(file,"rb");        if(f==NULL)             //判断文件是否打开成功
            {
                    return false;
            }        fseek(f,0,0);//移动到开头        //----------读BMP文件头
            if(fread((char*)bmph,sizeof(BITMAPFILEHEADER_),1,f)==NULL)
            {
                 return false;
            }        //-----------读BMP信息头
            if(fread((char*)bmpi,sizeof(BITMAPINFO_),1,f)==NULL)
            {
                    return false;
            }        fseek(f,bmph->Offbits,0);           //定位位图矩阵        int skip=0;            //填充象素数
            if(bmpi->width%4==0)
                    skip=0;
            else
                    skip=4-bmpi->width%4;        long N=(bmpi->width)*(bmpi->height);//有效象素总数
            *data=(unsigned char*)malloc(N);
            for(i=0;i<(bmpi->width)*(bmpi->height);i++)    //清空,变白色.
            {
                    (*data)[i]=0xff;
            }        unsigned char waste[8];
            pos=N-bmpi->width;
            for(i=0;i<bmpi->height;i++)           //读入位图矩阵
            {
                    fread(&(*data)[pos],bmpi->width,1,f);
                    fread(waste,skip,1,f);
                    pos=pos-bmpi->width;
            }
            
            fclose(f);        return true;
    }
      

  2.   

    想来是字节对齐的原因。
    每一行的像素数据宽度并非简单的是点数*色深/8;还需要对DWORD对齐。
      

  3.   

    我的代码如下.是画出位图的函数!
    void CBaseGdi::DrawBmp(CDC* pDC,int x,int y,int wide,int high,CString fName)
    {
    LPVOID hBmpData;
    HPALETTE hpal;
    HBITMAP bhm_ddb;
    int NumbColors; BITMAPFILEHEADER bFileH;
    BITMAPINFOHEADER bFileInfoH;
    LPBITMAPINFOHEADER lpFileInfoH;
    CFile FileBmp;
    CBitmap* pOldMap;
    CDC pDC1;
    int wide1,high1;
    long bytes_per_line;
    long BmpSize;
    long ImageSize; BOOL YN=FileBmp.Open(fName,CFile::typeBinary|CFile::modeRead);
    if(YN==0)
    {
    AfxMessageBox("Not Open File!");
    return;
    } FileBmp.Read((unsigned char*)&bFileH,sizeof(BITMAPFILEHEADER));
    if(bFileH.bfType!=19778)
    {
    FileBmp.Close();
    AfxMessageBox("Not A Bitmap File!");
    return;
    }
    FileBmp.Read((unsigned char*)&bFileInfoH,sizeof(BITMAPINFOHEADER));
    // BmpSize=bFileH.bfSize-sizeof(BITMAPFILEHEADER);
    bytes_per_line=(long)((bFileInfoH.biWidth*bFileInfoH.biBitCount+31)/32*4);
    ImageSize=(long)(bytes_per_line*bFileInfoH.biHeight);
    if(bFileInfoH.biClrUsed!=0)
    NumbColors=bFileInfoH.biClrUsed;
    else
    {
    switch(bFileInfoH.biBitCount)
    {
    case  1: NumbColors=2; break;
    case  4: NumbColors=16; break;
    case  8: NumbColors=256; break;
    case 24: 
    {
    // NumbColors=0; 
    FileBmp.Close();
    AfxMessageBox("本系统最多支持256色位图!");
    return;
    // break;
    }
    default: NumbColors=2; break;
    }
    }
    if(bFileH.bfOffBits!=(DWORD)(NumbColors*sizeof(RGBQUAD)+sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)))
    {
          AfxMessageBox("The NumbColors is Wrong!");
          FileBmp.Close();
    return;
    }
    bFileH.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+
                     NumbColors*sizeof(RGBQUAD)+ImageSize;
    BmpSize=bFileH.bfSize-sizeof(BITMAPFILEHEADER); if((hBmpData=GlobalAlloc(GHND,BmpSize))==0)
    {
    AfxMessageBox("The Memory is Wrong!");
    FileBmp.Close();
    return;
    }
    lpFileInfoH=(LPBITMAPINFOHEADER)GlobalLock(hBmpData); 
    FileBmp.Seek(sizeof(BITMAPFILEHEADER),CFile::begin);
    FileBmp.Read((unsigned char*)lpFileInfoH,BmpSize); if(NumbColors>0)//NumColors不为零,说明用到了调色板
    {
    //为逻辑调色板分配局部内存,大小为逻辑调色板结构长度加NumColors个PALETTENTRYLPLOGPALETTE cp=(LPLOGPALETTE)LocalAlloc(LHND,sizeof(LPLOGPALETTE)+NumbColors*sizeof(PALETTEENTRY)); if(cp!=NULL)
    {
    cp->palVersion=0x0300;
    cp->palNumEntries=NumbColors;
    //p_bi指向的是调色板开始的位置
    LPRGBQUAD    p_bi= (LPRGBQUAD)((LPSTR)lpFileInfoH +(DWORD)sizeof(BITMAPINFOHEADER));
    for(int k=0;k<NumbColors;k++)
    {
    cp->palPalEntry[k].peRed=p_bi->rgbRed;
    cp->palPalEntry[k].peGreen=p_bi->rgbGreen;
    cp->palPalEntry[k].peBlue=p_bi->rgbBlue;
    p_bi++; 
    }
    //产生逻辑调色板 hpal=CreatePalette(cp);
    LocalFree(cp);
    }
    }
    HPALETTE pOldHpal=NULL;
    if(hpal)//如果刚才产生了逻辑调色板
    {
    //将新的逻辑调色板选入DC,将旧的逻辑调色板句柄保存在//pOldHpal pOldHpal=SelectPalette(pDC->GetSafeHdc(),hpal,FALSE);
    RealizePalette(pDC->GetSafeHdc());
    }
    LPSTR p_image=(LPSTR)lpFileInfoH+sizeof(LPBITMAPINFOHEADER)+NumbColors*sizeof(RGBQUAD);
    //产生位图句柄
    bhm_ddb=CreateDIBitmap(pDC->GetSafeHdc(),lpFileInfoH,CBM_INIT,p_image,(LPBITMAPINFO)lpFileInfoH,DIB_RGB_COLORS);

    //将原来的调色板(如果有的话)选入设备上下文句柄 if(pOldHpal)
    {
    SelectPalette(pDC->GetSafeHdc(),pOldHpal,FALSE);
    hpal=0;
    } wide1=wide;
    high1=high;
    if(bhm_ddb!=0)
    {
    pDC1.CreateCompatibleDC(pDC);
    pOldMap=pDC1.SelectObject(CBitmap::FromHandle(bhm_ddb));
            pDC->StretchBlt(x,y,wide1,high1,&pDC1,0,0,lpFileInfoH->biWidth,lpFileInfoH->biHeight,SRCCOPY);
    pDC1.SelectObject(pOldMap);
    } GlobalUnlock(hBmpData); 
    GlobalFree(hBmpData); 
    FileBmp.Close();
    return;}
      

  4.   

    还有个问题,我经常会在LocalFree(cp);后出现错误,请高手门看看这段代码是否有错误?
    还有字节对齐问题!,请教一下该怎么对齐呢??不太懂!!望告知!
      

  5.   

    请问上面的大姐或兄弟,fread(waste,skip,1,f);这句是干什么用的啊??
      

  6.   

    就是读填充的字节啊,BMP文件如果行象素数不是4的倍数就会在文件里填入不足的字节,这句就是读这个填充字节,读到waste里扔掉的啊,不要填充字节嘛,相信你就是要了这个填充字节才出现倾斜得.
    伤心得说不出话了...........
      

  7.   

    void CBitmapButtons::GetBitMapData()
    {
    if(m_PreFilePathName == m_FilePathName[m_ButtonState])
    return; LPVOID hBmpData; BITMAPFILEHEADER  bFileH;
    BITMAPINFOHEADER  bFileInfoH; DWORD bytes_per_line; CFile BitMapFile;

    BOOL YN=BitMapFile.Open(m_FilePathName[m_ButtonState],CFile::modeRead | CFile::typeBinary);
    if(YN==0)
    {
    AfxMessageBox("该文件不存在,请检查!");
    m_FilePathName[m_ButtonState] = m_PreFilePathName;
    return;
    } m_PreFilePathName = m_FilePathName[m_ButtonState]; BitMapFile.Read((unsigned char*)&bFileH,sizeof(BITMAPFILEHEADER));
    if(bFileH.bfType!=19778)
    {
    BitMapFile.Close();
    AfxMessageBox("Not A Bitmap File!");
    return;
    } BitMapFile.Read((unsigned char*)&bFileInfoH,sizeof(BITMAPINFOHEADER)); m_BMPWidth[m_ButtonState] = bFileInfoH.biWidth;
    m_BMPHeight[m_ButtonState] = bFileInfoH.biHeight; switch(bFileInfoH.biBitCount)
    {
    case 1:  m_BMPType[m_ButtonState] = 0; break;
    case 4:  m_BMPType[m_ButtonState] = 1; break;
    case 8:  m_BMPType[m_ButtonState] = 2; break;
    case 24: 
    {
    // m_BMPType = 3; BitMapFile.Close();
    AfxMessageBox("本系统最多支持256色位图!");
    return;
    }
    } m_BMPSize[m_ButtonState]=bFileH.bfSize-sizeof(BITMAPFILEHEADER);
    bytes_per_line=(DWORD)((bFileInfoH.biWidth*bFileInfoH.biBitCount+31)/32*4);
    //有效象素总数
    m_BMPImageSize[m_ButtonState]=(DWORD)(bytes_per_line*bFileInfoH.biHeight);
    // m_BMPImageSize = bFileInfoH.biSizeImage;
    if(bFileInfoH.biClrUsed!=0)
    m_NumbColors[m_ButtonState]=bFileInfoH.biClrUsed;
    else
    {
    switch(bFileInfoH.biBitCount)
    {
    case  1: m_NumbColors[m_ButtonState]=2; break;
    case  4: m_NumbColors[m_ButtonState]=16; break;
    case  8: m_NumbColors[m_ButtonState]=256; break;
    case 24: m_NumbColors[m_ButtonState]=0; break;
    default: m_NumbColors[m_ButtonState]=2; break;
    }
    }
    if(bFileH.bfOffBits!=(DWORD)(m_NumbColors[m_ButtonState]*sizeof(RGBQUAD)+sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)))
    {
    AfxMessageBox("The NumbColors is Wrong!");
    BitMapFile.Close();
    return;
    }
    bFileH.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+
                     m_NumbColors[m_ButtonState]*sizeof(RGBQUAD)+m_BMPImageSize[m_ButtonState];
    m_BMPSize[m_ButtonState]=bFileH.bfSize-sizeof(BITMAPFILEHEADER); if((hBmpData=GlobalAlloc(GHND,m_BMPSize[m_ButtonState]))==0)
    {
    AfxMessageBox("The Memory is Wrong!");
    BitMapFile.Close();
    return;
    }
    lpFileInfoH[m_ButtonState]=(LPBITMAPINFOHEADER)GlobalLock(hBmpData);  BitMapFile.Seek(sizeof(BITMAPFILEHEADER),CFile::begin);
    BitMapFile.Read((unsigned char*)lpFileInfoH[m_ButtonState],m_BMPSize[m_ButtonState]);
    ///*
    // LPSTR STR = ((LPSTR)lpFileInfoH)+8;
    //*/
    BitMapFile.Close();}
      

  8.   

    上面的这段是我的读取位图的函数!!我是已经算好了.行象素已经是4的整数倍了!!!但我没有进行清空变白!!是不是这个问题??我现在是整块而且很整齐的移位了.而不是杂乱的.上面的兄弟姐妹们,能不能解释以下啊??
    sboom(+-LingCh-+)(怪你过分美丽) 能否留个联系方法!!我可以多向你请教!!谢谢
      

  9.   


    >>我经常会在LocalFree(cp);后出现错误
    cp 使用 LHND 分配的,LHNM = LMEM_MOVEABLE |  LMEM_ZEROINIT.
    由于是Moveable, 所以需要先Lock再使用。像素错位:
    LPSTR p_image=(LPSTR)lpFileInfoH+sizeof(LPBITMAPINFOHEADER)+NumbColors*sizeof(RGBQUAD);就是这儿啦,结构错写成了指针。
    结果 sizeof(LPBITMAPINFOHEADER) = 4。眼睛都看花了......
      

  10.   

    太感谢whoo(谁) 了.象素错位就是你说的那个地方!!改了就可以了.谢谢大家了!!