读取 P6 二进制 ppm 文件
Reading a P6 binary ppm file
所以我已经阅读了一些与此相关的问题,但其中 none 已经解决了我的问题。我目前正在尝试读取 P6 ppm 文件(它是一个二进制文件)。我当前的代码是
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
struct pixel {
char red;
char green;
char blue;
};
int main(int argc, char **argv)
{
char type[3];
int numRow, numCol, maxNum;
FILE *oldFile, *newFile;
struct pixel currentPixel;
char buffer[5];
oldFile = fopen(argv[1], "rb");
if(oldFile == NULL) {
fprintf(stderr, "Could not open file %s for reading in binary", argv[1]);
return 0;
}
fscanf(oldFile, "%2s", type);
type[2] = '[=10=]';
if(strcmp(type, "P6") != 0) { //Make sure we have a P6 file
printf("This file is not of type P6");
return 0;
}
newFile = fopen(argv[2], "wb");
fprintf(newFile, "%s\n", type);
/*Read number of columns
rows and
The max number that can represent a colour*/
fscanf(oldFile, "%d", &numCol);
fscanf(oldFile, "%d", &numRow);
fscanf(oldFile, "%d", &maxNum);
/*Print the information to newFile*/
fprintf(newFile, "%d %d\n", numCol, numRow);
fprintf(newFile, "%d\n", maxNum);
fseek(oldFile, 1, SEEK_CUR);
fread(¤tPixel, sizeof(struct pixel), 1, oldFile);
printf("%c %c %c", currentPixel.red, currentPixel.green, currentPixel.blue);
fclose(newFile);
fclose(oldFile);
return 0;
}
所以开始有效,我的 newFile 包含行 P6、3、3 和 255。然后我尝试使用 fread
行读取实际像素。这是它失败的地方,我不确定为什么。它目前在钻石内部打印出两个问号。我目前只试图读入构成一个像素的前三个数字(一个红色分量、一个绿色分量和一个蓝色分量)。
我也有同一张图片的P3文件,P3文件长这样:
P3
3 3
255
0 255 255 0 0 0 0 0 255
255 0 255 100 100 100 255 0 0
255 255 0 255 255 255 0 255 0
所以二进制文件应该像这样设置,但只是二进制格式。当我输入
od -c binaryImage.ppm
我明白了
0000000 P 6 \n 3 3 \n 2 5 5 \n [=12=] 377 377 [=12=] [=12=]
0000020 [=12=] [=12=] [=12=] 377 377 [=12=] 377 X X X 377 [=12=] [=12=] 377 377 [=12=]
0000040 377 377 377 [=12=] 377 [=12=]
0000046
我不确定为什么我的 fread 函数不是 working.Not 确定是否相关但我正在 Linux Ubuntu 上编译
gcc -Wall rotate.c -o rotate
您将 RGB 值打印为字符而不是数字。在结构中将它们保留为 unsigned char
(因为它们的值在 [0-255] 之间),但在打印时使用 %d
。您应该按如下方式使用 printf
:
printf("%d %d %d", currentPixel.red, currentPixel.green, currentPixel.blue);
我还建议不要使用结构来读取 RGB 值,因为编译器可能会添加一个填充字节以使结构与机器字(例如 32 位)对齐。在 32 位系统中,您将读取 4 个字节。您可以检查此打印 sizeof(struct pixel)
。要阅读有关结构对齐的更多信息,您可以查看维基百科文章 Data Structure Alignment.
使用 char
数组代替结构:
unsigned char currentPixel[3];
...
fread(currentPixel, 3, 1, oldFile);
printf("%d %d %d", currentPixel[0], currentPixel[1], currentPixel[2]);
此外,如果您需要读取整个图像,请创建一个大小为 number of pixels x 3
的 unsigned char
数组。 3 是 RGB 元组的字节数。如果 PPM 格式在每行末尾包含一些填充,您也需要考虑这一点。
所以我已经阅读了一些与此相关的问题,但其中 none 已经解决了我的问题。我目前正在尝试读取 P6 ppm 文件(它是一个二进制文件)。我当前的代码是
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
struct pixel {
char red;
char green;
char blue;
};
int main(int argc, char **argv)
{
char type[3];
int numRow, numCol, maxNum;
FILE *oldFile, *newFile;
struct pixel currentPixel;
char buffer[5];
oldFile = fopen(argv[1], "rb");
if(oldFile == NULL) {
fprintf(stderr, "Could not open file %s for reading in binary", argv[1]);
return 0;
}
fscanf(oldFile, "%2s", type);
type[2] = '[=10=]';
if(strcmp(type, "P6") != 0) { //Make sure we have a P6 file
printf("This file is not of type P6");
return 0;
}
newFile = fopen(argv[2], "wb");
fprintf(newFile, "%s\n", type);
/*Read number of columns
rows and
The max number that can represent a colour*/
fscanf(oldFile, "%d", &numCol);
fscanf(oldFile, "%d", &numRow);
fscanf(oldFile, "%d", &maxNum);
/*Print the information to newFile*/
fprintf(newFile, "%d %d\n", numCol, numRow);
fprintf(newFile, "%d\n", maxNum);
fseek(oldFile, 1, SEEK_CUR);
fread(¤tPixel, sizeof(struct pixel), 1, oldFile);
printf("%c %c %c", currentPixel.red, currentPixel.green, currentPixel.blue);
fclose(newFile);
fclose(oldFile);
return 0;
}
所以开始有效,我的 newFile 包含行 P6、3、3 和 255。然后我尝试使用 fread
行读取实际像素。这是它失败的地方,我不确定为什么。它目前在钻石内部打印出两个问号。我目前只试图读入构成一个像素的前三个数字(一个红色分量、一个绿色分量和一个蓝色分量)。
我也有同一张图片的P3文件,P3文件长这样:
P3
3 3
255
0 255 255 0 0 0 0 0 255
255 0 255 100 100 100 255 0 0
255 255 0 255 255 255 0 255 0
所以二进制文件应该像这样设置,但只是二进制格式。当我输入
od -c binaryImage.ppm
我明白了
0000000 P 6 \n 3 3 \n 2 5 5 \n [=12=] 377 377 [=12=] [=12=]
0000020 [=12=] [=12=] [=12=] 377 377 [=12=] 377 X X X 377 [=12=] [=12=] 377 377 [=12=]
0000040 377 377 377 [=12=] 377 [=12=]
0000046
我不确定为什么我的 fread 函数不是 working.Not 确定是否相关但我正在 Linux Ubuntu 上编译
gcc -Wall rotate.c -o rotate
您将 RGB 值打印为字符而不是数字。在结构中将它们保留为 unsigned char
(因为它们的值在 [0-255] 之间),但在打印时使用 %d
。您应该按如下方式使用 printf
:
printf("%d %d %d", currentPixel.red, currentPixel.green, currentPixel.blue);
我还建议不要使用结构来读取 RGB 值,因为编译器可能会添加一个填充字节以使结构与机器字(例如 32 位)对齐。在 32 位系统中,您将读取 4 个字节。您可以检查此打印 sizeof(struct pixel)
。要阅读有关结构对齐的更多信息,您可以查看维基百科文章 Data Structure Alignment.
使用 char
数组代替结构:
unsigned char currentPixel[3];
...
fread(currentPixel, 3, 1, oldFile);
printf("%d %d %d", currentPixel[0], currentPixel[1], currentPixel[2]);
此外,如果您需要读取整个图像,请创建一个大小为 number of pixels x 3
的 unsigned char
数组。 3 是 RGB 元组的字节数。如果 PPM 格式在每行末尾包含一些填充,您也需要考虑这一点。