DIB位图问题

zjz800800 2008-10-14 12:28:36

1.DWORD m_dwDdbWidthBytes=((m_nWidth*24+15)/16)*2;
m_nWidth为1.4.8位DIB位图宽度
公式如何来的?

我看到以前有人回答是:

*24/16*2 相对于*3,24位正好是3字节,
整体是为了保证结果为偶数,
这个公式看起来挺笨,
简化一下结果应该一样:
DWORD m_dwDdbWidthBytes==(m_nWidth*3+1)&-2;

看了之后觉得好像不对,希望会的人解释一下

2.
//每行实际字节数, 8个像素对应一个字节.
LONG nLineBytes = (m_nWidth + 7) / 8;
BYTE abyBitMask[] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
for(int n = 0; n < 8;n++)
{
//8个像素数据的索引值
BYTE byBit8 = *(pbyDibRaw++);//pbyDibRaw为指向DIB行数据的指针
BYTE byBitSingle = (byBit8 & abyBitMask[n]) >> (7 - n);
}

请解释一下 BYTE byBitSingle = (byBit8 & abyBitMask[n]) >> (7 - n);
...全文
334 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
zjz800800 2008-10-30
  • 打赏
  • 举报
回复
对大家回答不满意,说了n遍了,ddb图像的行扫描为什么是偶数,大家回答的几乎都是说的bit图像行扫描,郁闷送分钟。。。
e01620230 2008-10-22
  • 打赏
  • 举报
回复
switch(m_lpBMI->bmiHeader.biBitCount)
{
case 1 :
n = (DWORD)((m_lpBMI->bmiHeader.biWidth + 7)/8); //因为1位即1个像素也要占1个字节
break;
case 4 :
n =(DWORD)((m_lpBMI->bmiHeader.biWidth + 1)/2); //因为4位(即1个像素)也要占1个字节
break;

case 8 :
n = m_lpBMI->bmiHeader.biWidth;
break;
case 15:
case 16 :
n = m_lpBMI->bmiHeader.biWidth * 2;
break;
case 24 :
n = m_lpBMI->bmiHeader.biWidth * 3;
break;
case 32 :
n = m_lpBMI->bmiHeader.biWidth * 4;
break;
}

if (n%4!=0 || n== 0)
{
n+=(4-n%4); //确定每一梭的字节数
}
这个代码虽然效率不高但是很好理解
tiyuzhongxin789 2008-10-22
  • 打赏
  • 举报
回复
正确的计算方式,摘自ATL::CImage类的成员函数
static int ComputePitch( int nWidth, int nBPP )
{
return( (((nWidth*nBPP)+31)/32)*4 );
}
giant1st 2008-10-21
  • 打赏
  • 举报
回复
1 原式很直观的呀,就是为了保证 每行的字节数为偶数
m_dwDdbWidthBytes==(m_nWidth*3+1)&-2
-2 是 1111 1110,雨原式是等价的啊

2 很简单啊,那是为了 对付1个bit的图像,所以在字节里 是这样存储的 字节的最低位是左边的一个像素,更高位对应 更右的像素
zjz800800 2008-10-20
  • 打赏
  • 举报
回复
我看到有资料上说ddb的是 DWORD m_dwDdbWidthBytes=((m_nWidth*24+15)/16)*2; 即,行的字节数算法
zjz800800 2008-10-20
  • 打赏
  • 举报
回复
4字节对齐的都是dib的数据格式,4字节的,每行字节数=(每行像素个数*颜色位数+31)/32*4

我现在想问的是ddb的数据格式,老大们
rover___ 2008-10-20
  • 打赏
  • 举报
回复
每行是4字节对齐,位图文件格式MICROSOFT强制要求的。
ringphone 2008-10-20
  • 打赏
  • 举报
回复
通过乘除是有点笨,可以用
DWORD m_dwDdbWidthBytes =(m_nWidth*3+3)&0xFFFFFFFC;
m_nWidth*3如果不能被4整除,加上3就能保证整除结果+1,然后与上0xC(0b1100)截断尾数保证被4整除。
phisherr 2008-10-14
  • 打赏
  • 举报
回复
DWORD m_dwDdbWidthBytes==(m_nWidth*3+1)&-2;
这个公式不对;
结果要为4的倍数;
而且也不应该+1,(m_nWidth*3+3)&-4; 还差不多
cnzdgs 2008-10-14
  • 打赏
  • 举报
回复
位图中每行像素的字节数要求是4的整数倍,实际数据长度如果不是4的整数倍就在后面补0。
每行字节数=(每行像素个数*颜色位数+31)/32*4
Soyokaze 2008-10-14
  • 打赏
  • 举报
回复
同意1楼的,通用公式就是那个。
因为DIB的数据结构规定每个扫描行是按4Byte对齐的,4字节是32位,看每行的数据位一共包含多少个32位,算法就是整除32,这之前要填满到下一个4字节的前一位。每个32位是4字节,因为单位是字节,所以之后要乘4。
zjz800800 2008-10-14
  • 打赏
  • 举报
回复
不过现在看看 DWORD m_dwDdbWidthBytes==(m_nWidth*3+1)&-2;
好像是正确的。

大家再讨论一下
zjz800800 2008-10-14
  • 打赏
  • 举报
回复
大家说的都是dib的数据行扫描,dib的行扫描确实是4字节的倍数,不足4字节的补齐4字节的倍数,但是这个是ddb的数据扫描行,我想问的ddb行扫描,可能标题没有说清楚大家原谅,如果是dib的话一般的公式为:
//对于1,4,24位每行的字节宽度
DWORD CDib::GetDibWidthBytes(int nWidth, BYTE byBitCount)
{
DWORD dwWidthBytes = (DWORD)nWidth; //8-bits
if(byBitCount == 1) dwWidthBytes = (nWidth + 7) / 8;
else if(byBitCount == 4) dwWidthBytes = (nWidth + 1) / 2;
else if(byBitCount == 24) dwWidthBytes = 3 * nWidth ;
while((dwWidthBytes & 3) != 0)dwWidthBytes++;
return dwWidthBytes;
}

我第一个问题问的是ddb的行扫描计算字节的公式。

阿呆_ 2008-10-14
  • 打赏
  • 举报
回复
DIB位图中的每行是4字节对齐的,也就是说,数字必须能够整除4,不但但是偶数。
mynamelj 2008-10-14
  • 打赏
  • 举报
回复
正确的计算方式,摘自ATL::CImage类的成员函数
static int ComputePitch( int nWidth, int nBPP )
{
return( (((nWidth*nBPP)+31)/32)*4 );
}

19,469

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 图形处理/算法
社区管理员
  • 图形处理/算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧