2014-03-13 54 views
1

我很早以前就開始使用Python和SDL2來編程我的心理實驗。因此,我的問題可能很基本。 我想創建一個填充兩種不同顏色的隨機像素的正方形,並將其顯示在屏幕中間。我設法創建了這個像素方塊並顯示它,但創建它需要一秒鐘的時間。因此,我想早些時候創建像素平方,即在參與者被其他事物佔據的時刻,然後再顯示它。 我想過使用SDL_CreateRenderer(window,-1,0)兩次,但我無法做到這一點。有沒有一種簡單的方法來解決我的問題?也許可以將創建的像素平方保存到文件中,然後再加載它?這就是我如何創建我的像素的正方形:創建像素正方形並稍後呈現

def put_pixel(x,y, color): 
     pixel = SDL_Rect(x, y,1,1)   

     if color == "orange": 
      SDL_SetRenderDrawColor(sdlRenderer,255,100,0,255) 
     elif color == "blue": 
      SDL_SetRenderDrawColor(sdlRenderer,0,100,255,255) 

     SDL_RenderFillRect(sdlRenderer,pixel) 
     return sdlRenderer 

def pixel_square(n_pixel_x,n_pixel_y, n_pixel_blue): 

    seq = range(n_pixel_x*n_pixel_y) 
    random.shuffle(seq) 

    lst = range(n_pixel_x*n_pixel_y) 
    pos=0 
    for i in range(n_pixel_x): 
     for j in range(n_pixel_y): 
       lst[seq[pos]] = [i,j] 
       pos = pos+1 

    #create orange square 
    square_orange=SDL_Rect(MAXX/2-n_pixel_x/2,MAXY/2-n_pixel_y/2,n_pixel_x,n_pixel_y)  
    SDL_SetRenderDrawColor(sdlRenderer,255,100,0,255) #orange 
    SDL_RenderFillRect(sdlRenderer,square_orange)  

    #add blue pixels 
    for i in range(n_pixel_blue): 
     put_pixel(x=MAXX/2-n_pixel_x/2+lst[i][0], y=MAXY/2-n_pixel_y/2+lst[i][1], color="blue")  

    return sdlRenderer 

後來我用

SDL_RenderPresent(sdlRenderer) 

顯示像素的正方形。

如果你能幫我解決這個問題,我會很高興的! 謝謝! Vero

回答

0

由於計算開銷和處理循環,您的創建映像的過程很慢。除了優化它們並預先計算,存儲和加載來自其他地方的圖像之外,如果適用,我建議使用Numpy來即時生成圖像。它具有開箱即用的隨機分配陣列,並針對速度進行了大量優化。

一個完全工作示例可能看起來像:

import sys 
import sdl2 
import sdl2.ext 
import numpy 

SIZE_X = 400 
SIZE_Y = 300 

# RGB values 
RED = 0xFF0000 
GREEN = 0x00FF00 

def pixelate(): 
    choices = [RED, GREEN] 
    pixelarray = numpy.random.choice(choices,(SIZE_X, SIZE_Y)) 
    buf = pixelarray.tostring() 
    # Create a software surface from the array. The depth and pitch are really 
    # important here, since we use a continuous byte buffer access. 
    image = sdl2.SDL_CreateRGBSurfaceFrom(buf, 
              SIZE_X, SIZE_Y, 
              32, # Bit depth, we use 32-bit RGB 
              SIZE_X, # pitch (byte size of a single scanline) - for 32 bit it is SIZE_X 
              0xFF0000, 
              0x00FF00, 
              0x0000FF, 
              0x0) 
    # required to avoid loosing buf. SDL_CreateRGBSurfaceFrom() will 
    # reference the byte buffer, not copy it 
    image._buffer = buf 
    return image 

def main(): 
    sdl2.ext.init() 

    window = sdl2.ext.Window("Pixel example", size=(800, 600)) 
    imgoffset = sdl2.SDL_Rect(200, 150, 0, 0) 
    window.show() 

    # Software rendering, we also could use hardware rending and use streaming 
    # textures, but the example would become more complicated then. 
    windowsurface = window.get_surface() 

    running = True 
    while running: 
     events = sdl2.ext.get_events() 
     for event in events: 
      if event.type == sdl2.SDL_QUIT: 
       running = False 
       break 
      if event.type == sdl2.SDL_MOUSEBUTTONDOWN: 
       image = pixelate() 
       sdl2.SDL_BlitSurface(image, None, windowsurface, imgoffset) 
     window.refresh() 
     sdl2.SDL_Delay(10) 
    sdl2.ext.quit() 
    return 0 

if __name__ == "__main__": 
    sys.exit(main()) 

最重要的部分是像素化()函數,它創建填充有傳遞的值的隨機分佈指定大小的2D陣列(你的顏色)。 SDL2允許您從字節緩衝區創建曲面(圖像),因此下一步是從2D numpy陣列創建緩衝區並使用該特定緩衝區創建曲面。 一旦完成,它是一個在屏幕上顯示圖像的簡單問題。

如果Numpy不能在環境中使用的,我會避免單獨繪製每個像素使用put_pixel()方法,因爲這將導致在SDL2渲染器的每種顏色變化的至少一個上下文切換(最壞的情況下)。相反,預先計算一個二維數組,並用必要的值填充它,然後基於它創建一個軟件表面緩衝區(或者同樣是一個流紋理),然後通過單個操作在屏幕上閃爍。