【问题标题】:Issues writing PNM P6编写 PNM P6 的问题
【发布时间】:2014-05-12 01:34:33
【问题描述】:

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

P6
1786 1344
255

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

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

我的代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

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 < input->x; i++)
    {
        for (j=0; j < input->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 <input image file> <output image file>\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");
}

【问题讨论】:

  • 重新打开文件进行输出会擦除其当前内容。因此,在写入数据之前,请确保也写入这些行。 (优先于替代方法,它对 update 开放,fseek 到正确的位置,并在那里写入新数据。)
  • 这样的? ` void WriteImage(Image *img, char *filename) { FILE *f = fopen(filename, "wb"); fwrite(img->magicNum, 1, sizeof(char), f); fwrite(img->x, 1, sizeof(int), f); fwrite(img->y, 1, sizeof(int), f); fwrite(img->maxval, 1, sizeof(int), f) fwrite(img->data, sizeof(iPixel), img-> x * img-> y, f); f关闭(f); } `
  • 绝对不是。试试看,检查文件!根据规范(和输入文件),您正在编写应该使用 ASCII 的 binary
  • 该代码的问题到底出在哪里?大小不应该是 1,对吧?

标签: c file-io graphics io ppm


【解决方案1】:

小心写入与您正在阅读完全相同的格式。 PNM 格式为well defined,您阅读正确。然而,在写作过程中有几个错误:

  1. 使用"w""wb" 打开文件会将其截断为0 字节;
  2. 最佳做法是始终检查fopen 是否成功;
  3. 可以使用fscanf读取实际的ASCII数据,使用fread读取二进制数据。同样,写入 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 *
  • 无需检查每个单个像素
  • 检查更改了哪些像素的坐标...

【讨论】:

    猜你喜欢
    • 2014-06-30
    • 1970-01-01
    • 2016-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多