Demos (master): Pixel/subpixel test for lines.

Keith Whitwell keithw at kemper.freedesktop.org
Mon Aug 23 13:15:01 UTC 2010


Module: Demos
Branch: master
Commit: 8c7630de48440f67cbca46a161905066b885a8a5
URL:    http://cgit.freedesktop.org/mesa/demos/commit/?id=8c7630de48440f67cbca46a161905066b885a8a5

Author: Hui Qi Tay <hqt at vmware.com>
Date:   Mon Aug 16 10:55:18 2010 +0100

Pixel/subpixel test for lines.

Should extend to test other primitives like triangles and points.

---

 src/demos/Makefile.am |    1 +
 src/demos/SConscript  |    1 +
 src/demos/pixeltest.c |  465 +++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 467 insertions(+), 0 deletions(-)

diff --git a/src/demos/Makefile.am b/src/demos/Makefile.am
index b00d6ec..38f44b3 100644
--- a/src/demos/Makefile.am
+++ b/src/demos/Makefile.am
@@ -62,6 +62,7 @@ bin_PROGRAMS = \
 	morph3d \
 	multiarb \
 	paltex \
+	pixeltest \
 	pointblast \
 	projtex \
 	ray \
diff --git a/src/demos/SConscript b/src/demos/SConscript
index cfad95e..600ef4d 100644
--- a/src/demos/SConscript
+++ b/src/demos/SConscript
@@ -32,6 +32,7 @@ progs = [
     'morph3d',
     'multiarb',
     'paltex',
+    'pixeltest',
     'pointblast',
     'projtex',
     'ray',
diff --git a/src/demos/pixeltest.c b/src/demos/pixeltest.c
new file mode 100644
index 0000000..ad44d6f
--- /dev/null
+++ b/src/demos/pixeltest.c
@@ -0,0 +1,465 @@
+
+/* Pixeltest for lines.
+ * Hui Qi Tay 
+ *
+ * Modified from
+ * glReadPixels and glCopyPixels test by Brian Paul.
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+#include <GL/glut.h>
+
+
+static int ImgWidth, ImgHeight;
+static int WinWidth, WinHeight;
+
+static int APosX, APosY;         /* simple drawpixels */
+static int BPosX, BPosY;         /* read/draw pixels */
+int MouseButton, MouseY, MouseX; /* mouse control */
+float x0offset = 0.0f;           /* for line translation */
+float y0offset = 0.0f; 
+float x1offset = 0.0f;
+float y1offset = 0.0f;
+float width = 1.0f;
+
+struct Line{
+   float x0;
+   float y0;
+   float x1;
+   float y1;
+};
+
+#define STEP 16                 /* subpixel resolution 1/STEP */
+#define SIZE 128                /* of non-zoomed drawing region */
+#define ZOOM 32                 /* scale factor for zooming */
+
+struct Line line;
+static GLboolean DrawFront = GL_FALSE;
+GLushort TempImage[SIZE][SIZE]; /* original 128 by 128 pixel image */
+GLushort myImage[SIZE*ZOOM][SIZE*ZOOM]; /* zoom by a factor of 32 */
+
+static GLenum ReadFormat = GL_RGB;
+static GLenum ReadType = GL_UNSIGNED_SHORT_5_6_5;
+
+static void
+Reset( void )
+{
+   APosX = 8;     APosY = 24;
+   MouseX = 8;    MouseY = 24;
+   BPosX = APosX + ImgWidth + 40;   BPosY = 24;
+}
+
+
+static void
+PrintString(const char *s)
+{
+   while (*s) {
+      glutBitmapCharacter(GLUT_BITMAP_8_BY_13, (int) *s);
+      s++;
+   }
+}
+
+static void
+drawzoomline(int x0, int y0, int x1, int y1, GLushort color)
+{
+   /* Use the Bresenham Line Algorithm here. */
+   GLboolean steep = (abs(y1 - y0) > abs(x1 - x0));
+      
+   int deltax;
+   int deltay;
+   float error;
+   float deltaerr;
+   int ystep;
+   int y;
+
+   if (steep) {
+      int temp0 = x0;
+      int temp1 = x1;
+      x0 = y0;
+      y0 = temp0;
+      x1 = y1;
+      y1 = temp1;
+   }
+   if (x0 > x1) {
+      int tem0 = x0;
+      int tem1 = y0;
+      x0 = x1;
+      x1 = tem0;
+      y0 = y1;
+      y1 = tem1;
+   }
+      
+   deltax = x1 - x0;
+   deltay = abs(y1 - y0);
+   error = 0.0;
+   deltaerr = (float)deltay / (float)deltax;
+   y = y0;
+
+   if (y0 < y1)
+      ystep = 1; 
+   else
+      ystep = -1;
+  
+   for (int x = x0; x < x1; x++) {
+      if (y>0 && x>0) {
+         if (!steep) {
+            myImage[y][x] = color;
+            myImage[y+1][x] = color;
+         }
+         else {
+            myImage[x][y] = color;
+            myImage[x+1][y] = color;
+         }
+      }
+      error = error + deltaerr;
+      if (error >= 0.5) {
+         y = y + ystep;
+         error = error - 1.0;
+      }
+   }
+} 
+
+static void
+drawline(float xf0, float yf0, float xf1, float yf1, GLushort color)
+{
+   /* map line endpoints on to relevant pixel grids */
+   int x0 = xf0 * ZOOM; 
+   int y0 = yf0 * ZOOM;
+   int x1 = xf1 * ZOOM;
+   int y1 = yf1 * ZOOM;
+
+   drawzoomline(x0, y0, x1, y1, color);
+}
+
+static void
+plot(int x, int y, GLushort color)
+{
+   int i, j;
+
+   for (i=0; i<ZOOM; i++) {
+      for (j=0; j<ZOOM; j++) {
+         if (i == 0 || j == 0) {
+            /* draws the gridlines, use top-left rule */
+            myImage[x*ZOOM+i][y*ZOOM+j] = 0;
+         }
+         else if ((i >= 13 && i <= 19 && j == 16 ) || (j >= 13 && j <= 19 && i == 16) ){
+            /* draws the pixel centre */
+            myImage[x*ZOOM+i][y*ZOOM+j] = 0;
+         }
+	 else if ( (i + j == 15) || fabsf(i - j) == 16 || (i + j == 47) ){
+	    /* draws the pixel diamond, to test diamond exit rule */
+            myImage[x*ZOOM+i][y*ZOOM+j] = 0;
+         }
+         else
+            myImage[x*ZOOM+i][y*ZOOM+j]= color;
+      }   
+   }
+}
+
+
+static void
+drawMagnifiedView(void)
+{
+   float halfwidth = width/2;
+   int i, j;
+
+   /* Sets up pixel grid for each pixel
+    */      
+   for (i=0; i<128; i++){
+      for (j=0; j<128; j++){
+         plot(i, j, TempImage[i][j]);
+      }
+   }
+      
+   /* Draws the actual line on zoomed version */
+   drawline(line.x0+x0offset+APosX-MouseX, line.y0+y0offset+APosY-MouseY, 
+            line.x1+x1offset+APosX-MouseX, line.y1+y1offset+APosY-MouseY, 0);
+      
+   /* Draws bounding line area */ 
+   if (fabsf(line.x0 + x0offset - line.x1 - x1offset) >= 
+       fabsf(line.y0 + y0offset - line.y1 - y1offset)) {
+      /* X-MAJOR line */
+      drawline(line.x0+x0offset+APosX-MouseX, line.y0+y0offset+APosY-MouseY+halfwidth, 
+               line.x1+x1offset+APosX-MouseX, line.y1+y1offset+APosY-MouseY+halfwidth, 0xffff);
+      drawline(line.x0+x0offset+APosX-MouseX, line.y0+y0offset+APosY-MouseY-halfwidth, 
+               line.x1+x1offset+APosX-MouseX, line.y1+y1offset+APosY-MouseY-halfwidth, 0xffff);
+      drawline(line.x0+x0offset+APosX-MouseX, line.y0+y0offset+APosY-MouseY+halfwidth, 
+               line.x0+x0offset+APosX-MouseX, line.y0+y0offset+APosY-MouseY-halfwidth, 0xffff);
+      drawline(line.x1+x1offset+APosX-MouseX, line.y1+y1offset+APosY-MouseY+halfwidth, 
+               line.x1+x1offset+APosX-MouseX, line.y1+y1offset+APosY-MouseY-halfwidth, 0xffff);
+   }
+   else {
+      /* Y-MAJOR line */
+      drawline(line.x0+x0offset+APosX-MouseX+halfwidth, line.y0+y0offset+APosY-MouseY, 
+               line.x1+x1offset+APosX-MouseX+halfwidth, line.y1+y1offset+APosY-MouseY, 0xffff);
+      drawline(line.x0+x0offset+APosX-MouseX-halfwidth, line.y0+y0offset+APosY-MouseY, 
+               line.x1+x1offset+APosX-MouseX-halfwidth, line.y1+y1offset+APosY-MouseY, 0xffff);
+      drawline(line.x0+x0offset+APosX-MouseX+halfwidth, line.y0+y0offset+APosY-MouseY, 
+               line.x0+x0offset+APosX-MouseX-halfwidth, line.y0+y0offset+APosY-MouseY, 0xffff);
+      drawline(line.x1+x1offset+APosX-MouseX+halfwidth, line.y1+y1offset+APosY-MouseY, 
+               line.x1+x1offset+APosX-MouseX-halfwidth, line.y1+y1offset+APosY-MouseY, 0xffff);
+   }
+}
+
+static void
+Display( void )
+{
+   float z = 0;
+
+   glClearColor(.3, .3, .3, 1);
+   glClear( GL_COLOR_BUFFER_BIT );
+   
+   /* draw original image */
+
+   glViewport(APosX, APosY, ImgWidth, ImgHeight);
+   glMatrixMode( GL_PROJECTION );
+   glLoadIdentity();
+   /* transformation to match the pixel array */
+   glOrtho(0, ImgWidth, 0, ImgHeight, -1.0, 1.0);
+   glDisable(GL_CULL_FACE);
+
+   /* Blue background
+    */
+   glBegin(GL_POLYGON);
+   glColor3f(.5,.5,1); 
+   glVertex3f(0, 0, z);
+   glVertex3f(0, 150, z);
+   glVertex3f(150, 150, z);
+   glVertex3f(150, 0, z);
+   glEnd();
+
+   /* Original line
+    */
+   glLineWidth(width);
+   glBegin(GL_LINES);
+   glColor3f(.8,0,0);
+   glVertex3f(line.x0+x0offset, line.y0+y0offset, z);
+   glColor3f(0,.9,0); 
+   glVertex3f(line.x1+x1offset, line.y1+y1offset, z);
+   glEnd();
+
+
+   glColor3f(1,1,1);
+   glViewport( 0, 0, WinWidth, WinHeight );
+   glMatrixMode( GL_PROJECTION );
+   glLoadIdentity();
+   glOrtho( 0.0, WinWidth, 0.0, WinHeight, -1.0, 1.0 );
+   
+   /* might try alignment=4 here for testing */
+   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+   glPixelStorei(GL_PACK_ALIGNMENT, 1);
+
+   /* Legend */
+   glBegin(GL_LINE_STRIP);
+   glVertex3f(590, 800, 0);
+   glVertex3f(590, 670, 0);
+   glVertex3f(990, 670, 0);
+   glVertex3f(990, 800, 0);   
+   glVertex3f(590, 800, 0);   
+   glEnd();
+
+   glRasterPos2i(600, 780);
+   PrintString("Key:");
+   glRasterPos2i(600, 760);   
+   PrintString(" Change linewidth: v/b");
+   glRasterPos2i(600, 740);   
+   PrintString(" Move whole line: UP/DOWN/LEFT/RIGHT arrow keys");
+   glRasterPos2i(600, 720);   
+   PrintString(" Move endpoint: i/k/j/l");
+   glRasterPos2i(600, 700);   
+   PrintString(" Move startpoint: w/s/a/d");
+   glRasterPos2i(600, 680);
+   PrintString(" Change view: drag/click mouse");
+
+   glRasterPos2i(8, ImgHeight+30);   
+   PrintString("Zoom Pixel Test");
+
+   glRasterPos2i(APosX, 5);
+   PrintString("Original");
+
+   /* do readpixels, drawpixels */
+   glRasterPos2i(BPosX, 5);
+   PrintString("Read/DrawPixels");
+
+   /* clear the temporary image to white (helpful for debugging */
+   memset(TempImage, 255, sizeof TempImage);
+
+   /* Read pixels from the color buffer */
+   glReadPixels(MouseX, MouseY, ImgWidth, ImgHeight,
+                ReadFormat, ReadType, TempImage);
+   
+   glRasterPos2i(BPosX, BPosY);
+   glDisable(GL_DITHER);
+   drawMagnifiedView();
+ 
+   /* Write pixels to the frame buffer */
+   glDrawPixels(ImgWidth*5, ImgHeight*5, ReadFormat, ReadType, myImage);
+
+   if (!DrawFront)
+      glutSwapBuffers();
+   else
+      glFinish();
+}
+
+
+static void
+Reshape( int width, int height )
+{
+   WinWidth = width;
+   WinHeight = height;
+
+   glViewport( 0, 0, width, height );
+   glMatrixMode( GL_PROJECTION );
+   glLoadIdentity();
+   glOrtho( 0.0, width, 0.0, height, -1.0, 1.0 );
+   glMatrixMode( GL_MODELVIEW );
+   glLoadIdentity();
+}
+
+
+static void 
+Key( unsigned char key, int x, int y)
+{
+   switch (key) {
+   case 'w':
+      y0offset += 1.0/(float)STEP;
+      break;
+   case 's':
+      y0offset -= 1.0/(float)STEP;
+      break;
+   case 'd':
+      x0offset += 1.0/(float)STEP;
+      break;
+   case 'a':
+      x0offset -= 1.0/(float)STEP;
+      break;
+   case 'i':
+      y1offset += 1.0/(float)STEP;
+      break;
+   case 'k':
+      y1offset -= 1.0/(float)STEP;
+      break;
+   case 'l':
+      x1offset += 1.0/(float)STEP;
+      break;
+   case 'j':
+      x1offset -= 1.0/(float)STEP;
+      break;
+   case 'b':
+      width += 1.0/(float) STEP;
+      printf("width = %f\n", width);
+      break;
+   case 'v':
+      width -= 1.0/(float) STEP;
+      printf("width = %f\n", width);
+      break;
+   case 27:
+      exit(1);
+      break;
+   default:
+      return;
+   }
+   glutPostRedisplay();
+} 
+
+static void 
+SpecialKey( int k, int x, int y)
+{
+   switch (k) {
+   case GLUT_KEY_UP:
+      y0offset += 1.0/(float)STEP;
+      y1offset += 1.0/(float)STEP;
+      break;
+   case GLUT_KEY_DOWN:
+      y0offset -= 1.0/(float)STEP;
+      y1offset -= 1.0/(float)STEP;
+      break;
+   case GLUT_KEY_RIGHT:
+      x0offset += 1.0/(float)STEP;
+      x1offset += 1.0/(float)STEP;
+      break;
+   case GLUT_KEY_LEFT:
+      x0offset -= 1.0/(float)STEP;
+      x1offset -= 1.0/(float)STEP;
+      break;
+   default:
+      return;
+   }
+   glutPostRedisplay();
+} 
+ 
+static void 
+Mouse(int button, int state, int x, int y)
+{
+   /* if left mouse button is pressed and dragged
+    * then change screen view
+    */
+   if (state == GLUT_DOWN &&
+       button == GLUT_LEFT_BUTTON &&
+       x < 160 &&
+       y > WinHeight-180)
+   {
+	    MouseX = x;
+            MouseY = WinHeight - y;
+   }
+   glutPostRedisplay();
+}
+
+static void 
+processMouseMotion(int x, int y)
+{
+    MouseX = x;
+    MouseY = WinHeight - y;
+    glutPostRedisplay();
+}
+
+static void
+Init()
+{
+   printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION));
+   printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
+
+   ImgWidth=128;
+   ImgHeight=128;
+   x0offset = 0;
+   y0offset = 0;
+   x1offset = 0;
+   y1offset = 0;
+
+   line.x0 = 2;
+   line.y0 = 2;
+   line.x1 = 15;
+   line.y1 = 15; 
+   glutSetCursor(GLUT_CURSOR_CROSSHAIR);
+
+   glPixelStorei(GL_UNPACK_ROW_LENGTH, ImgWidth*ZOOM);
+   glPixelStorei(GL_PACK_ROW_LENGTH, ImgWidth);
+
+   Reset();
+}
+
+
+int
+main( int argc, char *argv[] )
+{
+   glutInitWindowSize( 1000, 800 );
+   glutInit( &argc, argv );
+  
+   glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE );
+   glutCreateWindow(argv[0]);
+   Init();
+   glutReshapeFunc( Reshape );
+   glutKeyboardFunc (Key);
+   glutSpecialFunc(SpecialKey);
+   glutDisplayFunc( Display );
+
+   glutMouseFunc(Mouse);
+   glutMotionFunc(processMouseMotion);
+
+   glutMainLoop();
+   return 0;
+}




More information about the mesa-commit mailing list