在自定义 HS8 图像加载器中读取图像数据时出错 (C)

问题描述 投票:0回答:1

我正在开发一个 C 程序来处理自定义 HS8 格式的图像。在初始基于文本的调试步骤之后,我的

load_image
函数似乎无法正确读取二进制像素数据。我遇到了
Segmentation fault (core dumped)
警告,并且像素的 RGB 值完全改变了。

(简化的.hs8文件格式):

HS8 图像具有 ASCII 文本标题:

HS8
width height

地点:

  • HS8 — 表示 HS8 格式的固定代码
  • 宽度 — 整数列数
  • 高度 — 整数行数

标题中的字段由一个或多个空格(空格、制表符、回车符或 换行符)字符。高度字段后跟一个空白字符。 图像数据位于标题后面。每个像素都存储为三个无符号 8 位二进制值 数据(不是文本)。像素从左到右存储在第一行中,然后从左到右存储在第二行中 行,依此类推,直到图像末尾。

/* The RGB values of a pixel. */
struct Pixel
{
    uint8_t red;
    uint8_t green;
    uint8_t blue;
};

/* An image loaded from a file. */
struct Image
{
    int width;
    int height;
    struct Pixel *pixels;
};

/* Free a struct Image */
void free_image(struct Image *img)
{
    /* Free the pixel data */
    free(img->pixels);

    /* Free the image structure */
    free(img);
}

/* Opens and reads an image file, returning a pointer to a new struct Image.
 * On error, prints an error message and returns NULL. */
struct Image *load_image(const char *filename)
{
    /* Open the file for reading */
    FILE *f = fopen(filename, "r");
    if (f == NULL)
    {
        fprintf(stderr, "File %s could not be opened.\n", filename);
        return NULL;
    }

    /* Read the header */
    char fileType[3];
    int width, height;
    if (fscanf(f, "%3s %d %d", fileType, &width, &height) != 3 || strcmp(fileType, "HS8") != 0)
    {
        fprintf(stderr, "Invalid header in file %s.\n", filename);
        fclose(f);
        return NULL;
    }

    /* Allocate memory for the image structure */
    struct Image *img = malloc(sizeof(struct Image));
    if (img == NULL)
    {
        fprintf(stderr, "Memory allocation failed.\n");
        fclose(f);
        return NULL;
    }

    /* Set image width and height */
    img->width = width;
    img->height = height;

    /* Allocate memory for pixel data */
    img->pixels = malloc(sizeof(struct Pixel) * width * height);
    if (img->pixels == NULL)
    {
        fprintf(stderr, "Memory allocation failed.\n");
        fclose(f);
        free(img);
        return NULL;
    }

    /* Read pixel data */
    size_t pixels_read = 0;
    for (int i = 0; i < img->height; i++)
    {
        for (int j = 0; j < img->width; j++)
        {
            size_t bytes_read = fread(&(img->pixels[pixels_read]), sizeof(struct Pixel), 1, f);
            if (bytes_read != 1)
            {
                fprintf(stderr, "Failed to read pixel data.\n");
                fclose(f);
                free(img->pixels);
                free(img);
                return NULL;
            }
            pixels_read++;
        }
    }
    /* Close the file */
    fclose(f);

    return img;
}

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

    /* Check command-line arguments */
    if (argc != 3)
    {
        fprintf(stderr, "Usage: process INPUTFILE OUTPUTFILE\n");
        return 1;
    }

    /* Load the input image */
    struct Image *in_img = load_image(argv[1]);
    if (in_img == NULL)
    {
        return 1;
    }

    /* Save the output image */
    if (!save_image(out_img, argv[2]))
    {
        fprintf(stderr, "Saving image to %s failed.\n", argv[2]);
        free_image(in_img);
        free_image(out_img);
        return 1;
    }

    free_image(in_img);
    free_image(out_img);
    return 0;
}

我考虑/尝试过的事情:

  • 文件位置:我通过调整读取计数来计算文本调试期间消耗的字节数。

谁能帮我找出为什么我无法正确读取图像数据?我正在使用 ubuntu 22.04.3 lts 和 x86 intel 处理器

c file io binary ppm
1个回答
0
投票

如果需要读取二进制数据(如您所描述的),则需要以二进制模式打开文件:

FILE *f = fopen(filename, "rb");

如果您想按照 StackOverflow 的要求提供“最小、完整、可验证的解决方案”,您需要提供有效 HS8 文件及其规范的链接。


如果您依赖于

Pixel struct
的大小,则需要检查并打印其大小,并检查它是否填充为 32 位。


您似乎没有阅读标题后面的空白字符。

© www.soinside.com 2019 - 2024. All rights reserved.