display an image with pyopengl and Pillow

3 篇文章 0 订阅
使用opengl和Pillow来显示图片。
如果你以前使用过python来处理图片的话,那你对PIL有一定的了解,PIL是python的一个第3方库,主要是用来做图片处理的,但从1.1.7版本开始就已经停止维护了。
而Pillow则是PIL的衍生分支,它支持PIL的API,使用方法都一样,到现在还在维护。

首先我们来创建一个QGLWidget
class MyGLWidget(QGLWidget):

添加一些buffer(内存)对象
# buffer object ids
self.vaoID = None
self.vboVerticesID = None
self.vboIndicesID = None
self.textureID = None

self.sprogram = None

使用Pillow来加载图片
# chang this to load your image file
self.loadImage('Lenna.png')

然后我们重写initializeGL方法来进行初始化
def initializeGL(self):

创建并编译shader
# create shader from file
vshader = shaderFromFile(GL_VERTEX_SHADER, 'shader.vert')
fshader = shaderFromFile(GL_FRAGMENT_SHADER, 'shader.frag')
# compile shaders
self.sprogram = shaders.compileProgram(vshader, fshader)

设置shader里的一些参数
# get attribute and set uniform for shaders
glUseProgram(self.sprogram)
self.vertexAL = glGetAttribLocation(self.sprogram, 'pos')
self.tmUL = glGetUniformLocation(self.sprogram, 'textureMap')
glUniform1i(self.tmUL, 0)
glUseProgram(0)

设置平面的坐标和顶点循序
# two triangle to make a quad
self.vertices = np.array((0.0, 0.0,
1.0, 0.1,
1.0, 0.9,
0.0, 1.0), dtype=np.float32)
self.indices = np.array((0, 1, 2,
0, 2, 3), dtype=np.ushort)

[img]http://dl2.iteye.com/upload/attachment/0095/9107/bedc95d9-b691-3db2-820b-8ff211e9ef97.png[/img]

然后将数据传送到显卡
# set up vertex array
self.vaoID = glGenVertexArrays(1)
self.vboVerticesID = glGenBuffers(1)
self.vboIndicesID = glGenBuffers(1)

glBindVertexArray(self.vaoID)
glBindBuffer(GL_ARRAY_BUFFER, self.vboVerticesID)
# copy vertices data from memery to gpu memery
glBufferData(GL_ARRAY_BUFFER, self.vertices.nbytes, self.vertices, GL_STATIC_DRAW)
# tell opengl how to procces the vertices data
glEnableVertexAttribArray(self.vertexAL)
glVertexAttribPointer(self.vertexAL, 2, GL_FLOAT, GL_FALSE, 0, None)
# send the indice data too
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.vboIndicesID)
glBufferData(GL_ELEMENT_ARRAY_BUFFER, self.indices.nbytes, self.indices, GL_STATIC_DRAW)

在我们传送图片数据到显卡之前,我们需要从上向下反转图片,不然我们显示的图片就是上向下反转的图片
# flip the image in the Y axis
im = self.im.transpose(Image.FLIP_TOP_BOTTOM)

然后传送图片数据到显卡
# set up texture
self.textureID = glGenTextures(1)
glActiveTexture(GL_TEXTURE0)
glBindTexture(GL_TEXTURE_2D, self.textureID)
# set filters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
# set uv coords mode
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP)
# send the image data to gpu memery
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, self.im.size[0], self.im.size[1],
0, GL_RGB, GL_UNSIGNED_BYTE, im.tostring())

这里你可以吧uv的坐标模式换一下
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT)

并把shader.vert里的uv坐标改成
uv = pos*2 - 1;

你将会得到

[img]http://dl2.iteye.com/upload/attachment/0095/9125/7b516777-0128-3232-b439-6e759a889767.png[/img]

到这里我们就可以开始进行渲染绘制了
def paintGL(self, *args, **kwargs):
# clear the buffers
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

# active shader
glUseProgram(self.sprogram)
# draw triangles
glDrawElements(GL_TRIANGLES, self.indices.size, GL_UNSIGNED_SHORT, None)
glUseProgram(0)

至于shader.vert和shader.frag,做的都是非常简单的事情
shader.vert负责接收顶点信息,并保存uv的坐标,最后把uv传递给shader.frag,然后它通过uv坐标来读取图片的像素并导出给硬件,最终硬件进行显示。

[img]http://dl2.iteye.com/upload/attachment/0095/9029/32af3768-9514-3135-91be-663f4ea3290c.png[/img]


完整的代码可以从这里获取
[url]https://github.com/mackst/opengl-samples/tree/master/displayImage[/url]

ps.图片需要你们自己添加
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值