编写PNM P6的问题

我正在编写一个程序,它接收两个重复的PNM P6文件,将第一个文件的内存放入缓冲区,在其上创建一条黄色对角线,并将结果写入第二个文件。 当我运行它时,输出文件已损坏,无法显示。 我注意到在查看输出时它缺少应该位于顶部的三行:

P6 1786 1344 255 

我不知道如何以编程方式确保这些行保留在代码中 – 我无法弄清楚为什么它们甚至首先被覆盖。

当我手动将这些行添加到输出时,该文件不再被破坏。 但是,没有出现黄色对角线。 这是同一个问题的一部分,还是我还应该考虑修复其他问题?

我的代码:

 #include  #include  #include  typedef struct { unsigned char red, green, blue; } iPixel; typedef struct { int x, y; iPixel *data; } Image; Image * ReadImage(char *filename) { FILE *f = fopen(filename, "rb"); Image *img = NULL; char magicNum[128]; int width, height, maxval; if (f == NULL) { fprintf(stderr, "Unable to open file %s\n", filename); return NULL; } fscanf(f, "%s\n%d %d\n%d\n", magicNum, &width, &height, &maxval); /* printf("Magic num = %s width = %d, height = %d, maxval = %d\n", magicNum, width, height, maxval) ; */ if (strcmp(magicNum, "P6") != 0) { fprintf(stderr, "Unable to read from file %s, because it is not a PNM file of type P6\n", filename); return NULL; } img = (Image *) malloc(sizeof(Image)); img -> x = width; img -> y = height; img -> data = (iPixel*) malloc(img -> x * img -> y * sizeof(iPixel)); fread(img -> data, sizeof(iPixel), width*height, f); fclose(f); return img; } void WriteImage(Image *img, char *filename) { FILE *f = fopen(filename, "wb"); fwrite(img->data, sizeof(iPixel), img-> x * img-> y, f); fclose(f); } Image * YellowDiagonal(Image *input) { int i, j; for (i = 0; i x; i++) { for (j=0; j y; j++) { if (i==j) { input->data[i].red=255; input->data[i].green=255; input->data[i].blue=0; } } } return input; } int main(int argc, char *argv[]) { if (argc != 3) { fprintf(stderr, "Usage: ./3A_c.c  \n"); exit(EXIT_FAILURE); } Image *img; img = ReadImage(argv[1]); fprintf(stderr, "Read.\n"); YellowDiagonal(img); fprintf(stderr, "Diagonal line.\n"); WriteImage(img, argv[2]); fprintf(stderr, "Write.\n"); } 

小心写出与您正在阅读的格式完全相同的格式。 PNM格式定义良好 ,您正在正确阅读它。 然而,在写作例程中有一些错误:

  1. "w""wb"打开文件会将其截断为0字节;
  2. 最佳做法总是检查fopen成功;
  3. 读取实际的ASCII数据可以用fscanffread二进制数据来完成。 类似地,编写ASCII应该使用fprintf完成,而只使用fwrite二进制数据。
  4. 如果您想确保编写与之前读过的数据相同的数据,则需要将其保存在某处。 读取maxval变量,但不保存,因此我无法将其写回。 但是,这不是一个问题,因为你的代码的其余部分假设图像是R8G8B8,所以maxval应该总是255

这是一个有效的调整后的WriteImage

 void WriteImage(Image *img, char *filename) { FILE *f = fopen(filename, "wb"); if (f == NULL) { printf ("Unable to open '%s' for writing!\n", filename); /* better would be: "return -1" to indicate an error, 0 otherwise */ return; } fprintf (f, "P6\n"); fprintf (f, "%d %d\n", img->x, img->y); /* actually you need to write 'maxval' here */ fprintf (f, "%d\n", 255); fwrite(img->data, sizeof(iPixel), img->x * img->y, f); fclose(f); } 

有了上述方法,您现在可以看到您的“对角线”不正确! 我不打算解决这个问题(我想我们无法看到发生的事情会阻止你在你的轨道上),但这里有一些指示只是为了指导你:

  • 如果您正在原位更改数据则无需返回Image *
  • 无需检查每个像素
  • 检查更改像素的坐标…