You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Python中用OpenGL/Pyglet绘制像素、调整大小及解决代码报错

Fixing glDrawPixels Error & Scaling Pixels (1 Display Pixel = 9 Program Pixels)

Hey there! Let's work through fixing your error and getting that pixel scaling working exactly how you want it.

First: Fix the ctypes.ArgumentError in glDrawPixels

The error happens because OpenGL's glDrawPixels expects a contiguous block of memory for pixel data (like a C-style array), but your nested Python list [[[0]*3...]] is a collection of scattered objects that OpenGL can't interpret directly. Plus, you used GL_UNSIGNED_INT for color data—since each RGB channel is a 0-255 single-byte value, we need GL_UNSIGNED_BYTE instead.

Here are two solid fixes:

NumPy arrays are stored as contiguous memory blocks, which plays perfectly with OpenGL. First install NumPy if you haven't: pip install numpy, then adjust your code like this:

import numpy as np
# Replace your data list with this:
data = np.random.randint(0, 256, size=(H, W, 3), dtype=np.uint8)

Then update the glDrawPixels call to use the correct type:

glDrawPixels(W, H, GL_RGB, GL_UNSIGNED_BYTE, data)

Option 2: Use ctypes (No NumPy Needed)

If you prefer to stick to standard libraries, create a flat ctypes byte array:

import ctypes
# Create a contiguous array of bytes
data = (ctypes.c_ubyte * (W * H * 3))()
for y in range(H):
    for x in range(W):
        idx = (y * W + x) * 3
        data[idx] = random.randint(0,255)
        data[idx+1] = random.randint(0,255)
        data[idx+2] = random.randint(0,255)

Again, use GL_UNSIGNED_BYTE in the glDrawPixels call with this array.

Second: Achieve 1 Display Pixel = 9 Program Pixels (3x3 Scaling)

To make each program pixel take up 3x3 display pixels (9 total), we'll use glPixelZoom to scale the pixel output, plus adjust the window and projection to match.

Here's the full, working code with both fixes:

import random
import numpy as np
from pyglet.gl import *
from OpenGL.GLUT import *

# Program pixel resolution (200x200)
PROG_W, PROG_H = 200, 200
# Window size = 3x program resolution (so 1 program pixel = 9 display pixels)
WIN_W, WIN_H = PROG_W * 3, PROG_H * 3

win = pyglet.window.Window(width=WIN_W, height=WIN_H)

@win.event
def on_draw():
    glClearColor(0, 0, 0, 1)
    glClear(GL_COLOR_BUFFER_BIT)
    
    # Set up orthographic projection matching our program's pixel grid
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    glOrtho(0, PROG_W, PROG_H, 0, -1, 1)
    glMatrixMode(GL_MODELVIEW)
    glLoadIdentity()
    
    # Scale each program pixel to 3x3 display pixels
    glPixelZoom(3.0, 3.0)
    
    # Generate contiguous random pixel data with NumPy
    data = np.random.randint(0, 256, size=(PROG_H, PROG_W, 3), dtype=np.uint8)
    
    # Draw pixels with the correct data type
    glDrawPixels(PROG_W, PROG_H, GL_RGB, GL_UNSIGNED_BYTE, data)
    
    glutSwapBuffers()

pyglet.app.run()

Key Details in the Code:

  • glOrtho sets up a coordinate system that matches our program's 200x200 pixel grid, so glDrawPixels draws exactly where we expect.
  • glPixelZoom(3.0, 3.0) stretches each program pixel to 3 times its size in both X and Y directions—so 200x200 becomes 600x600, filling the window perfectly.
  • The NumPy array fixes the memory type error and makes generating pixel data cleaner.

Quick Notes

  • If you don't want to use glPixelZoom, you could manually draw 3x3 colored squares for each program pixel, but glPixelZoom is far more efficient.
  • Make sure all dependencies are installed: pip install pyglet numpy pyopengl

内容的提问来源于stack exchange,提问作者Popeye The Sailor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 05:14:06