自定义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
相关产品推荐
相关产品推荐

