首页 > 解决方案 > 使用 C 读取图像 (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;
}

标签: cimageimage-processingppm

解决方案


我会把它写成这样的:

#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;
}
  • 正如建议的那样,最好使用 and 的组合,fgets()sscanf()不是fscanf()特别是当我们需要处理不规则线条时。
  • stdin当文件名被省略时,您不必编写特定的代码来读取。只需将文件指针分配fstdin.
  • 建议将函数名称更改为read()其他名称,因为它与现有的系统调用函数冲突read(2)

推荐阅读