解决方案 »
- 在创建一个mfc窗口程序的时候出现的问题!
- opengl中图像的问题
- ********继续散20分,第10个人进来后结贴,为的是细水长流**************
- 菜鸟提问,关于windows程序设计的问题
- javascript 中怎么样调用 activex control 的方法?
- VC+ODBC(用DynaSet)+Oracle 9i Lite 4.0中报错:message file is not loaded,请高手解决,可加分!
- 谁有小型的入侵检测系统实例剖析?
- 简单问题
- 新手求教:OpenCV程序如何在命令行运行
- winio在域用户下的使用?
- [求助]主窗口左上角打印窗口坐标
- 自绘按钮的鼠标消息经过父窗口吗?
而且你贴的代码完全和你的错误没有关系嘛,断言明明说m_hobject!=NULL不对,你贴的代码里哪用到m_hobject啦?
{
N++;
bFind = ccFileFind.FindNextFile();
bmpPath = ccFileFind.GetFilePath();
HBITMAP m_hBmp = (HBITMAP)LoadImage(NULL,
bmpPath,
IMAGE_BITMAP,
0,
0,
LR_LOADFROMFILE);
if ( m_hBmp == NULL )
{
AfxMessageBox("无法打开指定图!");
return;
}//有else
BITMAP bmp;
GetObject(m_hBmp, sizeof(BITMAP), &bmp);
int nbyte = bmp.bmBitsPixel/8;
BITMAPINFO bi;
bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
// bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
bi.bmiHeader.biWidth = bmp.bmWidth;
bi.bmiHeader.biHeight = -bmp.bmHeight;
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biBitCount = 8; //位深为8
bi.bmiHeader.biCompression = BI_RGB;
bi.bmiHeader.biSizeImage = bmp.bmWidth * bmp.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.bmWidthBytes* 492 ];
BYTE* pBits = (BYTE*)new BYTE[bmp.bmWidth * bmp.bmHeight * nbyte];
// ASSERT(hdc);
HBITMAP hOldBmp = (HBITMAP)SelectObject(hdc,m_hBmp);
int picNum = 0 ;
int whiteFlag = 0;
::ZeroMemory(pBits, bmp.bmWidth * bmp.bmHeight * nbyte);
// int re = GetDIBits(hdc,m_bmp,0,bm.bmHeight,pBits,&bi, DIB_RGB_COLORS);
if (!::GetDIBits(hdc,m_hBmp, 0, bmp.bmHeight, pBits, &bi, DIB_RGB_COLORS))
{
delete pBits;
pBits = NULL;
}
myListNum.RemoveAll();
for(int i = 0;i < bmp.bmWidth;i++)
{
for(int j = 0;j < bmp.bmHeight;j++)
{
//bmWidthBytes:一行像素所占的字节数,一行像素的存储必须按word对齐,所以该值必须为2的倍数
BYTE r = pBits[i * nbyte + j * bmp.bmWidthBytes + 2];
BYTE g = pBits[i * nbyte + j * bmp.bmWidthBytes + 1];
BYTE b = pBits[i * nbyte + j * bmp.bmWidthBytes + 0];
picNum = (int)((r*306 + g*601 + b*117)<<10);
COLORREF color = RGB(b, g, r); outfileName << "color" << color << endl;
}
}
}
BITMAP bm;
m_bmp.GetBitmap(&bm);
int nbyte = bm.bmBitsPixel / 8;
BITMAPINFO bi;
bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
bi.bmiHeader.biWidth = bm.bmWidth;
bi.bmiHeader.biHeight = -bm.bmHeight;
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biBitCount = bm.bmBitsPixel;
bi.bmiHeader.biCompression = BI_RGB;
bi.bmiHeader.biSizeImage = bm.bmWidth * bm.bmHeight * nbyte;
bi.bmiHeader.biClrUsed = 0;
bi.bmiHeader.biClrImportant = 0;
// 获取位图数据
HDC hdc = ::GetDC(NULL);
BYTE* pBits = (BYTE*)new BYTE[bm.bmWidth * bm.bmHeight * nbyte];
::ZeroMemory(pBits, bm.bmWidth * bm.bmHeight * nbyte);
if (!::GetDIBits(hdc, m_bmp, 0, bm.bmHeight, pBits, &bi, DIB_RGB_COLORS))
{
delete pBits;
pBits = NULL;
}
for (int i = 0;i < bm.bmWidth;++i)
{
for (int j = 0;j < bm.bmHeight;++j)
{
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];
//这里就可以做我们处理了
}
}
delete pBits;
pBits = NULL;
m_ppvBits = new DWORD[iWidth*iHeight];
BITMAPINFO bih; // create DIB Section
bih.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bih.bmiHeader.biWidth = iWidth;
bih.bmiHeader.biHeight = iHeight;
bih.bmiHeader.biPlanes = 1;
bih.bmiHeader.biBitCount = 32;
bih.bmiHeader.biCompression = BI_RGB;
bih.bmiHeader.biSizeImage = 0;
bih.bmiHeader.biXPelsPerMeter = 0;
bih.bmiHeader.biYPelsPerMeter = 0;
bih.bmiHeader.biClrUsed = 0;
bih.bmiHeader.biClrImportant = 0;
SetBitmap(&bih,m_ppvBits); DWORD* pLine = (DWORD*)GetDIBits();
// Copy the bits into our 32 bit dib..
for(int i=0;i<iHeight;i++)
{
for(int j=0;j<iWidth;j++)
{
pLine[(i*iWidth)+j] = FixColorRef(tempDC.GetPixel(j,i));
}
}
inline COLORREF CDIBSectionLite::FixColorRef(COLORREF clr)
{
int r = GetRValue(clr);
int g = GetGValue(clr);
int b = GetBValue(clr); return RGB(b,g,r);
}看看对你有没有帮助
如果源图片不是8位的,你才需要自己充填一个8位bitmapinfo结构再分配pBits内存然后用GetDIBits复制源的scanlines,你代码中最大问题是充填的bitmapinfo(注意是bitmapinfo结构不是bitmapinfoheader结构)没有设置调色板。
bmp.bmWidth:656
bmp.bmBitsPixel:32
bmp.bmWidthBytes:2624
bmp.bmBits:0000000000000000
bi.bmiHeader.biBitCount:8以上是我的打印结果,bmBits的值是一串0
HDC mdc = CreateCompatibleDC(dc);DeleteObject(SelectObject(mdc, hbmp));RGBQUAD colors[256];GetDIBColorTable(mdc, 0, 256, colors);......// bmp.bmBits指向pixels, 每字节内容是colors中的index, 颜色在colors中
...DeleteDC(mdc);
DeleteObject(hbmp);
ReleaseDC(dc);
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分辨率的。
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(这个好像保险点)
bmp.dsBm.bmBits的值都是0了我映射到内存也没有用啊,这到底怎么获取每个像素点的值???快崩溃了,都弄了好久天了。。
如果是的话直接读文件得了: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);
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;
}
当然与之相对的还有Up_Down形式的位图,它的记录顺序是从上到下的,对于这种形式的位图,也不存在压缩形式。
Bitmap的BITMAPINFOHEADER中的biHeight如果是负数,那么存的图片是UP_DOWN位图,第一个像素位于图片左上角,scanline是从上到下存放的,如果是正数,那么存的是BOTTOM_UP图,第一个像素位于图片左下角,scanline是从下往上存的。
Bitmap的BITMAPINFOHEADER中的biHeight如果是负数,那么存的图片是UP_DOWN位图,第一个像素位于图片左上角,scanline是从上到下存放的,如果是正数,那么存的是BOTTOM_UP图,第一个像素位于图片左下角,scanline是从下往上存的。按你这么说,我们遍历的时候不能根据for循环来改变遍历的顺序咯?
Bitmap的BITMAPINFOHEADER中的biHeight如果是负数,那么存的图片是UP_DOWN位图,第一个像素位于图片左上角,scanline是从上到下存放的,如果是正数,那么存的是BOTTOM_UP图,第一个像素位于图片左下角,scanline是从下往上存的。按你这么说,我们遍历的时候不能根据for循环来改变遍历的顺序咯?当然可以, 不过是我写代码的习惯而已。 因为图像处理占用的内存一般都比较大, 而大内存的顺序访问比随机访问效率提高相当明显
{
for(int i = 1; i<= hdr->biWidth; i++ )
和
for( int j = hdr->biHeight; j >0; j--)
{
for(int i = 1; i<= hdr->biWidth; i++ )
我测试一张图片图片的像素值时,这两种方式遍历出来的像素值顺序没有改变,按道理它应该是倒着的。对了,图像处理占用的内存很大,我们有什么方法可以减小内存的占用??