如何读写一个ppm文件?
How to read and write a ppm file?
我尝试读取一个 ppm 文件并创建一个相同的新文件。但是当我用 GIMP2 打开它们时,图像就不一样了。
我的代码哪里有问题?
int main()
{
FILE *in, *out;
in = fopen("parrots.ppm","r");
if( in == NULL )
{
std::cout<<"Error.\n";
return 0;
}
unsigned char *buffer = NULL;
long size = 0;
fseek(in, 0, 2);
size = ftell(in);
fseek(in, 0, 0);
buffer = new unsigned char[size];
if( buffer == NULL )
{
std::cout<<"Error\n";
return 0;
}
if( fread(buffer, size, 1, in) < 0 )
{
std::cout<<"Error.\n";
return 0 ;
}
out = fopen("out.ppm","w");
if( in == NULL )
{
std::cout<<"Error.\n";
return 0;
}
if( fwrite(buffer, size, 1, out) < 0 )
{
std::cout<<"Error.\n";
return 0;
}
delete[] buffer;
fcloseall();
return 0;
}
在此之前,我读取了一个结构中的 ppm 文件,当我编写它时,我得到了相同的图像,但绿色比原始图片中的更强烈。然后我尝试了这个简单的阅读和写作,但我得到了相同的结果。
int main()
缺少包含。
FILE *in, *out;
C 风格 I/O 在 C++ 程序中,为什么?此外,在初始化时声明,接近首次使用。
in = fopen("parrots.ppm","r");
这是在文本模式下打开文件,这肯定不是您想要的。使用 "rb"
作为模式。
unsigned char *buffer = NULL;
在初始化时声明,接近首次使用。
fseek(in, 0, 2);
你应该使用SEEK_END
,不能保证定义为2。
fseek(in, 0, 0);
参见上文,因为 SEEK_SET
不能保证定义为 0。
buffer = new unsigned char[size];
if( buffer == NULL )
默认情况下,new
不会return一个NULL
指针,而是抛出一个std::bad_alloc
异常。 (由于过度分配是大多数当前操作系统的常态,即使使用 malloc()
,检查 NULL
也不会保护您免受内存不足的影响,但很高兴看到您养成了检查的习惯。 )
C++11 给我们带来了smart pointers。使用它们。它们是避免内存泄漏(C++ 的极少数弱点之一)的绝佳工具。
if( fread(buffer, size, 1, in) < 0 )
成功使用fread
应该return写入对象的数量,应该检查是否等于第三个参数(!= 1
),而不是< 0
。
out = fopen("out.ppm","w");
又是文本模式,这里要"wb"
。
if( fwrite(buffer, size, 1, out) < 0 )
请参阅上面关于 fread
return 值的注释。同样适用于此。
fcloseall();
不是标准函数。使用 fclose( in );
和 fclose( out );
.
C++11 化的解决方案(为简洁起见省略了错误检查)看起来有点像这样:
#include <iostream>
#include <fstream>
#include <memory>
int main()
{
std::ifstream in( "parrots.ppm", std::ios::binary );
std::ofstream out( "out.ppm", std::ios::binary );
in.seekg( 0, std::ios::end );
auto size = in.tellg();
in.seekg( 0 );
std::unique_ptr< char[] > buffer( new char[ size ] );
in.read( buffer.get(), size );
out.write( buffer.get(), size );
in.close();
out.close();
return 0;
}
当然,智能 解决方案可以通过 Boost.Filesystem or the standard functionality(在撰写本文时处于实验阶段)进行实际的文件系统复制。
我尝试读取一个 ppm 文件并创建一个相同的新文件。但是当我用 GIMP2 打开它们时,图像就不一样了。
我的代码哪里有问题?
int main()
{
FILE *in, *out;
in = fopen("parrots.ppm","r");
if( in == NULL )
{
std::cout<<"Error.\n";
return 0;
}
unsigned char *buffer = NULL;
long size = 0;
fseek(in, 0, 2);
size = ftell(in);
fseek(in, 0, 0);
buffer = new unsigned char[size];
if( buffer == NULL )
{
std::cout<<"Error\n";
return 0;
}
if( fread(buffer, size, 1, in) < 0 )
{
std::cout<<"Error.\n";
return 0 ;
}
out = fopen("out.ppm","w");
if( in == NULL )
{
std::cout<<"Error.\n";
return 0;
}
if( fwrite(buffer, size, 1, out) < 0 )
{
std::cout<<"Error.\n";
return 0;
}
delete[] buffer;
fcloseall();
return 0;
}
在此之前,我读取了一个结构中的 ppm 文件,当我编写它时,我得到了相同的图像,但绿色比原始图片中的更强烈。然后我尝试了这个简单的阅读和写作,但我得到了相同的结果。
int main()
缺少包含。
FILE *in, *out;
C 风格 I/O 在 C++ 程序中,为什么?此外,在初始化时声明,接近首次使用。
in = fopen("parrots.ppm","r");
这是在文本模式下打开文件,这肯定不是您想要的。使用 "rb"
作为模式。
unsigned char *buffer = NULL;
在初始化时声明,接近首次使用。
fseek(in, 0, 2);
你应该使用SEEK_END
,不能保证定义为2。
fseek(in, 0, 0);
参见上文,因为 SEEK_SET
不能保证定义为 0。
buffer = new unsigned char[size];
if( buffer == NULL )
默认情况下,new
不会return一个NULL
指针,而是抛出一个std::bad_alloc
异常。 (由于过度分配是大多数当前操作系统的常态,即使使用 malloc()
,检查 NULL
也不会保护您免受内存不足的影响,但很高兴看到您养成了检查的习惯。 )
C++11 给我们带来了smart pointers。使用它们。它们是避免内存泄漏(C++ 的极少数弱点之一)的绝佳工具。
if( fread(buffer, size, 1, in) < 0 )
成功使用fread
应该return写入对象的数量,应该检查是否等于第三个参数(!= 1
),而不是< 0
。
out = fopen("out.ppm","w");
又是文本模式,这里要"wb"
。
if( fwrite(buffer, size, 1, out) < 0 )
请参阅上面关于 fread
return 值的注释。同样适用于此。
fcloseall();
不是标准函数。使用 fclose( in );
和 fclose( out );
.
C++11 化的解决方案(为简洁起见省略了错误检查)看起来有点像这样:
#include <iostream>
#include <fstream>
#include <memory>
int main()
{
std::ifstream in( "parrots.ppm", std::ios::binary );
std::ofstream out( "out.ppm", std::ios::binary );
in.seekg( 0, std::ios::end );
auto size = in.tellg();
in.seekg( 0 );
std::unique_ptr< char[] > buffer( new char[ size ] );
in.read( buffer.get(), size );
out.write( buffer.get(), size );
in.close();
out.close();
return 0;
}
当然,智能 解决方案可以通过 Boost.Filesystem or the standard functionality(在撰写本文时处于实验阶段)进行实际的文件系统复制。