使用 C 将 ppm 文件从 P3 转换为 P6

标签 c pointers segmentation-fault ppm

我正在尝试编写一个程序,使用 C 将 p3 PPM 文件转换为 P6。但我遇到了两个问题。 1,我的代码中出现段错误。和 2,标题没有被正确读入转换后的 p6 文件。这是我的头文件。

#ifndef PPM_UTILS
#define PPM_UTILS

#include "stdio.h"
#include "stdlib.h"
#include "string.h"

// First meaningful line of the PPM file
typedef struct header {
    char MAGIC_NUMBER[3];
    unsigned int HEIGHT, WIDTH, MAX_COLOR;
} header_t;

// Represents an RGB pixel with integer values between 0-255
typedef struct pixel {
    unsigned int R, G, B;
} pixel_t;

// PPM Image representation
typedef struct image {
    header_t header;
    pixel_t* pixels;
} image_t;

header_t read_header(FILE* image_file);
image_t* read_ppm(FILE* image_file);
image_t* read_p6(FILE* image_file, header_t header);
image_t* read_p3(FILE* image_file, header_t header);

void write_header(FILE* out_file, header_t header);
void write_p6(FILE* out_file, image_t* image);
void write_p3(FILE* out_file, image_t* image);

#endif

我将代码的主要部分拆分为两个文件,并在编译器中合并

#include <stdio.h>
#include "ppm_utils.h"

header_t read_header(FILE* image_file)
{

    header_t header;

    fscanf(image_file, "%c %d %d %d",header.MAGIC_NUMBER, &header.WIDTH, &header.HEIGHT, &header.MAX_COLOR);
    return header;
}

void write_header(FILE* out_file, header_t header)
{

    fprintf(out_file, "%c %d %d %d", *header.MAGIC_NUMBER,header.HEIGHT,header.WIDTH,header.MAX_COLOR);
}

image_t* read_ppm(FILE* image_file)
{

    header_t header = read_header(image_file);

    image_t* image = NULL;
    if (strcmp("P3", header.MAGIC_NUMBER) == 0)
    {
        image = read_p3(image_file, header);
    }
    else if (strcmp("P6", header.MAGIC_NUMBER) == 0)
    {
        image = read_p6(image_file, header);
    }
    return image;
}

image_t* read_p6(FILE* image_file, header_t header)
{

    int size;
    size = header.HEIGHT * header.WIDTH;
    image_t* image = (image_t*) malloc (sizeof(image_t));
    image -> header = header;
    image -> pixels = (pixel_t*) malloc (sizeof(pixel_t)* size);
    char r,g,b;
    r = 0;
    g = 0;
    b = 0;
    int i;
    for (i=0;i<size;i++){
        fscanf(image_file, "%c%c%c", &r, &g, &b);
        image -> pixels -> R = (int) r;
        image -> pixels -> G = (int) g;
        image -> pixels -> B = (int) b;
    }
    return image;
}
image_t* read_p3(FILE* image_file, header_t header)
{
    int size;
    size = header.HEIGHT * header.WIDTH;
    image_t* image = (image_t*) malloc (sizeof(image_t));
    image -> header = header;
    image -> pixels = (pixel_t*) malloc (sizeof(pixel_t)* size);
    int r,g,b;
    r = 0;
    g = 0;
    b = 0;
    int i;
    for (i=0;i<size;i++){
        fscanf(image_file, "%d %d %d ", &r, &g, &b);
        image -> pixels -> R = (int) r;
        image -> pixels -> G = (int) g;
        image -> pixels -> B = (int) b;
    }
    return image;

}

void write_p6(FILE* out_file, image_t* image)
{
    header_t header = image -> header;
    header.MAGIC_NUMBER[1]=6;
    write_header(out_file, header);
    int size = header.HEIGHT * header.WIDTH;
    int i;
    for (i=0;i<size;i++){
        fprintf(out_file,"%c%c%c", (char) image->pixels->R, (char) image->pixels->G, (char) image->pixels->B);
    }

}
void write_p3(FILE* out_file, image_t* image)
{
    header_t header = image -> header;
    header.MAGIC_NUMBER[1]=3;
    write_header(out_file, header);
    int size = header.HEIGHT * header.WIDTH;
    int i;
    for (i=0;i<size;i++){
        fprintf(out_file,"%d %d %d ",image->pixels->R,image->pixels->G,image->pixels->B);

    }

}

..

#include <stdio.h>
#include "ppm_utils.h"

int main(int argc, char *argv[])
{

    if (argc != 3)
    {
        printf("The program needs two arguments");
        return 1;
    }

    FILE *fr;
    fr = fopen(argv[1],"r");

    if (fr == NULL)
    {
        printf("The opening failed");
    }

    FILE *fw;
    fw = fopen(argv[2],"w");

    if (fw == NULL)
    {
        printf("The opening failed");
    }
    image_t* image = read_ppm(fr);
    write_p6(fw,image);
    free(image);
    free(image->pixels);
    fclose(fr);
    fclose(fw);
    return 0;
}

你们有什么解决办法吗?

最佳答案

读取头部时需要指定要读取的魔数(Magic Number)的字符数:

fscanf(image_file, "%2c %d %d %d",header.MAGIC_NUMBER, &header.WIDTH, &header.HEIGHT, &header.MAX_COLOR);

要与 strcmp()一起使用,数组中的最后一个字节必须设置为 0:

header.MAGIC_NUMBER[2] = 0;

写header的时候需要写成字符串:

fprintf(out_file, "%s %d %d %d", header.MAGIC_NUMBER,header.HEIGHT,header.WIDTH,header.MAX_COLOR);

关于使用 C 将 ppm 文件从 P3 转换为 P6,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48511809/

相关文章:

c - 未存储在变量中的数字类型

c - 段错误: double free or corruption (fast top)

c - 在 char 数组中搜索 char

c - 动态增加/减少数组大小

c - 在 C 中使用 "" block 内的整数

c - OpenMP 中有默认范围分隔符吗?

函数末尾的 C++ 段错误。引用线 = 右大括号

c++ - 通过删除基类来破坏派生类

c - 指针困惑

c++ - 为什么是这个结果?