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

C语言读取BMP像素忽略填充报错,求错误原因排查

读取BMP像素时跳过填充的错误分析与修正

问题描述

尝试用C语言读取BMP文件像素并忽略填充,但程序退出码为-1,编译器无具体报错。相关函数代码如下:

void readPixelsBMP(FILE* file, struct Pixel** pArr, int width, int height) {
  int padding = (width%4);
  for (int i = 0; i < width; i++) {
        for (int j = 0; j < height; j++)  {
           unsigned char b,g,r;
            fread(&b, sizeof(unsigned char), 1, file);
            fread(&g, sizeof(unsigned char), 1, file);
            fread(&r, sizeof(unsigned char), 1, file);
            pArr[i][j].b = b;
            pArr[i][j].g = g;
            pArr[i][j].r = r;
            if (j == height - 1) {
              //this line is the problem \/
                fseek(file, sizeof(char) * padding, SEEK_CUR);
            }
        }
    }  
}

期望通过fseek跳过填充但引发错误,现分析错误点并修正:

错误点分析

  • 循环顺序完全颠倒:BMP像素数据按行优先存储,外层循环应该遍历行数(height),内层遍历每行的像素数(width)。你现在外层循环width、内层height,相当于按列读取,不仅逻辑错误,还会导致数组访问越界,触发程序崩溃。
  • Padding计算错误:BMP要求每行字节数必须是4的倍数,每个像素占3字节(BGR顺序),正确的padding计算公式是(4 - (width * 3) % 4) % 4——你直接用width%4,完全没考虑每个像素的3字节,导致计算的填充长度错误。
  • 跳过填充的时机错误:填充是在每一行所有像素读取完成后存在的,应该在内层循环(每行像素)结束后执行fseek,而不是当j == height-1时执行——这个条件判断的是列遍历到最后一行,和行结束毫无关系。
  • 数组索引越界:因为循环顺序颠倒,pArr[i][j]中i是宽度索引、j是高度索引,但二维数组pArr应该是height行width列,直接访问会超出数组边界,导致内存错误。

修正后的代码

void readPixelsBMP(FILE* file, struct Pixel** pArr, int width, int height) {
    // 正确计算每行的填充字节数
    int row_size = width * 3;
    int padding = (4 - row_size % 4) % 4;

    // 外层循环遍历行数(height),内层遍历每行的像素数(width)
    for (int i = 0; i < height; i++) {
        for (int j = 0; j < width; j++) {
            unsigned char b, g, r;
            // 读取单个像素的BGR分量
            fread(&b, sizeof(unsigned char), 1, file);
            fread(&g, sizeof(unsigned char), 1, file);
            fread(&r, sizeof(unsigned char), 1, file);
            // 对应到数组的行和列(i是行,j是列)
            pArr[i][j].b = b;
            pArr[i][j].g = g;
            pArr[i][j].r = r;
        }
        // 每行像素读取完成后,跳过填充字节
        fseek(file, padding, SEEK_CUR);
    }
}

额外说明

  • 确保pArr已经正确分配内存:是一个height个元素的指针数组,每个指针指向width个struct Pixel的内存块。
  • 调用该函数前,文件指针必须已经定位到BMP像素数据的起始位置(即跳过文件头和信息头之后)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 05:51:30