这个问题有很多弱点——太多了,无法在评论中解决……
这个问题被标记为 C++。为什么容易出错fprintf()
?为什么不std::fstream
呢?它具有类似的功能(甚至更多),但增加了类型安全性(该printf()
系列无法提供)。
的对应部分fprintf()
是fscanf()
。格式化程序类似,但存储类型必须在格式化程序中配置,比在fprintf()
.
如果第一个代码示例是尝试从datafile.x
...读取像素,为什么datafile = fopen("pixeldata.x" , "w");
?要打开文件以fopen()
供阅读,它应该是"r"
.
char Image2[14] = "image_out.bmp";
是正确的(如果我计算正确的话)但维护不友好。让编译器为您完成工作:
char Image2[] = "image_out.bmp";
要为像素数据提供存储(在 OP 的情况下)固定大小为 512 × 512 字节,最简单的方法是:
unsigned char pixeldata[512 * 512];
在局部变量中存储该大小的数组 (512 × 512 = 262144 字节 = 256 KByte) 可能被某些人视为潜在问题。另一种方法是使用 astd::vector<unsigned char> pixeldata;
代替。(std::vector
在堆内存中动态分配存储,其中局部变量通常在一种堆栈内存上,而堆栈内存通常大小有限。)
关于std::vector<unsigned char> pixeldata;
,我看到两个选项:
预分配定义:
std::vector<unsigned char> pixeldata(512 * 512);
这样它就可以像上面的数组一样使用。
没有预分配的定义:
std::vector<unsigned char> pixeldata;
这将允许将每个读取像素添加到末尾std::vector::push_back()
。
可能是,值得事先保留最终尺寸,因为它从一开始就知道:
std::vector<unsigned char> pixeldata;
pixeldata.reserve(512 * 512); // size reserved but not yet used
所以,这就是它最终的样子:
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <vector>
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image_write.h"
int main()
{
const int w = 512, h = 512;
// read data
FILE *datafile = fopen("pixeldata.x" , "r");
if (!datafile) { // success of file open should be tested ALWAYS
std::cerr << "Cannot open 'pixeldata.x'!\n";
return -1; // ERROR! (bail out)
}
typedef unsigned char uchar; // for convenience
std::vector<uchar> pixeldata(w * h);
char Image2[] = "image_out.bmp";
for (int i = 0, n = w * h; i < n; ++i) {
if (fscanf(datafile, "%hhx", &pixeldata[i]) < 1) {
std::cerr << "Failed to read value " << i << of 'pixeldata.x'!\n";
return -1; // ERROR! (bail out)
}
}
fclose(datafile);
// write BMP image
stbi_write_bmp(Image2, w, h, 1, pixeldata.data());
// Actually, success of this should be tested as well.
// done
return 0;
}
一些附加说明:
请对这段代码持保留态度。我还没有编译或测试它。(我将此作为任务留给 OP,但会对“错误报告”做出反应。)
我默默地删除了using namespace std;
:SO:为什么“使用命名空间标准”被认为是不好的做法?
我添加了对文件操作成功的检查。由于很多原因,文件操作总是有利于失败。对于文件写入,甚至fclose()
应该进行测试。写入的数据可能会被缓存,直到文件关闭并且仅将缓存的数据写入文件可能会失败(因为这可能会溢出可用的卷空间)。
OP 使用了幻数(图像宽度和大小),这被认为是不好的做法。它使代码维护不友好,其他读者可能更难理解:SO:什么是幻数,为什么它不好?