解决方案 »

  1.   

    因为之前用GetPixel获取像素点的值实在太慢了,所以用GetDIBits这个函数,但是我感觉它好复杂,怎么都不会用。网上找的资料也是很混乱,我只想用硬盘里加载位图然后用GetDIBits函数获取每个像素点的值。。谢谢!
      

  2.   

    GetDIBits不是你这么用的,它是用来转换DDB到DIB的,比如GetDC()获取的DC中的HBITMAP或者CreateCompatibleBitmap创建的HBITMAP。你代码中m_bmp本来就是一个DIB了。
    而且你贴的代码完全和你的错误没有关系嘛,断言明明说m_hobject!=NULL不对,你贴的代码里哪用到m_hobject啦?
      

  3.   

    我只是要用GetDIBItes获取图片像素点的值,这个函数速率高,那GetDIBites到底怎么用啊。。
      

  4.   

    while (bFind)
    {  
    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;
    }
    }
    }
      

  5.   

    我改了成上面那样用GetDIbits获取图片信息可以吗???急啊,知道的麻烦帮助一下
      

  6.   

    我是按别人写的“GetDIbits”的用法然后写出来的,我要处理的是8位图的BMP图片,他的代码里也是这样写的:
    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;   
      

  7.   

    // Create a 32 bit bitmap
    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.   

    我不想用GetPixel这个函数,它的速率太慢了,所以选择用GetDIBits这个函数。你的例子还是很好的。
      

  9.   

    源图片是8位的吗? 如果是你根本不用那么麻烦,m_bmp.GetBitmap(&bm);后bm.bmBits就是源图片的scanline了,直接访问即可。
    如果源图片不是8位的,你才需要自己充填一个8位bitmapinfo结构再分配pBits内存然后用GetDIBits复制源的scanlines,你代码中最大问题是充填的bitmapinfo(注意是bitmapinfo结构不是bitmapinfoheader结构)没有设置调色板。
      

  10.   

    对的,我的图片是灰度图片,8位的。我应该怎么样通过GetDIBits函数获取每个像素点的值呢???求代码啊!
      

  11.   

    m_bmp.GetBitmap(&bm);后bm.bmBits指向的已经是源图的像素值了(当然对8位图来说每个字节都是个index值,具体颜色在调色板里)
      

  12.   

    可是我打印bm.bmBits的值是一串0,我怎么根据图片的宽高把每一个点的像素值遍历出来呢???麻烦讲的细一点呀!!!
      

  13.   

    bmp.bmHeight:492
    bmp.bmWidth:656
    bmp.bmBitsPixel:32
    bmp.bmWidthBytes:2624
    bmp.bmBits:0000000000000000
    bi.bmiHeader.biBitCount:8以上是我的打印结果,bmBits的值是一串0
      

  14.   

    HBITMAP hbmp=LoadImage(GetModuleHandle(0), "8_bit_bitmap.bmp", IMAGE_BITMAP, 0, 0, 0x2010);BITMAP bmp;GetObject(hbmp, sizeof(bmp), &bmp);HDC dc = GetDC(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);
      

  15.   

    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分辨率的。
      

  16.   

    这样啊,那么用
    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(这个好像保险点)
      

  17.   

    我想问一句,那就不用GetdiBits函数也可以获取每个像素点的像素值啦?那这两个方法到底哪个的效率高点呢!!!还有,像素点的值是存在bits中还是存在offset里,我怎么通过遍历图片宽高来获取?
      

  18.   

    我试了一下,bmp.dsBm.bmBits确实还是0,不过bmp.dshSection是CCCC CCCC CCCC CCCC。
    bmp.dsBm.bmBits的值都是0了我映射到内存也没有用啊,这到底怎么获取每个像素点的值???快崩溃了,都弄了好久天了。。
      

  19.   

    你确定你的图片是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);
      

  20.   

    我读取的不光是一张图片,是从硬盘里读取的几百上千张8位图图片,而且是灰度图,图片分辨率是656*492,这样的话就有32万左右的像素点,我就是要把这32个像素点的值求出来,然后再进行我的其他处理。我之前用getpixel效率太慢,大概是1秒钟才处理3张,为了提高效率,网上查资料,说是GetdiBits函数效率很快,但是我用了之后,得到的每个像素点的值都是一样的,就是按前面给的代码遍历每一个像素点的。。我的目标就是获取每一个点的像素值,而且效率要比较getpixel高很多。
      

  21.   

    直接读文件效率高多了。接上面代码: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;
    }
      

  22.   

    我明天试一下,先下班回去了。。对了,直接读取文件真的比用API快??
      

  23.   

    位图数据记录了位图的每一个像素值或该对应像素的颜色表的索引值,图像记录顺序是在扫描行内是从左到右,扫描行之间是从下到上。这种格式我们又称为Bottom_Up位图。
    当然与之相对的还有Up_Down形式的位图,它的记录顺序是从上到下的,对于这种形式的位图,也不存在压缩形式。
      

  24.   


    Bitmap的BITMAPINFOHEADER中的biHeight如果是负数,那么存的图片是UP_DOWN位图,第一个像素位于图片左上角,scanline是从上到下存放的,如果是正数,那么存的是BOTTOM_UP图,第一个像素位于图片左下角,scanline是从下往上存的。
      

  25.   

    我刚才测试了一下,对同一张图片用Getpixel()获取的像素点的值跟现在这种file的方法获取的像素值是一样的,比如我定一个像素值为723723的的点,两种方法获取到的为该值的点数是一样的。但是我用同样的遍历方式将同一张的所有像素点打印出来,两种方式的对应点的像素值却不是一样的。我想是不是顺序的原因才导致!!
      

  26.   


    Bitmap的BITMAPINFOHEADER中的biHeight如果是负数,那么存的图片是UP_DOWN位图,第一个像素位于图片左上角,scanline是从上到下存放的,如果是正数,那么存的是BOTTOM_UP图,第一个像素位于图片左下角,scanline是从下往上存的。按你这么说,我们遍历的时候不能根据for循环来改变遍历的顺序咯?
      

  27.   


    Bitmap的BITMAPINFOHEADER中的biHeight如果是负数,那么存的图片是UP_DOWN位图,第一个像素位于图片左上角,scanline是从上到下存放的,如果是正数,那么存的是BOTTOM_UP图,第一个像素位于图片左下角,scanline是从下往上存的。按你这么说,我们遍历的时候不能根据for循环来改变遍历的顺序咯?当然可以, 不过是我写代码的习惯而已。 因为图像处理占用的内存一般都比较大, 而大内存的顺序访问比随机访问效率提高相当明显
      

  28.   

    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++ )
    我测试一张图片图片的像素值时,这两种方式遍历出来的像素值顺序没有改变,按道理它应该是倒着的。对了,图像处理占用的内存很大,我们有什么方法可以减小内存的占用??