【问题标题】:glReadPixels swaps blue and redglReadPixels 交换蓝色和红色
【发布时间】:2016-06-26 11:31:05
【问题描述】:

我正在尝试将 opengl 中的屏幕区域保存到位图中。我尝试过使用 FreeImage 和 SDL_Image,它们都要求我交换红色和蓝色通道。当然,这让我怀疑 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 应该这样做吗?我正确地称呼它吗? 这里有什么问题?

【问题讨论】:

标签: opengl sdl-image


【解决方案1】:

glReadPixels 可以按预期完美运行。当你以GL_RGB读回数据时,你会在内存中得到如下布局

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

现在您使用每像素 24 位的 SDL_CreateRGBSurfaceFrom。这会将每组 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

所以它与您从中读取像素数据的格式不匹配。另请注意,您的代码不可移植,在大端架构上您会得到不同的(预期的)结果。

更新 1

如果您想尽可能地编写此代码,而不添加一些 endian-dependend #ifdefs,则不能使用每像素 3 个字节的格式。但是,您可以使用GL_UNSIGNED_INT_8_8_8_8GL_UNSIGNED_INT_8_8_8_8_REV,其中每个像素都被视为一个32 位整数,并使用机器的本机字节顺序存储。 _REV 变体将存储格式的第一个组件(例如,GL_RGBA 中的红色)在最低有效字节中,非_REV 变体在最高有效字节中。无论哪种情况,您都可以设置适当的掩码,它会独立于字节顺序工作。

【讨论】:

  • 啊!我很怀疑,但希望 SDL 会为我处理字节序...这就是为什么我也尝试在所有参数中使用 0 (根据文档,内部处理掩码),但仍然无济于事...哦,好吧....谢谢 :) 知道如何轻松地使这台机器独立于机器吗?
  • @JoaoPincho:我更新了我的答案以尝试解决这个问题。
猜你喜欢
  • 2012-08-03
  • 2022-12-19
  • 1970-01-01
  • 1970-01-01
  • 2014-08-26
  • 1970-01-01
  • 1970-01-01
  • 2016-08-20
  • 1970-01-01
相关资源
最近更新 更多