2016-06-26 60 views
0

我試圖將一個屏幕區域從opengl保存到位圖中。我試過使用FreeImage和SDL_Image,並且他們都要求我交換紅色和藍色通道。當然,這使我懷疑glReadPixels是這裏的問題... 我有這樣的示例代碼:glReadPixels藍色和紅色交換

bool CaptureScreenRegionToFile (uint32_t In_X, uint32_t In_Y, uint32_t In_Width, uint32_t In_Height, std::string In_Filename) 
{ 
GLubyte* ImageData = (GLubyte*) malloc (In_Width * In_Height * 3); 
glPixelStorei (GL_PACK_ALIGNMENT, 1); 
glReadPixels (In_X, In_Y, In_Width, In_Height, GL_RGB, GL_UNSIGNED_BYTE, ImageData); 

if (CheckError() == false) 
    { 
    free (ImageData); 
    return false; 
    } 

SDL_Surface *Surface; 

// JTP TODO Known bug here. Red and blue are swapped, for some reason... 
Surface = SDL_CreateRGBSurfaceFrom (ImageData, In_Width, In_Height, 3 * 8, In_Width * 3, 0x00FF0000, 0x0000FF00, 0x000000FF, 0); 
SDL_SaveBMP (Surface, In_Filename.c_str()); 
SDL_FreeSurface (Surface); 
free (ImageData); 

return true; 
} 

除非我調用CreateRGBSurfaceFrom後手動交換紅色和藍色通道,它的顏色會在BMP上交換。 glReadPixels應該這樣做嗎?我是否正確地調用它? 這裏有什麼問題?

+0

[可能相關的問題](http://stackoverflow.com/questions/5123387/loading-a-bmp-into-an-opengl-textures-switches-the-red-and-blue-colors-c-win )。 – DarkDust

回答

8

glReadPixels完美地工作,因爲它符合。當你讀回數據GL_RGB,你會得到如下的佈局在內存

0 1 2 3 4 5 6 7 8 
+---------------------+ 
|R|G|B|R|G|B|R|G|B|...| 
+---------------------+ 

現在你用每像素SDL_CreateRGBSurfaceFrom 24位。這將把每個3字節的組解釋爲一個像素。但是,它會將其視爲一個大整數,其中rmaskgmaskbmask和`amask。描述哪些比特屬於哪個圖像信道的參數。

例如,您使用0x00FF0000作爲紅色面具,這意味着位16到23將包含讀取(算上從最顯著位,以零開頭):

3  2|  1|  0|  0 bit 
1  4|  6|  8|  0 number 
+-----------------------------------+ 
|00000000|11111111|00000000|00000000| 
+-----------------------------------+ 
    byte 3 byte 2 byte 1 byte 0 

但是,你是最有可能一個little endian機器,其中最低有效字節存儲在最低存儲位置。這意味着您的rmask將被存儲爲:

0 1 2 byte number 
+--------------+ 
+ 00 | 00 | FF | 
+--------------+ 
    R G  B 

所以它不符合你讀像素數據的格式。還要注意,你的代碼是不可移植的,你會在一個big-endian架構上得到不同的結果。

更新1

如果你想寫這個代碼,可移植成爲可能,而不會增加一些尾數dependend #ifdefs,則無法使用的格式,每像素3個字節。但是,您可以使用GL_UNSIGNED_INT_8_8_8_8GL_UNSIGNED_INT_8_8_8_8_REV,其中每個像素都被視爲32位整數,並使用機器的本機排序進行存儲。 _REV變體將在最高有效字節中存儲格式的第一個組件(例如,紅色位於GL_RGBA),非最高位字節中的_REV變體。無論哪種情況,您都可以設置適當的掩碼,並且它將獨立於字節序工作。

+0

唉!我很懷疑,但希望SDL能夠照顧我的字節順序......這就是爲什麼我在所有參數(根據文檔,在內部照顧口罩)都嘗試0的原因,但仍然無濟於事......哦,以及....謝謝:)作爲如何使這個機器獨立輕鬆任何想法? –

+0

@JaoaoPincho:我更新了我的答案,試圖解決這個問題。 – derhass

相關問題