You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义HS8图像加载器读取数据错误排查求助

HS8格式图像读取程序的错误排查与修复

核心问题分析与修复步骤

1. 文件打开模式错误

原因:使用文本模式"r"打开文件时,系统会自动转换换行符(如\r\n转为\n),导致二进制像素数据的位置偏移,读取到错误内容甚至触发内存访问异常。
修复:改用二进制模式"rb"打开文件:

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

2. 文件头读取后未跳过残留空白字符

原因:fscanf读取完height后,文件指针停留在height后的空白字符(换行、空格等)上,后续fread会将这些空白字符当作像素数据的一部分,直接导致RGB值异常。
修复:读取头信息后,跳过所有空白字符直至二进制数据起始位置:

// 在读取头信息后添加这段代码
int c;
while ((c = fgetc(f)) != EOF && isspace(c)) {
    // 跳过所有空白字符
}
if (c != EOF) {
    // 将读取到的第一个非空白字符放回文件流
    ungetc(c, f);
}

注意:需包含<ctype.h>头文件以使用isspace函数。

3. 文件类型标识符数组大小不足

原因:定义char fileType[3],但"HS8"包含字符串终止符'\0'共4个字符,会导致数组越界,strcmp比较时因无正确终止符出现不可靠结果,甚至引发内存错误。
修复:将数组大小改为4:

char fileType[4];

4. main函数中未定义out_img

原因:代码直接使用未初始化的out_img,属于野指针,调用save_image时会触发Segmentation fault。
修复:初始化out_img(以下示例为复制输入图像的逻辑):

// 加载输入图像后添加
struct Image *out_img = malloc(sizeof(struct Image));
if (out_img == NULL) {
    fprintf(stderr, "Memory allocation failed.\n");
    free_image(in_img);
    return 1;
}
out_img->width = in_img->width;
out_img->height = in_img->height;
out_img->pixels = malloc(sizeof(struct Pixel) * in_img->width * in_img->height);
if (out_img->pixels == NULL) {
    fprintf(stderr, "Memory allocation failed.\n");
    free_image(in_img);
    free(out_img);
    return 1;
}
memcpy(out_img->pixels, in_img->pixels, sizeof(struct Pixel) * in_img->width * in_img->height);

注意:需包含<string.h>头文件以使用memcpy函数。

修复后的完整示例代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdint.h>

/* 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(img->pixels);
    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)
{
    FILE *f = fopen(filename, "rb");
    if (f == NULL)
    {
        fprintf(stderr, "File %s could not be opened.\n", filename);
        return NULL;
    }

    char fileType[4];
    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;
    }

    // 跳过文件头后的所有空白字符
    int c;
    while ((c = fgetc(f)) != EOF && isspace(c)) {}
    if (c != EOF) {
        ungetc(c, f);
    }

    struct Image *img = malloc(sizeof(struct Image));
    if (img == NULL)
    {
        fprintf(stderr, "Memory allocation failed.\n");
        fclose(f);
        return NULL;
    }

    img->width = width;
    img->height = height;

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

    // 一次性读取所有像素数据,提升效率
    size_t total_pixels = width * height;
    size_t bytes_read = fread(img->pixels, sizeof(struct Pixel), total_pixels, f);
    if (bytes_read != total_pixels)
    {
        fprintf(stderr, "Failed to read all pixel data. Read %zu of %zu pixels.\n", bytes_read, total_pixels);
        fclose(f);
        free(img->pixels);
        free(img);
        return NULL;
    }

    fclose(f);
    return img;
}

// 示例save_image实现
int save_image(struct Image *img, const char *filename)
{
    FILE *f = fopen(filename, "wb");
    if (f == NULL) {
        fprintf(stderr, "File %s could not be opened for writing.\n", filename);
        return 0;
    }

    fprintf(f, "HS8\n%d %d\n", img->width, img->height);
    size_t bytes_written = fwrite(img->pixels, sizeof(struct Pixel), img->width * img->height, f);
    if (bytes_written != img->width * img->height) {
        fprintf(stderr, "Failed to write all pixel data.\n");
        fclose(f);
        return 0;
    }

    fclose(f);
    return 1;
}

int main(int argc, char *argv[])
{
    if (argc != 3)
    {
        fprintf(stderr, "Usage: process INPUTFILE OUTPUTFILE\n");
        return 1;
    }

    struct Image *in_img = load_image(argv[1]);
    if (in_img == NULL)
    {
        return 1;
    }

    // 创建输出图像(复制输入图像)
    struct Image *out_img = malloc(sizeof(struct Image));
    if (out_img == NULL) {
        fprintf(stderr, "Memory allocation failed.\n");
        free_image(in_img);
        return 1;
    }
    out_img->width = in_img->width;
    out_img->height = in_img->height;
    out_img->pixels = malloc(sizeof(struct Pixel) * in_img->width * in_img->height);
    if (out_img->pixels == NULL) {
        fprintf(stderr, "Memory allocation failed.\n");
        free_image(in_img);
        free(out_img);
        return 1;
    }
    memcpy(out_img->pixels, in_img->pixels, sizeof(struct Pixel) * in_img->width * in_img->height);

    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;
}

内容的提问来源于stack exchange,提问作者Ajaz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 00:27:17