gpt4 book ai didi

c++ - BMP 创建 - C++ ofstream 输出损坏

转载 作者:搜寻专家 更新时间:2023-10-31 00:18:01 26 4
gpt4 key购买 nike

我目前正在为 OpenGL 框架编写 BMP 屏幕截图函数,但在写出数据时遇到了一个奇怪的问题。从 glReadPixels 引入的数据以及 BMP header 都是正确的,但似乎 ofstream.write 操作随机插入了无效值。

图像的正确 BMP 摘录(由 Paint 创建)和由我的函数制作的图像的摘录如下,突出显示了不正确的字节。正确的行永远是第一行。


0x08C行

3B 0D 4A 3A 0A 48 38 08 45 36
3B 0D 4A 3A 0D 0A 48 38 08 45
^^

第 0x0DC 行(此时已经关闭一个)

3E 2F 07 3D 2E 0A 3F 31 0E 44
07 3E 2F 07 3D 2E 0D 0A 3F 31
^^

第 0x0E68 行(紧挨着下一行,相隔两行)

35 13 48 3A 10 44 36 0A 3F 31
0E 44 35 13 48 3A 10 44 36 0D
^^

因此似乎存在一种模式,其中无效值始终是 0x0D 并且它被插入到 0x0A 的前面。我不知道为什么会发生这种情况,因为我已经确认 glReadPixels 中的 header 和数据都是正确的。该方法的代码如下。

bool captureScreen( const char* name, unsigned originX, unsigned originY, unsigned width, unsigned height )
{

//...

GLubyte* imageData = new GLubyte[ width * height * 3 ];
glReadPixels( originX, originY, width, height, GL_BGR, GL_UNSIGNED_BYTE, imageData );

//...

captureAsBMP( imageData, width, height, path.c_str( ) );

//...
}

bool captureAsBMP( GLubyte* data, GLuint width, GLuint height, const char* path )
{
std::ofstream stream( path, std::ios_base::out );

if( !stream.is_open( ) )
return false;

unsigned char BMPHeader[ 14 ] = { /* cut for brevity */ };
unsigned char DIBHeader[ 40 ] = { /* cut for brevity */ };
unsigned char padding[ 4 ] = { 0x00, 0x00, 0x00, 0x00 };

unsigned int paddingLength = 4 - (( width * 3 ) % 4);
paddingLength = ( paddingLength == 4 ? 0 : paddingLength );

long fileSize = ( width * height * 3 ) + ( paddingLength * height ) + 54;
long dataSize = fileSize - 54;

memcpy( &BMPHeader[ 2 ], &fileSize, sizeof( long ) );
memcpy( &DIBHeader[ 4 ], &width, sizeof( unsigned int ) );
memcpy( &DIBHeader[ 8 ], &height, sizeof( unsigned int ) );
memcpy( &DIBHeader[ 20 ], &dataSize, sizeof( long ) );

stream.write( reinterpret_cast< char* >( BMPHeader ), 14 );
stream.write( reinterpret_cast< char* >( DIBHeader ), 40 );

unsigned pos = 0;

// Write out one row at a time
for( int i = 0; i < height; i++ )
{
stream.write( reinterpret_cast< char* >( &data[ pos ] ), ( width * 3 ) );

// Is there padding that needs to be added?
if( paddingLength != 0 )
stream.write( reinterpret_cast< char* >( padding ), paddingLength );

// Update where we are in data
pos += width * 3;
}

stream.close( );

return true;
}

另请注意,所讨论的图像是 800x600,因此此错误发生在行的第一个流写入期间,在填充和 pos 递增之前。

最后,它应该如何显示:http://imgur.com/oziid

它是如何工作的:http://imgur.com/SrXgA (重新保存在 Paint 中,因为 Imgur 当然提示它被损坏了)

最佳答案

您需要通过添加 std::ios::binary 标志以二进制模式打开文件以避免 CRLF conversion .在 Windows 上,换行符表示为两个字节 0x0D 0x0A(回车 + 换行符,或 CR LF)——C 和 C++ 运行时会自动将它们转换为输入时的普通换行符,并且它们会自动转换普通换行符 '\n ' 当文件以文本模式(默认)打开时,在输出时转换为 CRLF 对。

要抑制这些换行符转换,您需要告诉运行时不要翻译。对于 C++ 的 iostream,这是通过 std::ios::binary 标志完成的;对于 C 的 FILE* 流,这是通过 "b" 模式标志完成的,例如"rb" 用于读取或 "wb" 用于写入。

关于c++ - BMP 创建 - C++ ofstream 输出损坏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11813994/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com