чтение ppm-файла с fread в C - PullRequest
       24

чтение ppm-файла с fread в C

0 голосов
/ 23 марта 2020

Я читаю ppm файл с fread и получаю то, чего нет в файле. Мой код выглядит следующим образом:

typedef struct {
        int red;
        int green;
        int blue;
} Pixel;

typedef struct {
        int width;
        int height;
        int max_value;
        Pixel *p;
} Image;


Image* read_image(char *filename)
{
    char buff[16];
    Image *img;
    FILE *fp;
    int c, rgb_comp_color;
    //open PPM file for reading
    fp = fopen(filename, "rb");
    if (!fp) {
        fprintf(stderr, "Unable to open file '%s'\n", filename);
        exit(1);
    }

    //read image format
    if (!fgets(buff, sizeof(buff), fp)) {
        perror(filename);
        exit(1);
    }

    //check the image format
    if (buff[0] != 'P' || buff[1] != '3') {
        fprintf(stderr, "Invalid image format (must be 'P3')\n");
        exit(1);
    }

    //alloc memory form image
    img = (Image *)malloc(sizeof(Image));
    if (!img) {
        fprintf(stderr, "Unable to allocate memory\n");
        exit(1);
    }

    //read image size information
    if (fscanf(fp, "%d %d", &img->width, &img->height) != 2) {
        fprintf(stderr, "Invalid image size (error loading '%s')\n", filename);
        exit(1);
    }

    //read rgb component
    if (fscanf(fp, "%d", &img->max_value) != 1) {
        fprintf(stderr, "Invalid rgb component (error loading '%s')\n", filename);
        exit(1);
    }


    while (fgetc(fp) != '\n') ;
    //memory allocation for pixel data
    img->p = (Pixel*)malloc(img->width * img->height * sizeof(Pixel));

    if (!img) {
        fprintf(stderr, "Unable to allocate memory\n");
        exit(1);
    }

    //read pixel data from file
    if (fread(img->p, 3 * img->width, img->height, fp) != img->height) {
        fprintf(stderr, "Error loading image '%s'\n", filename);
        exit(1);
    }

    fclose(fp);
    return img;
}

void print_image(Image *img){
        printf("P3\n");
        printf("%d %d\n", img->width, img->height);
        printf("%d\n", img->max_value);

        for(int i=0; i<img->width*img->height; i++)
           printf("%d %d %d  ", img->p[i].red, img->p[i].green, img->p[i].blue);
        printf("\n");
}


Когда я пытаюсь прочитать этот файл:

P3
 7
 7
 15

0    0    0     0    0    0     0    0    0     0    0    0     0    0    0     0    0    0     0    0    0     
0    3    3     3    3    0     0    7    7     7    7    0     0    11    11       11    11    0       0    15    15       
0    3    0     0    0    0     0    7    0     0    0    0     0    11    0        0    0    0     0    15    0        
0    3    3     3    0    0     0    7    7     7    0    0     0    11    11       11    0    0        0    15    15       
0    3    0     0    0    0     0    7    0     0    0    0     0    11    0        0    0    0     0    15    0        
0    3    0     0    0    0     0    7    7     7    7    0     0    11    11       11    11    0       0    15    0        
0    0    0     0    0    0     0    0    0     0    0    0     0    0    0     0    0    0     0    0    0     

Результат моего read_image такой (я печатаю результат с помощью функции print_image):

P3
7 7
15
538980362 540024864 807411744  538976288 538980361 540024864  807411744 538976288 538980361  540024864 807411744 538976288  538980361 540024864 807411744  538976288 538980361 540024864  807411744 538976288 538980361  540024864 807411744 538976288  538980361 540024864 807411744  538976288 540019209 857743392  538976288 538976307 540215584  857743392 538976288 538976304  3148064 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  

Я неправильно использую фред или какую часть процесса я пропускаю? Заранее спасибо.

1 Ответ

0 голосов
/ 23 марта 2020

IIR C, в файле .ppm геометрия / формат могут быть в несколько строк [или в одну строку].

Таким образом, выполнение fgets для чтения не будет работать. Вместо этого используйте fscanf для всего формата.

Кроме того, IIR C, фактические данные упакованы в двоичном виде, поэтому ваш тестовый файл на самом деле не является PPM [если он действительно содержит текст ascii для значений пикселей в качестве ваших данных блок, кажется, показывает].

Реальный формат данных не имеет встроенных символов новой строки, поэтому вы не можете сделать fgetc, просто выполните fread.

См. мой ответ: Как сделать черно-белое изображение ppm-файла в C?

...