一个用OpenGL显示图像色彩三维分布的程序

Drawing Image RGB Color Distribution Using OpenGL

  • .

    This article allows ones to:

    • draw an image RGB color distribution using OpenGL in a dialog,
    • use OpenGL display lists,
    • draw antialiased smooth colored lines,
    • implement mouse interaction (rotation),
    • store and load an image from resource.

    We assume that our aim is to display the RGB color distribution of the following image (Figure 1) in an interactive way. In particular, it would be nice to display the RGB cube and the image color cloud.

    Figure 1: Our goal is to display the RGB color distribution of this 24 bits BMP color image in an intuitive way. OpenGL will help us.

    Figure 2: Illustrates two viewpoints of the color distribution in a dialog. The viewpoint is modifed using the left mouse button that implements the x/y rotation, the dialog may be resized and a popup menu allows us to load and view the current image (Figure 3).

    Figure 3: Two examples of color distribution in the RGB cube seen under two distinct viewpoints. In particular, the red cloud is linked to the nose of the baboon seen in Figure 1. Notice that the lines are antialiased, each saturated color is drawn with a sphere , and the cloud is painted using the GL_POINTS primitive.

    Figure 4: A popup menu allows to load a 24 bits RGB image, change the OpenGL clear color (recalled back color), and view the current image in a dialog window.

    Initialization of the Rendering Engine

    Following lines make the rendering engine to be initialized in a dialog.
      
      
    1. //*********************************
    2. // OnCreate
    3. //*********************************
    4. int CColorDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
    5. {
    6. // Init OpenGL engine
    7. HWND hWnd = GetSafeHwnd();
    8. HDC hDC = ::GetDC(hWnd);
    9.  
    10. if(SetWindowPixelFormat(hDC)==FALSE)
    11. return 0;
    12.  
    13. if(CreateViewGLContext(hDC)==FALSE)
    14. return 0;
    15.  
    16. // The lines are antialiased
    17. glEnable(GL_LINE_SMOOTH);
    18. glEnable(GL_BLEND);
    19. glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
    20. glHint(GL_LINE_SMOOTH_HINT,GL_NICEST);
    21. glLineWidth(1.5); // required
    22. glPointSize(1.0);
    23. glPolygonMode(GL_FRONT,GL_LINE);
    24. glPolygonMode(GL_BACK,GL_LINE);
    25. glShadeModel(GL_SMOOTH);
    26.  
    27. // Precalculate display lists
    28. BuildListCube();
    29. BuildListCloud();
    30.  
    31. return 0;
    32. }
      
      
    1. //**********************************************
    2. // OpenGL
    3. //**********************************************
    4. BOOL CColorDlg::SetWindowPixelFormat(HDC hDC)
    5. {
    6. PIXELFORMATDESCRIPTOR pixelDesc;
    7.  
    8. pixelDesc.nSize = sizeof(PIXELFORMATDESCRIPTOR);
    9. pixelDesc.nVersion = 1;
    10.  
    11. pixelDesc.dwFlags = PFD_DRAW_TO_WINDOW
    12. | PFD_SUPPORT_OPENGL
    13. | PFD_DOUBLEBUFFER
    14. | PFD_STEREO_DONTCARE;
    15.  
    16. pixelDesc.iPixelType = PFD_TYPE_RGBA;
    17. pixelDesc.cColorBits = 32;
    18. pixelDesc.cRedBits = 8;
    19. pixelDesc.cRedShift = 16;
    20. pixelDesc.cGreenBits = 8;
    21. pixelDesc.cGreenShift = 8;
    22. pixelDesc.cBlueBits = 8;
    23. pixelDesc.cBlueShift = 0;
    24. pixelDesc.cAlphaBits = 0;
    25. pixelDesc.cAlphaShift = 0;
    26. pixelDesc.cAccumBits = 64;
    27. pixelDesc.cAccumRedBits = 16;
    28. pixelDesc.cAccumGreenBits = 16;
    29. pixelDesc.cAccumBlueBits = 16;
    30. pixelDesc.cAccumAlphaBits = 0;
    31. pixelDesc.cDepthBits = 32;
    32. pixelDesc.cStencilBits = 8;
    33. pixelDesc.cAuxBuffers = 0;
    34. pixelDesc.iLayerType = PFD_MAIN_PLANE;
    35. pixelDesc.bReserved = 0;
    36. pixelDesc.dwLayerMask = 0;
    37. pixelDesc.dwVisibleMask = 0;
    38. pixelDesc.dwDamageMask = 0;
    39.  
    40. m_GLPixelIndex = ChoosePixelFormat(hDC,&pixelDesc);
    41. if(m_GLPixelIndex==0) // Choose default
    42. {
    43. m_GLPixelIndex = 1;
    44. if(!DescribePixelFormat(hDC,m_GLPixelIndex,
    45. sizeof(PIXELFORMATDESCRIPTOR),&pixelDesc))
    46. return FALSE;
    47. }
    48.  
    49. if(!SetPixelFormat(hDC,m_GLPixelIndex,&pixelDesc))
    50. return FALSE;
    51.  
    52. return TRUE;
    53. }
    54.  
    55. //*********************************
    56. // CreateViewGLContext
    57. //*********************************
    58. BOOL CColorDlg::CreateViewGLContext(HDC hDC)
    59. {
    60. m_hGLContext = wglCreateContext(hDC);
    61.  
    62. if(m_hGLContext==NULL)
    63. return FALSE;
    64.  
    65. if(wglMakeCurrent(hDC,m_hGLContext)==FALSE)
    66. return FALSE;
    67.  
    68. return TRUE;
    69. }
      
      
    1. //*********************************
    2. // OnDestroy
    3. //*********************************
    4. void CColorDlg::OnDestroy()
    5. {
    6. CDialog::OnDestroy();
    7.  
    8. if(wglGetCurrentContext() != NULL)
    9. wglMakeCurrent(NULL,NULL);
    10.  
    11. if(m_hGLContext != NULL)
    12. {
    13. wglDeleteContext(m_hGLContext);
    14. m_hGLContext = NULL;
    15. }
    16.  
    17. glDeleteLists(1,2);
    18. }

    RENDERING

    The RGB cube and the cloud are rendered in two distinct display lists. The cube is a fixed part, while the color cloud is rebuild each time a new image is loaded.
      
      
    1. //*********************************
    2. // OnPaint
    3. //*********************************
    4. void CColorDlg::OnPaint()
    5. {
    6. // ** Draw scene **
    7. CPaintDC dc(this);
    8. RenderScene();
    9. SwapBuffers(dc.m_ps.hdc); // double buffer
    10. }
      
      
    1. //*********************************
    2. // RenderScene
    3. //*********************************
    4. void CColorDlg::RenderScene()
    5. {
    6. ::glClearColor((float)GetRValue(m_BackColor)/255.0f,
    7. (float)GetGValue(m_BackColor)/255.0f,
    8. (float)GetBValue(m_BackColor)/255.0f,1.0f);
    9. ::glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    10.  
    11. ::glPushMatrix();
    12. ::glTranslated(0.0,0.0,-8.0);
    13. ::glRotated(m_xRotate, 1.0, 0.0, 0.0);
    14. ::glRotated(m_yRotate, 0.0, 1.0, 0.0);
    15. ::glCallList(1); // cube
    16. ::glCallList(2); // clouds
    17. ::glPopMatrix();
    18. }
    19.  
    20. //***********************************************
    21. // BuildList
    22. //***********************************************
    23. void CColorDlg::BuildListCube(BOOL list)
    24. {
    25. GLUquadricObj* pQuadric = gluNewQuadric();
    26.  
    27. if(list)
    28. ::glNewList(1,GL_COMPILE_AND_EXECUTE);
    29.  
    30. float x = m_Size;
    31.  
    32. // RGB cube
    33. glBegin(GL_LINE_LOOP);
    34. glColor3ub(0,0,0);
    35. glVertex3d(-x,-x,-x);
    36. glColor3ub(255,0,0);
    37. glVertex3d(x,-x,-x);
    38. glColor3ub(255,255,0);
    39. glVertex3d(x,x,-x);
    40. glColor3ub(0,255,0);
    41. glVertex3d(-x,x,-x);
    42. glEnd();
    43.  
    44. glBegin(GL_LINE_LOOP);
    45. glColor3ub(0,0,255);
    46. glVertex3d(-x,-x,x);
    47. glColor3ub(255,0,255);
    48. glVertex3d(x,-x,x);
    49. glColor3ub(255,255,255);
    50. glVertex3d(x,x,x);
    51. glColor3ub(0,255,255);
    52. glVertex3d(-x,x,x);
    53. glEnd();
    54.  
    55. glBegin(GL_LINES);
    56. glColor3ub(0,0,0);
    57. glVertex3d(-x,-x,-x);
    58. glColor3ub(0,0,255);
    59. glVertex3d(-x,-x,x);
    60. glColor3ub(255,0,0);
    61. glVertex3d(x,-x,-x);
    62. glColor3ub(255,0,255);
    63. glVertex3d(x,-x,x);
    64. glColor3ub(255,255,0);
    65. glVertex3d(x,x,-x);
    66. glColor3ub(255,255,255);
    67. glVertex3d(x,x,x);
    68. glColor3ub(0,255,0);
    69. glVertex3d(-x,x,-x);
    70. glColor3ub(0,255,255);
    71. glVertex3d(-x,x,x);
    72. glEnd();
    73.  
    74. // Spheres
    75. glPolygonMode(GL_FRONT,GL_FILL);
    76. glPolygonMode(GL_BACK,GL_FILL);
    77. float radius = 0.1f;
    78.  
    79. glPushMatrix();
    80. glTranslated(-m_Size,-m_Size,-m_Size);
    81. glColor3ub(0,0,0);
    82. gluSphere(pQuadric,radius,12,12);
    83. glPopMatrix();
    84.  
    85. glPushMatrix();
    86. glTranslated(m_Size,-m_Size,-m_Size);
    87. glColor3ub(255,0,0);
    88. gluSphere(pQuadric,radius,12,12);
    89. glPopMatrix();
    90.  
    91. glPushMatrix();
    92. glTranslated(-m_Size,m_Size,-m_Size);
    93. glColor3ub(0,255,0);
    94. gluSphere(pQuadric,radius,12,12);
    95. glPopMatrix();
    96.  
    97. glPushMatrix();
    98. glTranslated(-m_Size,-m_Size,m_Size);
    99. glColor3ub(0,0,255);
    100. gluSphere(pQuadric,radius,12,12);
    101. glPopMatrix();
    102.  
    103. glPushMatrix();
    104. glTranslated(m_Size,m_Size,-m_Size);
    105. glColor3ub(255,255,0);
    106. gluSphere(pQuadric,radius,12,12);
    107. glPopMatrix();
    108.  
    109. glPushMatrix();
    110. glTranslated(-m_Size,m_Size,m_Size);
    111. glColor3ub(0,255,255);
    112. gluSphere(pQuadric,radius,12,12);
    113. glPopMatrix();
    114.  
    115. glPushMatrix();
    116. glTranslated(m_Size,-m_Size,m_Size);
    117. glColor3ub(255,0,255);
    118. gluSphere(pQuadric,radius,12,12);
    119. glPopMatrix();
    120.  
    121. glPushMatrix();
    122. glTranslated(m_Size,m_Size,m_Size);
    123. glColor3ub(255,255,255);
    124. gluSphere(pQuadric,radius,12,12);
    125. glPopMatrix();
    126.  
    127. if(list)
    128. ::glEndList();
    129.  
    130. gluDeleteQuadric(pQuadric);
    131. }
    132.  
    133. //***********************************************
    134. // BuildListCloud
    135. //***********************************************
    136. void CColorDlg::BuildListCloud()
    137. {
    138. TRACE("Build list cloud...");
    139.  
    140. // Image area
    141. unsigned int area = m_Image.GetWidth()
    142. * m_Image.GetHeight();
    143.  
    144. TRACE("area : %d...",area);
    145.  
    146. // Need valid image (24 bits)
    147. if(area == 0 ||
    148. m_Image.GetDepth() != 24)
    149. return;
    150.  
    151. // Maximum -> area distinct colors / 2^24
    152. // This table is memory expansive, but short lived
    153. TRACE("alloc...");
    154. unsigned char *pTable = new unsigned char[16777216];
    155. memset(pTable,0,16777216); // init 0
    156.  
    157. // Image data
    158. unsigned int wb32 = m_Image.GetWidthByte32();
    159. unsigned char *pData = m_Image.GetData();
    160.  
    161. // Build a new list
    162. TRACE("build list...");
    163. int nb = 0;
    164. ::glNewList(2,GL_COMPILE_AND_EXECUTE);
    165. glBegin(GL_POINTS);
    166. float tmp = 2.0f/255.0f*m_Size;
    167. for(unsigned int j=0;j<m_Image.GetHeight();j++)
    168. for(unsigned int i=0;i<m_Image.GetWidth();i++)
    169. {
    170. unsigned char b = pData[wb32*j+3*i];
    171. unsigned char g = pData[wb32*j+3*i+1];
    172. unsigned char r = pData[wb32*j+3*i+2];
    173. if(!pTable[b*65536+g*256+r])
    174. {
    175. glColor3ub(r,g,b);
    176. float x = -m_Size+(float)r*tmp;
    177. float y = -m_Size+(float)g*tmp;
    178. float z = -m_Size+(float)b*tmp;
    179. glVertex3d(x,y,z);
    180. pTable[b*65536+g*256+r] = 1;
    181. nb++;
    182. }
    183. }
    184. glEnd();
    185. ::glEndList();
    186. TRACE("%d points...",nb);
    187.  
    188. TRACE("cleanup...");
    189. delete [] pTable;
    190. TRACE("ok\n");
    191. }

    Downloads

    Download source - 10 Kb
    Download (built) demo project - 530 Kb



    来源:http://www.codeguru.com/cpp/g-m/opengl/article.php/c2691/Drawing-Image-RGB-Color-Distribution-Using-OpenGL.htm

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值