2011-07-27 54 views
7

我有一個小問題:我無法修改SDL屏幕的像素。如何使用SDL修改像素?

具體而言,以下代碼不起作用。

Uint32 * pixels = (Uint32 *) screen -> pixels; 
screen -> pixels = pixels; 

這個編譯,但它不顯示任何東西。我錯過了什麼?

+0

我不是在這裏改變任何特定的像素。即時通訊只是複製一切,並試圖將其全部複製。格式化,你是什麼意思? – nory

+4

你意識到你的代碼什麼都不做? 'screen-> pixels = screen-> pixels;'。當然是 –

+0

。即時消息只是搞亂,瞭解語法和東西 – nory

回答

-2

您不得修改SDL_Surface結構的內容。如果你想複製像素你應該malloc()一些內存,然後memcpy()的像素。

+0

但我的目標是解決像素的問題 – nory

+0

您能澄清一下我們爲什麼**不能修改SDL_Surface的內容嗎?會/會導致錯誤/意外行爲? – snapfractalpop

+0

@snapfractalpop:從'SDL_video.h'文件中:「這個結構[SDL_Surface]應該被視爲只讀,'像素'[...]」除外。如果你不遵守你打破結構不變,所以庫將無法正常工作。 – rodrigo

18

我有以下功能躺在SDL_Surface像素設置。有兩個版本,分別用於32位,24位,16位和8位表面。如果你只想設置一個像素,你可以使用正常版本。但是如果你想設置一堆像素,首先你鎖定表面,然後使用nolock版本(因爲它不鎖定表面而命名),然後解鎖。這樣你就不會重複鎖定和解鎖表面,這應該是一個昂貴的操作,儘管我認爲我沒有實際測試過它。

void PutPixel32_nolock(SDL_Surface * surface, int x, int y, Uint32 color) 
{ 
    Uint8 * pixel = (Uint8*)surface->pixels; 
    pixel += (y * surface->pitch) + (x * sizeof(Uint32)); 
    *((Uint32*)pixel) = color; 
} 

void PutPixel24_nolock(SDL_Surface * surface, int x, int y, Uint32 color) 
{ 
    Uint8 * pixel = (Uint8*)surface->pixels; 
    pixel += (y * surface->pitch) + (x * sizeof(Uint8) * 3); 
#if SDL_BYTEORDER == SDL_BIG_ENDIAN 
    pixel[0] = (color >> 24) & 0xFF; 
    pixel[1] = (color >> 16) & 0xFF; 
    pixel[2] = (color >> 8) & 0xFF; 
#else 
    pixel[0] = color & 0xFF; 
    pixel[1] = (color >> 8) & 0xFF; 
    pixel[2] = (color >> 16) & 0xFF; 
#endif 
} 

void PutPixel16_nolock(SDL_Surface * surface, int x, int y, Uint32 color) 
{ 
    Uint8 * pixel = (Uint8*)surface->pixels; 
    pixel += (y * surface->pitch) + (x * sizeof(Uint16)); 
    *((Uint16*)pixel) = color & 0xFFFF; 
} 

void PutPixel8_nolock(SDL_Surface * surface, int x, int y, Uint32 color) 
{ 
    Uint8 * pixel = (Uint8*)surface->pixels; 
    pixel += (y * surface->pitch) + (x * sizeof(Uint8)); 
    *pixel = color & 0xFF; 
} 

void PutPixel32(SDL_Surface * surface, int x, int y, Uint32 color) 
{ 
    if(SDL_MUSTLOCK(surface)) 
     SDL_LockSurface(surface); 
    PutPixel32_nolock(surface, x, y, color); 
    if(SDL_MUSTLOCK(surface)) 
     SDL_UnlockSurface(surface); 
} 

void PutPixel24(SDL_Surface * surface, int x, int y, Uint32 color) 
{ 
    if(SDL_MUSTLOCK(surface)) 
     SDL_LockSurface(surface); 
    PutPixel24_nolock(surface, x, y, color); 
    if(SDL_MUSTLOCK(surface)) 
     SDL_LockSurface(surface); 
} 

void PutPixel16(SDL_Surface * surface, int x, int y, Uint32 color) 
{ 
    if(SDL_MUSTLOCK(surface)) 
     SDL_LockSurface(surface); 
    PutPixel16_nolock(surface, x, y, color); 
    if(SDL_MUSTLOCK(surface)) 
     SDL_UnlockSurface(surface); 
} 

void PutPixel8(SDL_Surface * surface, int x, int y, Uint32 color) 
{ 
    if(SDL_MUSTLOCK(surface)) 
     SDL_LockSurface(surface); 
    PutPixel8_nolock(surface, x, y, color); 
    if(SDL_MUSTLOCK(surface)) 
     SDL_UnlockSurface(surface); 
} 
+2

我知道這是一個老問題/答案,但我想指出,如果您嘗試抓取超出曲面邊界的像素,程序將崩潰。例如,試圖從64寬度的表面獲得一個64像素的X座標將會因爲最後一個像素位於63而崩潰。 – TyCobb

2

操作screen->pixels的內容將修改像素,但有一些注意事項。

首先,如您在代碼片段中所示,請注意screen->pixels是指向曲面像素數據的指針。基於表面的寬度(surface->pitch)和像素的大小(以字節爲單位),像素數據本身作爲來自該指針的線性陣列被訪問。 像素大小(aka深度)在初始化過程中設置,使用SDL_SetVideoMode(),可以在screen->format->BytesPerPixel中找到。

進行更改之前可能需要鎖定表面。

此外,根據傳遞給SDL_SetVideoMode()的選項,您可能還需要撥打SDL_Flip()來顯示您所做的更改。

像素操作的工作實例可以發現here


正如已指出了意見,在這個問題列出的代碼是不是真的要爲沒有變化正在對像素數據進行的做任何事情可見。

1

添加一個SDL2變種在表面上,但在渲染操作像素沒有(如果你試圖操縱你的屏幕外的像素不死機,不象以前的答案)

void putPixelRGB(SDL_Renderer* renderer, int x, int y, unsigned char r, unsigned char g, unsigned char b) 
{ 
    SDL_SetRenderDrawColor(renderer, (Uint8)r, (Uint8)g, (Uint8)b, 255); 
    SDL_RenderDrawPoint(renderer, x, y); 
} 
-1

爲什麼要改變一個像素?

作出新的表面&一個矩形

// CODE ------------>

SDL_Surface *screen, *PIXEL = NULL; 

SDL_Rect PIXELRect; 
PIXELRect.h=5; 
PIXELRect.w=5; 
PIXELRect.x=100; 
PIXELRect.y=100; 

screen = SDL_SetVideoMode(640, 468, 32, SDL_DOUBLEBUF | SDL_HWSURFACE | SDL_ANYFORMAT); 

while(running){ 
SDL_FillRect(screen, &PIXELRect, (#color)); 
}