用C读取图像(PPM)

用C读取图像(PPM),c,image,image-processing,ppm,C,Image,Image Processing,Ppm,所以我必须以PPM格式读取此图像,然后将其写入另一个文件。 但是,如果图像有注释,它将停止工作。 如果图像是这样的: P3 3 2 255 255 0 0 0 255 0 0 0 255 255 255 0 255 255 255 0 0 0 P3 3 2 255 # "3 2" is the width and height of the image in pixels # "255" is the maximu

所以我必须以PPM格式读取此图像,然后将其写入另一个文件。 但是,如果图像有注释,它将停止工作。 如果图像是这样的:

P3
3 2
255
255   0   0
  0 255   0
  0   0 255
255 255   0
255 255 255
  0   0   0
P3
3 2
255
# "3 2" is the width and height of the image in pixels
# "255" is the maximum value for each color
# The part below is image data: RGB triplets
255   0   0  # red
  0 255   0  # green
  0   0 255  # blue
255 255   0  # yellow
255 255 255  # white
  0   0   0  # black
它可以工作,但如果图像是这样的:

P3
3 2
255
255   0   0
  0 255   0
  0   0 255
255 255   0
255 255 255
  0   0   0
P3
3 2
255
# "3 2" is the width and height of the image in pixels
# "255" is the maximum value for each color
# The part below is image data: RGB triplets
255   0   0  # red
  0 255   0  # green
  0   0 255  # blue
255 255   0  # yellow
255 255 255  # white
  0   0   0  # black
它停止工作了。 我真的不知道为什么,因为我已经编程忽略评论。 我会在下面留下代码,也许有人能帮我

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

typedef struct pixel {
  unsigned int r,g,b;
} pixel;

typedef struct imagem{
  int cols,rows;
  char mnumber[2];
  int maxcolor;
  pixel *matrix;
}imagem;

static imagem read(const char *filename)
{
  imagem img;
  FILE *f;

  f = fopen(filename,"rb");

  if(f == NULL) {
    scanf("%c %c",&img.mnumber[0],&img.mnumber[1]);
    scanf("%d %d",&img.cols,&img.rows);
    scanf("%d",&img.maxcolor);

    img.matrix = (pixel*) malloc(img.cols*img.rows*sizeof(pixel));

    for(int i = 0; i < img.cols*img.rows;i++)
    {
      scanf("%u %u %u",&img.matrix[i].r,&img.matrix[i].g,&img.matrix[i].b);
    }
  } else {

      int i = 0;

      while(i != 2)
      {
        img.mnumber[i] = getc(f);
        //printf("%c\n",(char) img.mnumber[i]);
        i++;
      }
      
        int c = getc(f);
        while (c == '#') {
          while (getc(f) != '\n') {
            getc(f);
          }
          c = getc(f);
        }
        ungetc(c, f);

      
      fscanf(f,"%d %d",&img.cols,&img.rows);
     
      fscanf(f,"%d",&img.maxcolor);

      img.matrix = (pixel*)malloc(img.cols * img.rows* sizeof(pixel));


      for(int i = 0; i < img.cols*img.rows;i++)
      {
        fscanf(f,"%u %u %u",&img.matrix[i].r,&img.matrix[i].g,&img.matrix[i].b);
      }

      fclose(f);
      return img;
    }
    return img;
}
#包括
#包括
#包括
#包括
typedef结构像素{
无符号整数r,g,b;
}像素;
类型定义结构映像{
int列,行;
字符编号[2];
int-maxcolor;
像素*矩阵;
}imagem;
静态imagem读取(常量字符*文件名)
{
imagem-img;
文件*f;
f=fopen(文件名,“rb”);
如果(f==NULL){
scanf(“%c%c”、&img.mnumber[0]、&img.mnumber[1]);
scanf(“%d%d”、&img.cols、&img.rows);
scanf(“%d”,&img.maxcolor);
img.matrix=(像素*)malloc(img.cols*img.rows*sizeof(像素));
for(int i=0;i
我会这样写:

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

typedef struct pixel {
    unsigned int r,g,b;
} pixel;

typedef struct imagem{
    int cols, rows;
    char mnumber[2];
    int maxcolor;
    pixel *matrix;
} imagem;

static imagem read(const char *filename)
{
    imagem img;
    FILE *f;
    int i;
    char buf[BUFSIZ];

    if (filename == NULL) {
        f = stdin;
    } else {
        f = fopen(filename, "r");
        if (f == NULL) {
            fprintf(stderr, "Can't open %s\n", filename);
            exit(1);
        }
    }

    if (fgets(buf, sizeof buf, f) == NULL) {
        fprintf(stderr, "Can't read data\n");
        exit(1);
    }

    for (i = 0; i < 2; i++) {
        img.mnumber[i] = buf[i];
    }

    if (fgets(buf, sizeof buf, f) == NULL) {
        fprintf(stderr, "Can't read data\n");
        exit(1);
    }
    sscanf(buf, "%d %d", &img.cols, &img.rows);
    if (fgets(buf, sizeof buf, f) == NULL) {
        fprintf(stderr, "Can't read data\n");
        exit(1);
    }
    sscanf(buf, "%d", &img.maxcolor);

    img.matrix = malloc(img.cols * img.rows * sizeof(pixel));
    if (img.matrix == NULL) {
        fprintf(stderr, "malloc failed\n");
        exit(1);
    }

    i = 0;
    while (fgets(buf, sizeof buf, f) != NULL) {
        if (buf[0] == '#') continue;
        else {
            sscanf(buf, "%u %u %u", &img.matrix[i].r, &img.matrix[i].g, &img.matrix[i].b);
            i++;
        }
    }    fclose(f);
    return img;
}
#包括
#包括
#包括
#包括
typedef结构像素{
无符号整数r,g,b;
}像素;
类型定义结构映像{
int列,行;
字符编号[2];
int-maxcolor;
像素*矩阵;
}imagem;
静态imagem读取(常量字符*文件名)
{
imagem-img;
文件*f;
int i;
char buf[BUFSIZ];
如果(文件名==NULL){
f=stdin;
}否则{
f=fopen(文件名,“r”);
如果(f==NULL){
fprintf(stderr,“无法打开%s\n”,文件名);
出口(1);
}
}
if(fgets(buf,sizeof buf,f)=NULL){
fprintf(stderr,“无法读取数据”);
出口(1);
}
对于(i=0;i<2;i++){
img.mnumber[i]=buf[i];
}
if(fgets(buf,sizeof buf,f)=NULL){
fprintf(stderr,“无法读取数据”);
出口(1);
}
sscanf(基本单位、%d%d、&img.cols和&img.rows);
if(fgets(buf,sizeof buf,f)=NULL){
fprintf(stderr,“无法读取数据”);
出口(1);
}
sscanf(buf、%d、&img.maxcolor);
img.matrix=malloc(img.cols*img.rows*sizeof(像素));
if(img.matrix==NULL){
fprintf(stderr,“malloc失败\n”);
出口(1);
}
i=0;
while(fgets(buf,sizeof buf,f)!=NULL){
如果(buf[0]='#')继续;
否则{
sscanf(buf,“%u%u%u”,&img.matrix[i].r,&img.matrix[i].g,&img.matrix[i].b);
i++;
}
}fclose(f);
返回img;
}
  • 正如所建议的,最好结合使用
    fgets()
    sscanf()
    而不是
    fscanf()
    尤其是当我们需要处理不规则的线条时
  • 当 文件名被省略。只需将文件指针
    f
    分配给
    stdin
  • 建议将函数名
    read()
    更改为其他名称 因为它与现有的系统调用函数
    read(2)
    冲突

遵循基本的开发和调试原则:1。进行正确的错误检查。具体来说,检查
fscanf
malloc
调用的返回值。2使用调试器逐步检查代码,观察其流和变量值,以发现哪里出了问题。您的代码只处理一次注释,并且只处理文件的特定部分。只有当注释从文件的第二行开始时,它才有可能工作。因此,很明显,它对给出的示例不起作用,因为这不是注释的起点。在调试器中运行代码(甚至在循环中添加基本调试打印语句)应该清楚地表明注释循环从未运行。实际上,我认为如果注释从第二行开始,它甚至不会工作。因为代码没有正确处理第一行末尾的换行符。与
“#”相比,该换行符始终是字符,因此永远不会匹配。同样,更系统地调试代码,您应该可以轻松地发现这些问题。为了处理注释,我会使用
fgets
阅读每一行,然后使用
strchr
查找
的位置(如果有),并用nul字符
\0
替换
。然后,您需要检查该行是否为空,如果为空,则跳过该行。注意:实际图像的每个“行”都需要是4像素字节的倍数,因此单个像素(3字节)将无法正确显示,因此图像中的每个行都需要一个“虚拟”字节