以高分辨率保存来自opengl(pyqt)的图像:

时间:2014-02-05 10:32:33

标签: image opengl pyqt4

我有一个PyQt应用程序,其中QtOpenGL.QGLWidget显示风力涡轮机。

我想将涡轮机保存为高分辨率的图像,但到目前为止,我只能保存渲染的屏幕图像,即在我的情况下1680x1050减去边框,工具栏等。

glPixelStorei(GL_PACK_ALIGNMENT, 1)
data = glReadPixels(0, 0, self.width, self.height, GL_RGBA, GL_UNSIGNED_BYTE)

我如何解决这个限制?

修改

我尝试过使用帧缓冲,

from __future__ import division
import OpenGL
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
from PIL import Image
import time, sys
import numpy as np


WIDTH = 400
HEIGHT = 300

def InitGL():
    glMatrixMode(GL_PROJECTION)
    gluPerspective(45.0, float(WIDTH) / float(HEIGHT), 0.1, 100.0)
    glMatrixMode(GL_MODELVIEW)


def DrawGLScene():
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    glLoadIdentity()
    glTranslatef(0, 0., -3)
    glutWireTeapot(1)
    glFlush()

def capture_screen():
    DrawGLScene()
    glPixelStorei(GL_PACK_ALIGNMENT, 1)
    data = glReadPixels(0, 0, WIDTH, HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE)
    image = Image.fromstring("RGBA", (WIDTH, HEIGHT), data)
    image.transpose(Image.FLIP_TOP_BOTTOM).show()

def capture_fbo(width=800, height=600):

    fbo = glGenFramebuffers(1)
    render_buf = glGenRenderbuffers(1)

    glBindRenderbuffer(GL_RENDERBUFFER, render_buf)

    glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA, width, height);
    glBindFramebuffer(GL_FRAMEBUFFER, fbo)
    glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, render_buf);
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    glMatrixMode(GL_MODELVIEW)
    glLoadIdentity()
    glTranslatef(1, 1., -3)
    glScale(width / WIDTH, height / HEIGHT, 1)
    glutWireTeapot(1.0)
    glFlush()
    glReadBuffer(GL_COLOR_ATTACHMENT0);
    data = glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE)
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
    image = Image.fromstring("RGBA", (width, height), data)
    image.transpose(Image.FLIP_TOP_BOTTOM).show()

    glDeleteFramebuffers(1, [fbo]);
    glDeleteRenderbuffers(1, [render_buf]);


glutInit(sys.argv)
glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH)
glutInitWindowSize(WIDTH, HEIGHT)
window = glutCreateWindow("")
glutDisplayFunc(DrawGLScene)
InitGL()
DrawGLScene()
capture_screen()
capture_fbo()

glutMainLoop()

但在正常屏幕窗口区域之外的区域没有绘制任何内容 enter image description here

1 个答案:

答案 0 :(得分:1)

glReadPixels的工作方式是从当前选择的帧缓冲区中读取像素。

不确定帧缓冲是什么?这是维基页面:http://www.opengl.org/wiki/Framebuffer_Object

快速解释一下,您可以将帧缓冲视为您的图形卡所使用的“画布”。你可以拥有任意数量的帧缓冲区(sorta ...大多数驱动程序在某处定义一个限制),但只会显示一个。这是选定的帧缓冲区,只能与您在屏幕上显示的窗口一样大。

以下是制作帧缓冲的教程:http://www.lighthouse3d.com/tutorials/opengl-short-tutorials/opengl_framebuffer_objects/

修改它,以便您创建的帧缓冲区是您想要截取屏幕截图的分辨率。

设置了帧缓冲区后,您可以像这样绘制它:

glBindFramebuffer(GL_DRAW_FRAMEBUFFER, buffer);
/* drawing code */
glReadPixels();

如果您希望仍能在屏幕上看到某些内容,则需要在绘制到新的帧缓冲区后绘制到默认的帧缓冲区:

glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); //"0" means return to default framebuffer
/* same drawing code */

请注意,这意味着您将绘制整个场景两次!确保你的帧率可以处理它。