How to scale glDrawPixels?
Asked Answered
M

3

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 ( );
    }
Midpoint answered 8/1, 2012 at 1:0 Comment(0)
T
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.

Tuggle answered 8/1, 2012 at 1:12 Comment(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! :DCholer
L
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);
Leucite answered 8/4, 2014 at 8:58 Comment(0)
C
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.

Cracker answered 8/1, 2012 at 13:33 Comment(3)
Ok, I'm going to check that, I really appreciate your help. I'll chaange to texturesMidpoint
@Cracker 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?Jermainejerman
@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.Cracker

© 2022 - 2024 — McMap. All rights reserved.