用 C 读取图像 (PPM)

时间:2021-05-14 23:02:02

标签: 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 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;
}

1 个答案:

答案 0 :(得分:1)

我会把它写成这样:

#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;
}
  • 按照建议,最好使用 fgets()sscanf() 而不是 fscanf() 尤其是当我们需要处理不规则线条时。
  • 您不必编写特定的代码来读取 stdin 文件名被省略。只需将文件指针 f 分配给 stdin
  • 建议把函数名read()改成别的 因为它与现有的系统调用函数 read(2) 冲突。
相关问题