用GetDIBits获取8位图像素点怎么获取不了!!求大神给代码

马孔多的黑夜 2014-07-23 09:19:03
贴代码如下,怎么遍历不了图片,而且发生断言:m_hobject!=NULL;然后还有严重的内存泄露。。求帮助
CBitmap m_bmp;
m_bmp.LoadBitmap("E:\bin\x64\2014_6_10_20_41_9_118.bmp");
BITMAP bm;
m_bmp.GetBitmap(&bm);
int nbyte = bm.bmBitsPixel/8;

BITMAPINFO bi;
bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bi.bmiHeader.biWidth = bm.bmWidth;
bi.bmiHeader.biHeight = -bm.bmHeight;
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biBitCount = 8; //位深为8
bi.bmiHeader.biCompression = BI_RGB;
bi.bmiHeader.biSizeImage = bm.bmWidth * bm.bmHeight * nbyte;
bi.bmiHeader.biXPelsPerMeter = 0;
bi.bmiHeader.biYPelsPerMeter = 0;
bi.bmiHeader.biClrUsed = 0;
bi.bmiHeader.biClrImportant = 0;
HDC hdc = ::GetDC(NULL);

BYTE* pBits = (BYTE*)new BYTE[bm.bmWidth * bm.bmHeight * nbyte];
HBITMAP hOldBmp = (HBITMAP)SelectObject(hdc,m_bmp);
BYTE picNum ;
int whiteFlag = 0;
::ZeroMemory(pBits, bm.bmWidth * bm.bmHeight * nbyte);
if (!::GetDIBits(hdc, m_bmp, 0, bm.bmHeight, pBits, &bi, DIB_RGB_COLORS))
{
delete pBits;
pBits = NULL;
}
myListNum.RemoveAll();

for(int i = 0;i <= 656;i++)
{
for(int j= 0;j <= 492;j++)
{
//bmWidthBytes:一行像素所占的字节数,一行像素的存储必须按word对齐,所以该值必须为2的倍数
BYTE r = pBits[i * nbyte + j * bm.bmWidthBytes + 2];
BYTE g = pBits[i * nbyte + j * bm.bmWidthBytes + 1];
BYTE b = pBits[i * nbyte + j * bm.bmWidthBytes + 0];
picNum = (int)((r*306 + g*601 + b*117)<<10);
COLORREF color = RGB(b, g, r);
outfileName << "color" << color << endl;
//myListNum.AddTail = -1;
}
}

delete pBits;
pBits = NULL;
}
...全文
425 35 打赏 收藏 转发到动态 举报
写回复
用AI写文章
35 条回复
切换为时间正序
请发表友善的回复…
发表回复
马孔多的黑夜 2014-07-26
  • 打赏
  • 举报
回复
我怎么让它在遍历图片时从上往下遍历啊???
马孔多的黑夜 2014-07-26
  • 打赏
  • 举报
回复

这是我测试的截图,不管从上往下还是从下往上,都是一样的。。怎么回事呢??
robertbo 2014-07-25
  • 打赏
  • 举报
回复
位图数据记录了位图的每一个像素值或该对应像素的颜色表的索引值,图像记录顺序是在扫描行内是从左到右,扫描行之间是从下到上。这种格式我们又称为Bottom_Up位图。 当然与之相对的还有Up_Down形式的位图,它的记录顺序是从上到下的,对于这种形式的位图,也不存在压缩形式。
马孔多的黑夜 2014-07-25
  • 打赏
  • 举报
回复
这个速率真快。。但是,这遍历的顺序是怎么样的??从下到上,从左往右遍历的吗?但是,位图的遍历顺序不是从上往下从左往右遍历的吗?但是根据我的测试结果,怎么感觉获取到的像素值跟实际图片的不太符合!!
马孔多的黑夜 2014-07-25
  • 打赏
  • 举报
回复
for( int j = 1; j <=hdr->biHeight ; j++) { for(int i = 1; i<= hdr->biWidth; i++ ) 和 for( int j = hdr->biHeight; j >0; j--) { for(int i = 1; i<= hdr->biWidth; i++ ) 我测试一张图片图片的像素值时,这两种方式遍历出来的像素值顺序没有改变,按道理它应该是倒着的。对了,图像处理占用的内存很大,我们有什么方法可以减小内存的占用??
阿呆_ 2014-07-25
  • 打赏
  • 举报
回复
引用 31 楼 u013782830 的回复:
[quote=引用 28 楼 Idle_ 的回复:] [quote=引用 26 楼 u013782830 的回复:] 这个速率真快。。但是,这遍历的顺序是怎么样的??从下到上,从左往右遍历的吗?但是,位图的遍历顺序不是从上往下从左往右遍历的吗?但是根据我的测试结果,怎么感觉获取到的像素值跟实际图片的不太符合!!
Bitmap的BITMAPINFOHEADER中的biHeight如果是负数,那么存的图片是UP_DOWN位图,第一个像素位于图片左上角,scanline是从上到下存放的,如果是正数,那么存的是BOTTOM_UP图,第一个像素位于图片左下角,scanline是从下往上存的。[/quote] 按你这么说,我们遍历的时候不能根据for循环来改变遍历的顺序咯?[/quote] 当然可以, 不过是我写代码的习惯而已。 因为图像处理占用的内存一般都比较大, 而大内存的顺序访问比随机访问效率提高相当明显
马孔多的黑夜 2014-07-25
  • 打赏
  • 举报
回复
引用 28 楼 Idle_ 的回复:
[quote=引用 26 楼 u013782830 的回复:] 这个速率真快。。但是,这遍历的顺序是怎么样的??从下到上,从左往右遍历的吗?但是,位图的遍历顺序不是从上往下从左往右遍历的吗?但是根据我的测试结果,怎么感觉获取到的像素值跟实际图片的不太符合!!
Bitmap的BITMAPINFOHEADER中的biHeight如果是负数,那么存的图片是UP_DOWN位图,第一个像素位于图片左上角,scanline是从上到下存放的,如果是正数,那么存的是BOTTOM_UP图,第一个像素位于图片左下角,scanline是从下往上存的。[/quote] 按你这么说,我们遍历的时候不能根据for循环来改变遍历的顺序咯?
马孔多的黑夜 2014-07-25
  • 打赏
  • 举报
回复
谢谢啦,结贴了!!
马孔多的黑夜 2014-07-25
  • 打赏
  • 举报
回复
我刚才测试了一下,对同一张图片用Getpixel()获取的像素点的值跟现在这种file的方法获取的像素值是一样的,比如我定一个像素值为723723的的点,两种方法获取到的为该值的点数是一样的。但是我用同样的遍历方式将同一张的所有像素点打印出来,两种方式的对应点的像素值却不是一样的。我想是不是顺序的原因才导致!!
阿呆_ 2014-07-25
  • 打赏
  • 举报
回复
引用 26 楼 u013782830 的回复:
这个速率真快。。但是,这遍历的顺序是怎么样的??从下到上,从左往右遍历的吗?但是,位图的遍历顺序不是从上往下从左往右遍历的吗?但是根据我的测试结果,怎么感觉获取到的像素值跟实际图片的不太符合!!
Bitmap的BITMAPINFOHEADER中的biHeight如果是负数,那么存的图片是UP_DOWN位图,第一个像素位于图片左上角,scanline是从上到下存放的,如果是正数,那么存的是BOTTOM_UP图,第一个像素位于图片左下角,scanline是从下往上存的。
马孔多的黑夜 2014-07-24
  • 打赏
  • 举报
回复
对的,我的图片是灰度图片,8位的。我应该怎么样通过GetDIBits函数获取每个像素点的值呢???求代码啊!
阿呆_ 2014-07-24
  • 打赏
  • 举报
回复
源图片是8位的吗? 如果是你根本不用那么麻烦,m_bmp.GetBitmap(&bm);后bm.bmBits就是源图片的scanline了,直接访问即可。 如果源图片不是8位的,你才需要自己充填一个8位bitmapinfo结构再分配pBits内存然后用GetDIBits复制源的scanlines,你代码中最大问题是充填的bitmapinfo(注意是bitmapinfo结构不是bitmapinfoheader结构)没有设置调色板。
马孔多的黑夜 2014-07-24
  • 打赏
  • 举报
回复
我明天试一下,先下班回去了。。对了,直接读取文件真的比用API快??
阿呆_ 2014-07-24
  • 打赏
  • 举报
回复
直接读文件效率高多了。接上面代码: unsigned char* p= bits; int linelen=(hdr->biWidth+1) / 2 * 2;; if( hdr->biHeight > 0 ) { p += linelen * (hdr->biHeight-1); linelen = -linelen; } for( y = 0; y < hdr->biHeight; y++ ) { for(x = 0; x < hdr->biWidth; x++ ) { BYTE r = colors[p[x]].rgbRed; BYTE g = colors[p[x]].rgbGreen; BYTE b = colors[p[x]].rgbBlue; COLORREF color = RGB(b, g, r); ...... } p += linelen; }
马孔多的黑夜 2014-07-24
  • 打赏
  • 举报
回复
我读取的不光是一张图片,是从硬盘里读取的几百上千张8位图图片,而且是灰度图,图片分辨率是656*492,这样的话就有32万左右的像素点,我就是要把这32个像素点的值求出来,然后再进行我的其他处理。我之前用getpixel效率太慢,大概是1秒钟才处理3张,为了提高效率,网上查资料,说是GetdiBits函数效率很快,但是我用了之后,得到的每个像素点的值都是一样的,就是按前面给的代码遍历每一个像素点的。。我的目标就是获取每一个点的像素值,而且效率要比较getpixel高很多。。。。
阿呆_ 2014-07-24
  • 打赏
  • 举报
回复
你确定你的图片是8位bmp? 如果是的话直接读文件得了: FILE* fp; size_t size; char* buf; BITMAPINFOHEADER* hdr; RGBQUAD* colors; unsigned char* bits; fp = fopen("8_bit_bitmap.bmp", "rb"); fseek(fp,0,SEEK_END); size = ftell(fp); buf = (char*)malloc(size); fseek(fp, 0, SEEK_SET); fread(buf, 1, size, fp); fclose(fp); hdr = (BITMAPINFOHEADER*)(buf+sizeof(BITMAPFILEHEADER)); colors = (RGBQUAD*)(hdr+1); bits = (unsigned char*)(colors+256); // you can process pixel data here ... free(buf);
马孔多的黑夜 2014-07-24
  • 打赏
  • 举报
回复
我试了一下,bmp.dsBm.bmBits确实还是0,不过bmp.dshSection是CCCC CCCC CCCC CCCC。 bmp.dsBm.bmBits的值都是0了我映射到内存也没有用啊,这到底怎么获取每个像素点的值???快崩溃了,都弄了好久天了。。
马孔多的黑夜 2014-07-24
  • 打赏
  • 举报
回复
我想问一句,那就不用GetdiBits函数也可以获取每个像素点的像素值啦?那这两个方法到底哪个的效率高点呢!!!还有,像素点的值是存在bits中还是存在offset里,我怎么通过遍历图片宽高来获取?
阿呆_ 2014-07-24
  • 打赏
  • 举报
回复
这样啊,那么用 HBITMAP hbmp=LoadImage(0, "8_bit_bitmap.bmp", IMAGE_BITMAP, 0, 0, 0x2010); DIBSECTION bmp; GetObject(hbmp, sizeof(DIBSECTION), &bmp); 然后检查bmp.dsBm.bmBits看看是否为NULL,如果是的话检查bmp.dshSection,这个应该就不是0了,是个file mapping的handle, 你可以用MapViewOfFile将bits内容映射到内存(注意起始位置为bmp.dsOffset),同样也可以映射color table到内存,offset为sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER), 或者是bmp.dsOffset-sizeof(RGBQUAD)*256(这个好像保险点)
马孔多的黑夜 2014-07-24
  • 打赏
  • 举报
回复
GBQUAD colors[256]; RGBQUAD rgbQ; GetDIBColorTable(mdc, 0, 256, colors); for (int i = 0 ;i<256;i++) { rgbQ =colors[i]; int N = RGB(rgbQ.rgbRed,rgbQ.rgbGreen,rgbQ.rgbBlue); outfileName<< "bmp.bmBits:"<< bmp.bmBits <<endl; outfileName << N << endl; } 按照你的代码,我把颜色值那么打印出来是有256个值,但是每个值都是一样的。 还有那个bmBits的值也是一串0,,是0000000000000000。 但是我的最终目的是获取图片的每个像素点的值,我下一步跟怎么办。我的图片是656*492分辨率的。
加载更多回复(14)

19,468

社区成员

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

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