none
如何在内存DC中调用GetPixel获取像素点颜色值? RRS feed

  • 问题

  •  

    由于文字背景色为白色,前景色为黑色,于是我在窗口中间绘制了16 * 16的单元格:

    1、使用客户区域的窗口DC来绘图(在窗口中显示出来)

       A、左边白色为绘图区域,在左上角输出了一个“鲁”字;

       B、再使用GetTextExtentPoint32函数可以得出该文字为16 * 16像素大小;

       C、最后使用GetPixel函数取出每个像素点的颜色值,来填充左窗口中对应的表格。

       单元格的填充方法:根据左上角(最小的)“鲁”字每个像素点的颜色值,来对应填充这里单元格的颜色;

       该点阵的计算方法:每个像素点用1bit表示(0表示黑,1表示白),于是这个字号的鲁字就占了16 * 16 / 2 = 32字节

                         按横向取,因为8bit/字节嘛,也就是一个字节要横向取8个像素点。


       如下图所示:

     

     

    这个方法的缺点就是DLL模块中必须要使用一个窗口句柄,然后把文字画上去再取出像素点,所以这方法欠妥。便想到了下面的方法:先创建一个虚拟DC,然后再创建一个内存DC,在内存DC中使用TextOut,但用GetPixel时,老是返回CLR_INVALID,而MSDN中一段解释也没有看明白,它说并不是所有DC都支持GetPixel,必须调用GetDeviceCaps来获取详情(在BD、GG许久后,这个API始终没看懂到底有什么用)

     

    2、使用内存DC来输出图形

       A、创建虚拟DC,再创建一个兼容的内存DC,再TextOut输出文字;(我将DC载入HBITMAP,发现全为背景的黑色)

       B、再使用GetTextExtentPoint32函数可以得出该文字为16 * 16像素大小;(大小能获取到)

       C、最后使用GetPixel函数取出每个像素点的颜色值,来填充左窗口中对应的表格。(这里GetPixel失败)

     

       相关伪代码如下:

     

    #include <windows.h>
    
    #pragma comment(lib,"user32.lib")
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR pszCmdLine, int cmdShow)
    {
     // create a virtual dc to draw elements.
     HDC  hdcScreen	 = CreateDC("DISPLAY", NULL, NULL, NULL); 
     HDC  hdcCompatible = CreateCompatibleDC(hdcScreen);
     CString m_strText = _T("Hello");
     SIZE m_sz;
     
     if(hdcCompatible == NULL)
     {
      MessageBox(NULL,_T("CreateCompatibleDC Failed !"),NULL,NULL);
      return NULL;
     }
     
     // then set the text color is black,the back color is white.
     SetBkColor(hdcCompatible,RGB(255,255,255));
     SetTextColor(hdcCompatible,RGB(0,0,0));
     
     // draw the text int a virtual dc.
     TextOut(hdcCompatible,0,0,m_strText,m_strText.GetLength());
    	
     // get the text width and height.
     GetTextExtentPoint32(hdcCompatible,m_strText,m_strText.GetLength(),&m_sz);
     
     // get the pixel infomation.
     for(int i=0; i<m_sz.cx; i++)
     {
      for(int j=0; j<m_sz.cy; j++)
      {
       COLORREF color = GetPixel(hdcCompatible,i,j);
       if(color == CLR_INVALID)
       {
        TRACE("call GetPixel Failed !\r\n");
       }
       else if(color == RGB(255,255,255)
       {
        // Set the bit is 0. 
       }
       else
       {
        // Set the bit is 1. 
       }
      }
     }
    }
    

     

     

    这里的color变量一直都是0x00FFFFFF(背景色),困扰半个月的问题了,希望有空的兄弟帮忙看看这个问题如何解决,或者有更好的方法,不盛感激!


    2011年4月14日 1:24

答案

  • Hi Koma,

    有时在调试的时候使用GetPixel会出错,请您尝试一下正常模式下运行。看是否还存在此问题。

    另外以下这篇文章是讲GetPixel出错要注意的地方,和您的问题十分相近,您可以参考下此文章。看是否有帮助。

     http://blog.csdn.net/wuyao721/archive/2008/12/25/3605703.aspx 

    此回复包含了指向第三方的网址信息. Microsoft提供此链接以帮助您了解更多信息.此链接不受控于Microsoft且此链接包含的任何软件与信息未经验证.Microsoft无法保证其质量,安全性以及稳定性.从互联网获取软件与信息有潜在的危险, Microsoft提醒您知悉此风险.

     

    如果您的问题还存在,我建议你可以使用其他的方法来代替GetPixel方法。

    比如我们可以用CreateDIBSection创建一个HBITMAP,它给你返回图像缓冲区的地址。创建一个内存DC,把这个DIBSECTIONHBITMAP选入DC,把你的图片绘制到这个DC,图像缓冲区中就是图片数据了

    如果我的回答有什么问题,您可以提出。

     

    谢谢您的理解,

    Lucy


    Lucy Liu [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • 已标记为答案 Koma.Walk 2011年4月18日 1:00
    2011年4月15日 9:09
    版主

全部回复

  • Not all devices support the GetPixel function. For more information, see the RC_BITBLT raster capability under the GetDeviceCaps member function.

    A bitmap must be selected within the device context, otherwise, CLR_INVALID is returned on all pixels.


    Visual C++ enthusiast, like network programming and driver development. At present is being engaged in the WinCE/Windows Mobile platform embedded development.
    2011年4月14日 3:23
    版主
  • Hi Koma,

    有时在调试的时候使用GetPixel会出错,请您尝试一下正常模式下运行。看是否还存在此问题。

    另外以下这篇文章是讲GetPixel出错要注意的地方,和您的问题十分相近,您可以参考下此文章。看是否有帮助。

     http://blog.csdn.net/wuyao721/archive/2008/12/25/3605703.aspx 

    此回复包含了指向第三方的网址信息. Microsoft提供此链接以帮助您了解更多信息.此链接不受控于Microsoft且此链接包含的任何软件与信息未经验证.Microsoft无法保证其质量,安全性以及稳定性.从互联网获取软件与信息有潜在的危险, Microsoft提醒您知悉此风险.

     

    如果您的问题还存在,我建议你可以使用其他的方法来代替GetPixel方法。

    比如我们可以用CreateDIBSection创建一个HBITMAP,它给你返回图像缓冲区的地址。创建一个内存DC,把这个DIBSECTIONHBITMAP选入DC,把你的图片绘制到这个DC,图像缓冲区中就是图片数据了

    如果我的回答有什么问题,您可以提出。

     

    谢谢您的理解,

    Lucy


    Lucy Liu [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • 已标记为答案 Koma.Walk 2011年4月18日 1:00
    2011年4月15日 9:09
    版主
  • Hi Koma,

    有时在调试的时候使用GetPixel会出错,请您尝试一下正常模式下运行。看是否还存在此问题。

    另外以下这篇文章是讲GetPixel出错要注意的地方,和您的问题十分相近,您可以参考下此文章。看是否有帮助。

     http://blog.csdn.net/wuyao721/archive/2008/12/25/3605703.aspx 

    此回复包含了指向第三方的网址信息. Microsoft提供此链接以帮助您了解更多信息.此链接不受控于Microsoft且此链接包含的任何软件与信息未经验证.Microsoft无法保证其质量,安全性以及稳定性.从互联网获取软件与信息有潜在的危险, Microsoft提醒您知悉此风险.

     

    如果您的问题还存在,我建议你可以使用其他的方法来代替GetPixel方法。

    比如我们可以用CreateDIBSection创建一个HBITMAP,它给你返回图像缓冲区的地址。创建一个内存DC,把这个DIBSECTIONHBITMAP选入DC,把你的图片绘制到这个DC,图像缓冲区中就是图片数据了

    如果我的回答有什么问题,您可以提出。

     

    谢谢您的理解,

    Lucy


    Lucy Liu [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    非常感谢!
    2011年4月18日 1:00