5

I need to scale the result of glDrawPixels image.

I'm drawing a 640x480 pixels image buffer with glDrawPixels in a Qt QGLWidget.

I tryed to do the following in PaintGL:

glScalef(windowWidth/640, windowHeight/480, 0);
glDrawPixels(640,480,GL_RGB,GL_UNSIGNED_BYTE,frame);

But it doesn't work.

I am setting the OpenGL viewport and glOrtho with the size of the widget as:

void WdtRGB::paintGL() {

         glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

         // Setup the OpenGL viewpoint
         glMatrixMode(GL_PROJECTION);
         glLoadIdentity();
         glOrtho(0, windowWidth, windowHeight, 0, -1.0, 1.0);

    glDepthMask(0);
        //glRasterPos2i(0, 0);
        glScalef(windowWidth/640, windowHeight/480, 0);
        glDrawPixels(640,480,GL_RGB,GL_UNSIGNED_BYTE,frame);
    }

    //where windowWidth and windowHeight corresponds to the widget size.
    /the init functions are:

    void WdtRGB::initializeGL() {

        glClearColor ( 0.8, 0.8, 0.8, 0.0); // Background to a grey tone

        /* initialize viewing values  */
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();

        glOrtho(0, windowWidth, windowHeight, 0, -1.0, 1.0);

        glEnable (GL_DEPTH_TEST);

    }

    void WdtRGB::resizeGL(int w, int h) {
        float aspect=(float)w/(float)h;

        windowWidth = w;
        windowHeight = h;
        glViewport (0, 0, (GLsizei) w, (GLsizei) h);
        glMatrixMode (GL_PROJECTION);
        glLoadIdentity ();

        if( w <= h )
                glOrtho ( -5.0, 5.0, -5.0/aspect, 5.0/aspect, -5.0, 5.0);
        else
                glOrtho (-5.0*aspect, 5.0*aspect, -5.0, 5.0, -5.0, 5.0);

        //printf("\nresize");
        emit changeSize ( );
    }
genpfault
  • 51,148
  • 11
  • 85
  • 139
Hermandroid
  • 2,120
  • 4
  • 29
  • 35

3 Answers3

5

It sounds like what you actually need to do instead of calling glDrawPixels () is to load your image data into a texture and draw a textured quad the size of the window. So something like this:

glGenTextures (1, &texID);
glBindTextures (GL_TEXTURE_RECTANGLE_EXT, texID);
glTexImage2D (GL_TEXTURE_RECTANGLE_EXT, 0, GL_RGBA, 640, 480, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, frame);
glBegin (GL_QUADS);
glTexCoord2f (0, 0);
glVertex2f (0, 0);
glTexCoord2f (640, 0);
glVertex2f (windowWidth, 0);
glTexCoord2f (640, 480);
glVertex2f (windowWidth, windowHeight);
glTexCoord2f (0, 480);
glVertex2f (0, windowHeight);
glEnd();

Or if that's too much work, glPixelZoom (windowWidth / 640, windowHeight / 480), might do the trick, too.

user1118321
  • 25,567
  • 4
  • 55
  • 86
  • 1
    I found that I needed a glEnable/glDisable (GL_TEXTURE_RECTANGLE) pair around the begin/end to get the texture applied to the quads, and that I needed to use GL_TEXTURE_RECTANGLE without the _EXT, but this otherwise worked perfectly for me too, thanks! :D – David Gardner Jan 27 '13 at 17:29
2

Just for further reference: Instead of doing the glScalef(windowWidth/640, windowHeight/480, 0); before the glDrawPixels you should do a pixel zoom:

glRasterPos2i(0,0);
GLint iViewport[4];
glGetIntegerv(GL_VIEWPORT, iViewport);
glPixelZoom(iViewport[2]/640, iViewport[3]/480);
glDrawPixels(640,480,GL_RGB,GL_UNSIGNED_BYTE,frame);
Theolodis
  • 4,977
  • 3
  • 34
  • 53
1

I need to scale the result of glDrawPixels image.

glDrawPixels directly goes to the framebuffer. So every incoming pixel is mapped 1:1 to the output. There is a function (ah, why am I telling you this) glPixelZoom, which allows you to zoom glDrawPixels.

BUT I urge you, not to use glDrawPixels!

Use textures quads instead. glDrawPixels is a depreciated function, no longer supported by modern OpenGL-3. And even when it was not deprecated it still is a very slow function. Textured quads are better in every regard.

datenwolf
  • 159,371
  • 13
  • 185
  • 298
  • Ok, I'm going to check that, I really appreciate your help. I'll chaange to textures – Hermandroid Jan 08 '12 at 14:55
  • @datenwolf how can I access frame buffer directly? I want to draw a 2d buffer of my choice in real time, using EGL as a nice proxy for hardware acceleration. Are textures suitable for this? – rr- Apr 11 '15 at 17:57
  • 1
    @rr-: OpenGL does not give you direct (as in giving you a pointer to the framebuffer memory) to write to. Also for efficiency reasons direct writes are to be avoided. You want to asynchronously write to the framebuffer. And using any variant of OpenGL this is done by loading your image into a texture and issung a drawing command for a textured quad. The command is queued up and executed asynchronously, so that your CPU process is not stalled by any graphics events it had to wait for. – datenwolf Apr 11 '15 at 22:20