如题,我读取并显示了一个位图,图像倾斜,并且很多划痕,看到论坛上有人说是4字节对齐问题,我不懂,希望有讲的深刻的,来教育下小弟原图:打开后:

解决方案 »

  1.   

    我是用CDC *pDC = m_Image_repaired.GetDC();
    BITMAPINFO bmpInfo;
    bmpInfo.bmiHeader = bmpInfoHeader;
    HBITMAP  hBitmap = CreateDIBitmap(pDC->m_hDC,&bmpInfoHeader,CBM_INIT,m_pImageData,&bmpInfo,DIB_RGB_COLORS);
    HBITMAP hOldBmp = m_Image_repaired.GetBitmap();
    m_Image_repaired.SetBitmap(hBitmap);来显示,有问题的就是m_pImageData部分,我的对齐代码是int temp_Width = (m_orgWidth*3+3)/4*4;
    int externWidth;
    externWidth =temp_Width - m_orgWidth*3;

    int sizeofbuffer = temp_Width * m_orgHeight;
    int k = 0;
    BYTE* m_pImageTempBuffer = new BYTE[sizeofbuffer];

    for (int n = 1; n <= m_orgHeight ; n++) 
    {
    k = 0;
    for (int m = 0; m < m_orgWidth * 3; m += 3) 
    {
    m_pImageTempBuffer[m_orgWidth*3*(m_orgHeight-n)+k]   = pData[m_orgWidth*3*(m_orgHeight-n)+m]; //blue
    m_pImageTempBuffer[m_orgWidth*3*(m_orgHeight-n)+k+1] = pData[m_orgWidth*3*(m_orgHeight-n)+m+1];//green
    m_pImageTempBuffer[m_orgWidth*3*(m_orgHeight-n)+k+2] = pData[m_orgWidth*3*(m_orgHeight-n)+m+2];//red
    k += 3;
    }
    for(m=0;m<externWidth;m++)
    {
    m_pImageTempBuffer[m_orgWidth*3*(m_orgHeight-n)+k]=255;
    k++;
    }
    }
    delete []pData;
    pData = new BYTE[sizeofbuffer];
    memcpy(pData, m_pImageTempBuffer, sizeofbuffer);
    delete []m_pImageTempBuffer;,m_pImageData就赋值为上述函数返回的pData;
      

  2.   

    我说错了,恩,高没有要求,只是为了采集标清摄像头的视频省事的做法,习惯问题,并非强制4位对齐是对buf而言的,也就是说不管存盘还是显示,你在申请buf的时候,每行4位对齐,用24位位图来说,如果高是2
    如果宽为5,则每行实际占15字节,buf的每行末位只补1个0x00//16-15=1,申请buf时候=4*2
    如果宽为6,则每行实际占18字节,buf的每行末位只补2个0x00//20-18=2,申请buf时候=5*2
    如果宽为7,则每行实际占21字节,buf的每行末位只补3个0x00//24-21=3,申请buf时候=6*2验证方法:用画图做一个1*5的纯白色24位图并存盘,然后用UltraEdit打开
      

  3.   

    再错~~用24位位图来说,如果高是2
    如果宽为5,则每行实际占15字节,buf的每行末位只补1个0x00//16-15=1,申请buf时候=16*2
    如果宽为6,则每行实际占18字节,buf的每行末位只补2个0x00//20-18=2,申请buf时候=20*2
    如果宽为7,则每行实际占21字节,buf的每行末位只补3个0x00//24-21=3,申请buf时候=24*2
      

  4.   

    Windows规定一个扫描行所占的字节数必须是4的倍数(即以long为单位),不足的以0填充,
    我们在开发过程中也用到了3楼的方法:
    int temp_Width = (m_orgWidth*3+3)/4*4;
      

  5.   

    http://nmgwhjl.web-128.com/    
    注册送积分活动开始了!!! 注册即送积分 50! 积分可兑换礼品、免费发信息,免费打广告...
    乌海信息网: 免费发布各类 二手信息、房产交易信息、物品交易信息、征婚、 交友、免费查询,免费发布。
    有你更精彩.......
      

  6.   

    代码给你改好了,这里假设你的pData是没有对齐的,m_pImageTempBuffer是对齐的
    int temp_Width = (m_orgWidth*3+3)/4*4;
        int externWidth;
        externWidth =temp_Width - m_orgWidth*3;
        
        int sizeofbuffer = temp_Width * m_orgHeight;
        //int k = 0;
        BYTE* m_pImageTempBuffer = new BYTE[sizeofbuffer];
        memset(m_pImageTempBuffer,0,sizeofbuffer);
        for (int n = 1; n <= m_orgHeight ; n++) 
        {
            //k = 0;
            for (int m = 0; m < m_orgWidth * 3; m += 3) 
            {
                m_pImageTempBuffer[temp_Width*(m_orgHeight-n)+m]   = pData[m_orgWidth*3*(m_orgHeight-n)+m];    //blue
                m_pImageTempBuffer[temp_Width*(m_orgHeight-n)+m+1] = pData[m_orgWidth*3*(m_orgHeight-n)+m+1];//green
                m_pImageTempBuffer[temp_Width*(m_orgHeight-n)+m+2] = pData[m_orgWidth*3*(m_orgHeight-n)+m+2];//red
                //k += 3;
            }
            //for(m=0;m<externWidth;m++)
            //{
            //    m_pImageTempBuffer[m_orgWidth*3*(m_orgHeight-n)+k]=255;
            //    k++;
            //}
        }
        delete []pData;
        pData = new BYTE[sizeofbuffer];
        memcpy(pData, m_pImageTempBuffer, sizeofbuffer);
        delete []m_pImageTempBuffer;
      

  7.   


    注意这里有假设,如果你的pData是对齐的,就需将
    m_pImageTempBuffer[temp_Width*(m_orgHeight-n)+m]   = pData[m_orgWidth*3*(m_orgHeight-n)+m];    //blue
    改成下面的
    m_pImageTempBuffer[temp_Width*(m_orgHeight-n)+m]   = pData[temp_Width*(m_orgHeight-n)+m];    //bluegreen、red类似处理你要清楚pData中的结构
      

  8.   

    单色BMP图片显示问题 [推荐] 我用了这个帖子上的方法还是不行啊!还在求助中,不放弃
      

  9.   

    验证方法:用画图做一个1*5的纯白色24位图并存盘,然后用UltraEdit打开我在8#已经说了啊,然后在网上找一段代码读BMP文件的代码读这个bmp文件,并显示到体上
    这个东西要自己写一遍才好啊你真的验证了吗?
      

  10.   

    自己做纯白bmp图片,分别做成1*4;1*5;1*6;1*7;1*8
      

  11.   

    // vc2005打开bmp文件,显示并强制另存为24位图
    void CTestGdiDlg::OnBnClickedButton5()
    {
    // 打开bmp文件
    HBITMAP hBitmap = (HBITMAP)LoadImageW(NULL, L"D:\\源图.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE); 
    if(hBitmap == NULL)
    AfxMessageBox(L"LoadImage");
    CBitmap *pBitmap = CBitmap::FromHandle(hBitmap); // 得到图片格式
    BITMAP bmp_info;
    pBitmap->GetBitmap(&bmp_info); // 解析得到24位图的BITMAPINFO
    BITMAPINFO *pBITMAPINFO = (BITMAPINFO*)malloc(sizeof(BITMAPINFOHEADER));
    memset(pBITMAPINFO, 0, sizeof(BITMAPINFOHEADER));
    BITMAPINFOHEADER *pInfo_Header = (BITMAPINFOHEADER *)pBITMAPINFO;
    pInfo_Header->biSize = sizeof(BITMAPINFOHEADER);   
    pInfo_Header->biWidth = bmp_info.bmWidth;   
    pInfo_Header->biHeight = bmp_info.bmHeight;   
    pInfo_Header->biPlanes = 1;   
    pInfo_Header->biBitCount = 24;   
    pInfo_Header->biCompression = BI_RGB;  // 创建兼容DC  选定对象->位图
    CDC dcCompatible;
    dcCompatible.CreateCompatibleDC(NULL);
    dcCompatible.SelectObject(pBitmap); // 把兼容DC贴到DC上
    CDC *pCurDC = this->GetDC();
    pCurDC->BitBlt(0,0,bmp_info.bmWidth, bmp_info.bmHeight,&dcCompatible,0,0,SRCCOPY); // 获得数据buf
    // 4字节对齐 每行所占位数(bmWidth * 3)保证为4的倍数 注意不是像素(bmWidth)保证为4的倍数
    DWORD bufSize = (bmp_info.bmWidth * 3 + 3) / 4 * 4 * bmp_info.bmHeight;
    BYTE * pBuffer = new BYTE[bufSize];
    if(GetDIBits(dcCompatible.GetSafeHdc(), hBitmap, 0, bmp_info.bmHeight, pBuffer,
    pBITMAPINFO, DIB_RGB_COLORS) == 0)
    {
    AfxMessageBox(L"GetDIBits");
    } // 建立文件
    CFile file;
    file.Open(L"D:\\新图.bmp", CFile::modeCreate | CFile::modeWrite | CFile::typeBinary); // 写文件头
    BITMAPFILEHEADER File_Header;
    File_Header.bfType = 0x4d42;
    File_Header.bfOffBits = sizeof(BITMAPFILEHEADER) + pInfo_Header->biSize; 
    File_Header.bfSize = File_Header.bfOffBits + bufSize;   
    File_Header.bfReserved1 = 0;   
    File_Header.bfReserved2 = 0;
    file.Write(&File_Header, sizeof(BITMAPFILEHEADER)); // 写数据头
    file.Write(pInfo_Header, sizeof(BITMAPINFOHEADER)); // 写数据
    file.Write(pBuffer, bufSize); // 关闭文件 释放内存
    file.Close();
    delete []pBuffer;
    free(pBITMAPINFO);
    ::DeleteObject(hBitmap);
    this->ReleaseDC(pCurDC);
    }
      

  12.   

    不是24位真彩色(width*3+3)/4*4不可以,用
    #define WIDTHBYTES(bits)    (((bits) + 31) / 32 * 4)
    代码贴来看看,很简单的。
      

  13.   

    得点积分,4字节对齐就是一行像素字节数必须是4的整数倍。
    假设为灰度位图一个像素一个字节,一行如果是13个像素,那么要四字节对齐,申请空间时这一行要申请16个像素,最后三个像素空着。彩色图像一个像素占3个字节,情况一样。
    主要是微软DIB显示的时候有这个限制
      

  14.   

    我只想获得位图数据,如一个15X20的真彩位图,那么你只要给我每个像素点的的值就行了,
    实在想不通还搞什么位图的四字节。
    明明白白你给我300个值,然后我调用SetPixel输出就可以了。
    这四个字节是为了什么而存在。
    位图储存在硬盘上,也要补齐四个字节吗?,既然没有,输出也同样可以没有,什么补齐四个字节,我看它就是狗屁(虽然我知道这样做肯定有用),但没办法了,我没看到具体用在哪里,只能乱吼几句,也泄我心中的莫名其妙以及想不通,无奈。
    还有什么分配内存的时候,每行多分配四个字节。
    我用的是函数获取硬盘真彩位图的大小,再减54得到多少,就分配多少内存,然后再用ReadFile函数从54字节开始读位图全部的数据,这部分数据是怎么的呢,每行补齐四字节了吗?
    按我所想的,应该每三个字节描述一个像素点,可是老是不对。