我正在尝试编写一个从 P6 到 P3 的转换器,这意味着从以二进制保存的数据到以 ASCII 保存的数据。
这是我为完成这项工作而编写的函数,但是 red
、green
和 blue
整数得到垃圾值而不是它们的十进制值。
int convertP6toP3(char* fileName)
{
FILE *src, *dest;
char *outputFilename;
char magicNumber[3];
int height, width, depth;
int red = 0, green = 0, blue = 0;
int i, j, widthCounter = 1;
if (checkFileExists(fileName) == FALSE)
{
printf("- Given file does not exists!\n");
return ERROR;
}
else
src = fopen(fileName, "rb");
outputFilename = getOutputFilename(fileName, ".p3.ppm");
dest = fopen(outputFilename, "w+");
// check that the input file is actually in P6 format
fscanf(src, "%s", magicNumber);
if (strcmp(magicNumber, "P6") != 0)
return ERROR;
fscanf(src, "%d %d %d", &height, &width, &depth);
fprintf(dest, "P3\n");
fprintf(dest, "#P3 converted from P6\n");
fprintf(dest, "%d %d\n%d\n", height, width, depth);
for (i = 0; i < width*height; i++)
{
for (j = 0; j < 3; j++)
{
fread(&red, sizeof(int), 1, src);
fread(&green, sizeof(int), 1, src);
fread(&blue, sizeof(int), 1, src);
}
for (j = 0; j < 3; j++)
fprintf(dest, "%d %d %d ", red, green, blue);
if (widthCounter == width)
{
fprintf(dest, "\n");
widthCounter = 1;
}
else
widthCounter++;
}
free(outputFilename);
fclose(src);
fclose(dest);
return TRUE;
}
我在读取二进制数据时做错了什么?高度、宽度和深度读取无误。
编辑:尝试使用读取的数据大小后,我得到了一些我无法解释的疯狂结果:
最佳答案
根据我们在该问题的评论线程中的讨论,我认为问题出在您对二进制数据的读取上。
如果每个样本是一个字节,您将希望对红色/蓝色/绿色变量使用 unsigned char
并执行 fread(&var, 1, 1, src)
我会想。我估计 sizeof(int)
可能是 4(取决于系统)所以对于红色、绿色和蓝色中的每一个,你一直在读取 4 个无符号字节并将它们存储在一个有符号整数中......这会导致麻烦。
此外,我认为您不需要内部循环for(j = ...
我会将您的内部循环重写为:
unsigned char red, green blue;
...
for (i = 0; i < width*height; i++)
{
fread(&red, 1, 1, src); //<-- Note inner for(j... has been removed
fread(&green, 1, 1, src);
fread(&blue, 1, 1, src);
fprintf(dest, "%u %u %u ",
(unsigned int)red,
(unsigned int)green,
(unsigned int)blue);
...
此外,我在 http://netpbm.sourceforge.net/doc/ppm.html 阅读的规范表示样本不需要是一个字节,具体取决于“...最大颜色值 (Maxval)...”的值,您似乎将其存储在 depth
中。
编辑#1: 我取出你的内部 j 循环的原因...
for (i = 0; i < width*height; i++)
{
for (j = 0; j < 3; j++)
{
fread(&red, sizeof(int), 1, src);
fread(&green, sizeof(int), 1, src);
fread(&blue, sizeof(int), 1, src);
}
...是因为这读取了 9 个字节,但只存储了最后读取的 3 个字节的值。这是因为在第一次循环迭代中,您读取了 3 个字节并将它们分别存储在变量 red
、green
和 blue
中。然后循环重复并将新数据读入这些变量。因此最后一组数据丢失等等...
我不知道为什么把它放回去有帮助?!这意味着可用的像素数据字节数比我阅读标准时想象的要多。它说的是宽度*高度像素,至少我是这样读的,但是使用 for(j...
循环你会读到 3*width*height。
鉴于我们所看到的(参见问题中的评论)看起来没有这个循环你没有阅读足够的样本,但从标准来看,我不明白为什么(还):)
编辑 2: 如果你尝试....
unsigned char red, green blue;
...
for (i = 0; i < width*height; i++)
{
for (j = 0; j < 3; j++)
{
fread(&red, 1, 1, src);
fread(&green, 1, 1, src);
fread(&blue, 1, 1, src);
fprintf(dest, "%u %u %u ",
(unsigned int)red,
(unsigned int)green,
(unsigned int)blue);
if (widthCounter == width)
{
fprintf(dest, "\n");
widthCounter = 1;
}
else
widthCounter++;
}
}
关于c - 从文件中读取二进制数并将其保存为整数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18334290/