将真彩图转变为灰度图发生错位

fyl19870803 2010-03-29 02:29:33
以下为我将真彩图转变为灰度图的代码,有些真彩图可以正常转换,可是有些转换后发生错位,转换后的图被斜着分成几部分,该如何解决?

void ColorToGray(LPSTR lpDIB, LONG lWidth, LONG lHeight)
{
ASSERT(lpDIB!=NULL);

// 图像每行的字节数
LONG lLineBytes=WIDTHBYTES(lWidth*8);
BYTE rgbBlue(0);
BYTE rgbGreen(0);
BYTE rgbRed(0);

// 真彩色图像变成灰度图像
if (DIBNumColors(lpDIB) == 0)
{
// 位图信息头
LPBITMAPINFOHEADER lpBI = (LPBITMAPINFOHEADER)lpDIB;
lpBI->biSize = 40;
lpBI->biWidth = lWidth;
lpBI->biHeight = lHeight;
lpBI->biPlanes = 1;
lpBI->biBitCount = 8;
lpBI->biCompression = 0;
lpBI->biSizeImage = lLineBytes*lHeight;
lpBI->biClrUsed = 0;
lpBI->biClrImportant = 0;

// DIB图像数据
LPBYTE lpDIBBits=LPBYTE(lpDIB+(DWORD)(*lpDIB));
LPBYTE lpdesc=new BYTE[lLineBytes*lHeight];
LONG i,j;
for (j=0; j<lHeight; j++)
{
for (i=0; i<lWidth; i++)
{
rgbBlue = *(lpDIBBits+lLineBytes*j*3+i*3);
rgbGreen = *(lpDIBBits+lLineBytes*j*3+i*3+1);
rgbRed = *(lpDIBBits+lLineBytes*j*3+i*3+2);
lpdesc[lWidth*j+i]= (BYTE)(0.299*rgbRed+0.587*rgbGreen+0.114*rgbBlue+0.5);
}
}
for(i=0;i<lHeight;i++)
{
for(j=0;j<lWidth;j++)
{
*(lpDIBBits+sizeof(RGBQUAD)*256+lLineBytes*i+j)= lpdesc[lWidth*i+j];
}
}
delete [] lpdesc;

// 添加调色板
LPBITMAPINFO lpbmi = (LPBITMAPINFO)lpDIB;
LPBITMAPCOREINFO lpbmc = (LPBITMAPCOREINFO)lpDIB;
int k=0;
if(IS_WIN30_DIB(lpDIB))
{
for (k=0; k<256; k++)
{
lpbmi->bmiColors[k].rgbRed=(BYTE)k;
lpbmi->bmiColors[k].rgbGreen=(BYTE)k;
lpbmi->bmiColors[k].rgbBlue=(BYTE)k;
lpbmi->bmiColors[k].rgbReserved=0;
}
}
else
{
for (k=0; k<256; k++)
{
lpbmc->bmciColors[k].rgbtRed=(BYTE)k;
lpbmc->bmciColors[k].rgbtGreen=(BYTE)k;
lpbmc->bmciColors[k].rgbtBlue=(BYTE)k;
}
}
}
}
...全文
279 13 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
zhangyan_wt 2010-03-29
  • 打赏
  • 举报
回复
24位图像对齐得时候要先乘3再对齐。灰度图像直接对齐。

long lLineBytes24B =(lWidth*3+3)/4*4;
long lLineBytesGray = (lWidth+3)/4*4;

然后
for (j=0; j<lHeight; j++)
{
for (i=0; i<lWidth; i++)
{
rgbBlue = *(lpDIBBits+lLineBytes24B*j+i*3);
rgbGreen = *(lpDIBBits+lLineBytes24B*j+i*3+1);
rgbRed = *(lpDIBBits+lLineBytes24B*j+i*3+2);
lpdesc[lLineBytesGray *j+i]= (BYTE)(0.299*rgbRed+0.587*rgbGreen+0.114*rgbBlue+0.5);
}
}
gamedragon 2010-03-29
  • 打赏
  • 举报
回复
你的WIDTHBYTES是怎么写的,写几个例子试试就知道问题了。
laviewpbt 2010-03-29
  • 打赏
  • 举报
回复
BMP的基础知识中有关于扫描行的概念的,就是必须保证图像的每一行像素所占用的字节数为4的倍数。

对于24位图像,一个像素占用3个字节,那么比如一个宽度为101的图像,他的一行像素实际需要的内存数为
101*3=303个字节,但是Windows实际为他一行像素分配的字节数是304.

对于8位图像,一个像素占用1个字节,那么比如一个宽度为101的图像,他的一行像素实际需要的内存数为
101*1=101个字节,但是Windows实际为他一行像素分配的字节数是104.

在你上面的计算中,你用8位图像的扫描行宽度乘以3并不能完全代表24位图像的扫描行。
也就是 104*3不等于304.
fyl19870803 2010-03-29
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 laviewpbt 的回复:]
这里的代码没有一句是对的。
懒得讲了,就是扫描行对齐的问题。
for (j=0; j<lHeight; j++)
{
for (i=0; i<lWidth; i++)
{
rgbBlue = *(lpDIBBits+lLineBytes*j*3+i*3);
rgbGreen = *(lpDIBBits+lLineBytes*j*3+i*3+1);
rgbRed = *(lpDIBB……
[/Quote]
laviewpbt老大,讲清楚好吧,给个以前讲过的链接也行呀,小弟也是刚弄没多久,还是个菜鸟哇。先谢谢了!
fyl19870803 2010-03-29
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 kier2 的回复:]
lpdesc[lWidth*j+i]=这里可能也要改,你新分配的灰度图像内存,也要是4字节的倍数吧,改成
lpdesc[lLineBytes*j+i]看看
[/Quote]
不行,lpdesc就是为了临时存储变量,因为转变前后像素数是不会变的,而lpdesc分配的的内存大小就是像素数,所以那个是没错的。
不过还是要谢谢kier2兄的!
laviewpbt 2010-03-29
  • 打赏
  • 举报
回复
这里的代码没有一句是对的。
懒得讲了,就是扫描行对齐的问题。
for (j=0; j<lHeight; j++)
{
for (i=0; i<lWidth; i++)
{
rgbBlue = *(lpDIBBits+lLineBytes*j*3+i*3);
rgbGreen = *(lpDIBBits+lLineBytes*j*3+i*3+1);
rgbRed = *(lpDIBBits+lLineBytes*j*3+i*3+2);
lpdesc[lWidth*j+i]= (BYTE)(0.299*rgbRed+0.587*rgbGreen+0.114*rgbBlue+0.5);
}
}
kier2 2010-03-29
  • 打赏
  • 举报
回复
lpdesc[lWidth*j+i]=这里可能也要改,你新分配的灰度图像内存,也要是4字节的倍数吧,改成
lpdesc[lLineBytes*j+i]看看
fyl19870803 2010-03-29
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 m_tornado 的回复:]
你看一下,如果宽度*3是4的倍数的图像是不是就没有问题呢
也就是说一个 1024 * 768 的图像处理是没有问题的
如果是111* 768 的应该就发生错位了

首先觉得是对BMP格式认识不够,如果宽度*3不是4的倍数,那么会自动补齐,所以会出现错位
[/Quote]
这个我考虑过了,lLineBytes是灰度图的对齐时行的字节数,也就是LONG lLineBytes=WIDTHBYTES(lWidth*8);所以说lLineBytes是一定对齐的,是4的倍数,所以rgbBlue = *(lpDIBBits+lLineBytes*j*3+i*3); 这里的lLineBytes*j*3也一定会是4的倍数,因为它就是在前者基础上乘以了个3。

kier2 2010-03-29
  • 打赏
  • 举报
回复
人家有 LONG lLineBytes=WIDTHBYTES(lWidth*8);应该是考虑了行对齐的呀!
laviewpbt 2010-03-29
  • 打赏
  • 举报
回复
扫描行对齐
m_tornado 2010-03-29
  • 打赏
  • 举报
回复
你看一下,如果宽度*3是4的倍数的图像是不是就没有问题呢
也就是说一个 1024 * 768 的图像处理是没有问题的
如果是111* 768 的应该就发生错位了

首先觉得是对BMP格式认识不够,如果宽度*3不是4的倍数,那么会自动补齐,所以会出现错位
fyl19870803 2010-03-29
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 kier2 的回复:]
有些位图是32位的,你的只适合24位的,32位的还有ALPHA通道
[/Quote]
可是我试了一下,发生错位的那张图的biBitCount也是24位呀,怎么会是32位。
kier2 2010-03-29
  • 打赏
  • 举报
回复
有些位图是32位的,你的只适合24位的,32位的还有ALPHA通道

19,472

社区成员

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

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