Drawing Image RGB Color Distribution Using OpenGL
Posted by
Pierre Alliez and Magali Mazihre on
October 18th, 2000
-
.
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.
Initialization of the Rendering Engine
Following lines make the rendering engine to be initialized in a dialog.- //*********************************
- // OnCreate
- //*********************************
- int CColorDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
- {
- // Init OpenGL engine
- HWND hWnd = GetSafeHwnd();
- HDC hDC = ::GetDC(hWnd);
- if(SetWindowPixelFormat(hDC)==FALSE)
- return 0;
- if(CreateViewGLContext(hDC)==FALSE)
- return 0;
- // The lines are antialiased
- glEnable(GL_LINE_SMOOTH);
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
- glHint(GL_LINE_SMOOTH_HINT,GL_NICEST);
- glLineWidth(1.5); // required
- glPointSize(1.0);
- glPolygonMode(GL_FRONT,GL_LINE);
- glPolygonMode(GL_BACK,GL_LINE);
- glShadeModel(GL_SMOOTH);
- // Precalculate display lists
- BuildListCube();
- BuildListCloud();
- return 0;
- }
- //**********************************************
- // OpenGL
- //**********************************************
- BOOL CColorDlg::SetWindowPixelFormat(HDC hDC)
- {
- PIXELFORMATDESCRIPTOR pixelDesc;
- pixelDesc.nSize = sizeof(PIXELFORMATDESCRIPTOR);
- pixelDesc.nVersion = 1;
- pixelDesc.dwFlags = PFD_DRAW_TO_WINDOW
- | PFD_SUPPORT_OPENGL
- | PFD_DOUBLEBUFFER
- | PFD_STEREO_DONTCARE;
- pixelDesc.iPixelType = PFD_TYPE_RGBA;
- pixelDesc.cColorBits = 32;
- pixelDesc.cRedBits = 8;
- pixelDesc.cRedShift = 16;
- pixelDesc.cGreenBits = 8;
- pixelDesc.cGreenShift = 8;
- pixelDesc.cBlueBits = 8;
- pixelDesc.cBlueShift = 0;
- pixelDesc.cAlphaBits = 0;
- pixelDesc.cAlphaShift = 0;
- pixelDesc.cAccumBits = 64;
- pixelDesc.cAccumRedBits = 16;
- pixelDesc.cAccumGreenBits = 16;
- pixelDesc.cAccumBlueBits = 16;
- pixelDesc.cAccumAlphaBits = 0;
- pixelDesc.cDepthBits = 32;
- pixelDesc.cStencilBits = 8;
- pixelDesc.cAuxBuffers = 0;
- pixelDesc.iLayerType = PFD_MAIN_PLANE;
- pixelDesc.bReserved = 0;
- pixelDesc.dwLayerMask = 0;
- pixelDesc.dwVisibleMask = 0;
- pixelDesc.dwDamageMask = 0;
- m_GLPixelIndex = ChoosePixelFormat(hDC,&pixelDesc);
- if(m_GLPixelIndex==0) // Choose default
- {
- m_GLPixelIndex = 1;
- if(!DescribePixelFormat(hDC,m_GLPixelIndex,
- sizeof(PIXELFORMATDESCRIPTOR),&pixelDesc))
- return FALSE;
- }
- if(!SetPixelFormat(hDC,m_GLPixelIndex,&pixelDesc))
- return FALSE;
- return TRUE;
- }
- //*********************************
- // CreateViewGLContext
- //*********************************
- BOOL CColorDlg::CreateViewGLContext(HDC hDC)
- {
- m_hGLContext = wglCreateContext(hDC);
- if(m_hGLContext==NULL)
- return FALSE;
- if(wglMakeCurrent(hDC,m_hGLContext)==FALSE)
- return FALSE;
- return TRUE;
- }
- //*********************************
- // OnDestroy
- //*********************************
- void CColorDlg::OnDestroy()
- {
- CDialog::OnDestroy();
- if(wglGetCurrentContext() != NULL)
- wglMakeCurrent(NULL,NULL);
- if(m_hGLContext != NULL)
- {
- wglDeleteContext(m_hGLContext);
- m_hGLContext = NULL;
- }
- glDeleteLists(1,2);
- }
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.- //*********************************
- // OnPaint
- //*********************************
- void CColorDlg::OnPaint()
- {
- // ** Draw scene **
- CPaintDC dc(this);
- RenderScene();
- SwapBuffers(dc.m_ps.hdc); // double buffer
- }
- //*********************************
- // RenderScene
- //*********************************
- void CColorDlg::RenderScene()
- {
- ::glClearColor((float)GetRValue(m_BackColor)/255.0f,
- (float)GetGValue(m_BackColor)/255.0f,
- (float)GetBValue(m_BackColor)/255.0f,1.0f);
- ::glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- ::glPushMatrix();
- ::glTranslated(0.0,0.0,-8.0);
- ::glRotated(m_xRotate, 1.0, 0.0, 0.0);
- ::glRotated(m_yRotate, 0.0, 1.0, 0.0);
- ::glCallList(1); // cube
- ::glCallList(2); // clouds
- ::glPopMatrix();
- }
- //***********************************************
- // BuildList
- //***********************************************
- void CColorDlg::BuildListCube(BOOL list)
- {
- GLUquadricObj* pQuadric = gluNewQuadric();
- if(list)
- ::glNewList(1,GL_COMPILE_AND_EXECUTE);
- float x = m_Size;
- // RGB cube
- glBegin(GL_LINE_LOOP);
- glColor3ub(0,0,0);
- glVertex3d(-x,-x,-x);
- glColor3ub(255,0,0);
- glVertex3d(x,-x,-x);
- glColor3ub(255,255,0);
- glVertex3d(x,x,-x);
- glColor3ub(0,255,0);
- glVertex3d(-x,x,-x);
- glEnd();
- glBegin(GL_LINE_LOOP);
- glColor3ub(0,0,255);
- glVertex3d(-x,-x,x);
- glColor3ub(255,0,255);
- glVertex3d(x,-x,x);
- glColor3ub(255,255,255);
- glVertex3d(x,x,x);
- glColor3ub(0,255,255);
- glVertex3d(-x,x,x);
- glEnd();
- glBegin(GL_LINES);
- glColor3ub(0,0,0);
- glVertex3d(-x,-x,-x);
- glColor3ub(0,0,255);
- glVertex3d(-x,-x,x);
- glColor3ub(255,0,0);
- glVertex3d(x,-x,-x);
- glColor3ub(255,0,255);
- glVertex3d(x,-x,x);
- glColor3ub(255,255,0);
- glVertex3d(x,x,-x);
- glColor3ub(255,255,255);
- glVertex3d(x,x,x);
- glColor3ub(0,255,0);
- glVertex3d(-x,x,-x);
- glColor3ub(0,255,255);
- glVertex3d(-x,x,x);
- glEnd();
- // Spheres
- glPolygonMode(GL_FRONT,GL_FILL);
- glPolygonMode(GL_BACK,GL_FILL);
- float radius = 0.1f;
- glPushMatrix();
- glTranslated(-m_Size,-m_Size,-m_Size);
- glColor3ub(0,0,0);
- gluSphere(pQuadric,radius,12,12);
- glPopMatrix();
- glPushMatrix();
- glTranslated(m_Size,-m_Size,-m_Size);
- glColor3ub(255,0,0);
- gluSphere(pQuadric,radius,12,12);
- glPopMatrix();
- glPushMatrix();
- glTranslated(-m_Size,m_Size,-m_Size);
- glColor3ub(0,255,0);
- gluSphere(pQuadric,radius,12,12);
- glPopMatrix();
- glPushMatrix();
- glTranslated(-m_Size,-m_Size,m_Size);
- glColor3ub(0,0,255);
- gluSphere(pQuadric,radius,12,12);
- glPopMatrix();
- glPushMatrix();
- glTranslated(m_Size,m_Size,-m_Size);
- glColor3ub(255,255,0);
- gluSphere(pQuadric,radius,12,12);
- glPopMatrix();
- glPushMatrix();
- glTranslated(-m_Size,m_Size,m_Size);
- glColor3ub(0,255,255);
- gluSphere(pQuadric,radius,12,12);
- glPopMatrix();
- glPushMatrix();
- glTranslated(m_Size,-m_Size,m_Size);
- glColor3ub(255,0,255);
- gluSphere(pQuadric,radius,12,12);
- glPopMatrix();
- glPushMatrix();
- glTranslated(m_Size,m_Size,m_Size);
- glColor3ub(255,255,255);
- gluSphere(pQuadric,radius,12,12);
- glPopMatrix();
- if(list)
- ::glEndList();
- gluDeleteQuadric(pQuadric);
- }
- //***********************************************
- // BuildListCloud
- //***********************************************
- void CColorDlg::BuildListCloud()
- {
- TRACE("Build list cloud...");
- // Image area
- unsigned int area = m_Image.GetWidth()
- * m_Image.GetHeight();
- TRACE("area : %d...",area);
- // Need valid image (24 bits)
- if(area == 0 ||
- m_Image.GetDepth() != 24)
- return;
- // Maximum -> area distinct colors / 2^24
- // This table is memory expansive, but short lived
- TRACE("alloc...");
- unsigned char *pTable = new unsigned char[16777216];
- memset(pTable,0,16777216); // init 0
- // Image data
- unsigned int wb32 = m_Image.GetWidthByte32();
- unsigned char *pData = m_Image.GetData();
- // Build a new list
- TRACE("build list...");
- int nb = 0;
- ::glNewList(2,GL_COMPILE_AND_EXECUTE);
- glBegin(GL_POINTS);
- float tmp = 2.0f/255.0f*m_Size;
- for(unsigned int j=0;j<m_Image.GetHeight();j++)
- for(unsigned int i=0;i<m_Image.GetWidth();i++)
- {
- unsigned char b = pData[wb32*j+3*i];
- unsigned char g = pData[wb32*j+3*i+1];
- unsigned char r = pData[wb32*j+3*i+2];
- if(!pTable[b*65536+g*256+r])
- {
- glColor3ub(r,g,b);
- float x = -m_Size+(float)r*tmp;
- float y = -m_Size+(float)g*tmp;
- float z = -m_Size+(float)b*tmp;
- glVertex3d(x,y,z);
- pTable[b*65536+g*256+r] = 1;
- nb++;
- }
- }
- glEnd();
- ::glEndList();
- TRACE("%d points...",nb);
- TRACE("cleanup...");
- delete [] pTable;
- TRACE("ok\n");
- }
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