C语言实现PGM图像模糊时出现部分图像翻转右侧异常问题
PGM图像模糊功能异常排查
问题现象
- 开发PGM图像处理与转换项目过程中,其余功能均运行正常,新增均值模糊功能后出现显示异常
- 异常表现:图像部分内容错位/翻转到右侧,暂时无法确定问题出在模糊处理逻辑还是图像保存流程
- 参考对比图:
- 原始图像:

- 模糊后异常图像:

- 原始图像:
问题相关代码
模糊处理逻辑
for (x =0; x < blurred->height ; x++) { for (y =0; y < blurred->width ; y++) { counter = 0; sum = 0; average=0; // check lower left pixel if ((x + 1) < blurred->height && (y - 1)>= 0){ sum += blurred->data[x+1][y-1]; counter++; } // check right pixel if ((y + 1) < blurred->width ){ sum += blurred->data[x][y+1]; counter++; } // check lower right pixel if ((x + 1) < blurred->height && (y + 1) < blurred->width){ sum += blurred->data[x+1][y+1]; counter++; } // check lower pixel if ((x + 1) < blurred->height ){ sum += blurred->data[x+1][y]; counter++; } // check left pixel if ((y - 1) >= 0){ sum += blurred->data[x][y-1]; counter++; } // check upper pixel if ((x - 1) >= 0){ sum += blurred->data[x-1][y]; counter++; } // check upper left pixel if ((x - 1) >= 0 && (y - 1) >= 0){ sum += blurred->data[x-1][y-1]; counter++; } // check upper right pixel if ((x - 1) >= 0 && (y + 1) < blurred->width ){ sum += blurred->data[x-1][y+1]; counter++; } // index pixel sum += blurred->data[x][y]; counter++; average = sum / counter; final->data[x][y] = average; } }
PGM图像保存逻辑
void save(image * pgm, const char * filename) { int i, j, rows, cols; FILE * writeFile = fopen(filename, "wb"); rows = pgm->height; cols = pgm->width; fprintf(writeFile, "P5\n"); fprintf(writeFile, "%d %d\n", cols, rows); fprintf(writeFile, "255\n"); fprintf(writeFile, "\n"); for (i = 0; i < rows; i++){ for (j = 0; j < cols; j++){ putc(pgm->data[i][j], writeFile); } } fprintf(writeFile, "\n"); fclose(writeFile); }
根因定位
保存逻辑可以直接排除:其余功能正常运行已经证明save函数的核心流程是对的,仅存在一个不影响显示的冗余写法问题。
异常本质是行内存越界写入导致的行卷绕错位,核心原因出在模糊功能的输出图像初始化环节:
- 创建模糊输出图像
final时宽高参数传反:如果你的create_image函数参数顺序为(width, height),你错传为(blurred->height, blurred->width),会导致final每行分配的内存长度等于原始图像高度,而非实际需要的原始图像宽度。 - 当原始图像宽度大于高度时,列遍历y超过
final每行的实际分配长度后,像素值会被写入下一行的起始内存位置。最终保存时PGM头声明的宽度是原始宽度,图像查看器每行读取对应宽度的字节时,就会把下一行开头的像素拼接到本行末尾,表现为“部分内容翻转到右侧”,和你描述的现象完全一致。 - 额外逻辑隐患:如果
blurred没有存储原始图像的独立副本,和输入原图像、输出final共享内存,计算邻域时会读取到已经被模糊修改过的像素,导致模糊效果不均匀、出现拖影。 - save函数的冗余问题:二进制P5格式PGM不需要在像素末尾追加换行,最后一行
fprintf(writeFile, "\n");会多写入1字节,不符合格式规范,不过大部分查看器会忽略该字节,不会造成显示异常。
修复方案
- 修正输出图像内存分配
创建final时严格匹配输入图像的宽高,参数顺序和create_image函数定义保持一致:// 请根据你实际的create_image函数参数顺序调整,保证final的宽高和输入完全一致 image* final = create_image(blurred->width, blurred->height); // 可加打印校验,确认宽高值匹配 // printf("blurred: w=%d,h=%d; final: w=%d,h=%d\n", blurred->width, blurred->height, final->width, final->height); - 保证模糊计算读取原始像素
模糊计算前必须将原始输入图像拷贝到独立的blurred缓冲区,禁止输入、输出缓冲区共享内存,避免污染原始像素。可参考实现拷贝函数:image* copy_image(image* src) { image* dst = create_image(src->width, src->height); for (int i = 0; i < src->height; i++) { memcpy(dst->data[i], src->data[i], src->width); } return dst; } // 模糊函数开头用原始输入生成副本 image* blurred = copy_image(original_input); - 清理save函数冗余代码
删除像素写入循环结束后的fprintf(writeFile, "\n");语句,避免写入多余字节。 - 可选类型修正
将图像像素存储类型改为unsigned char,累加和sum保持int类型,避免有符号字符符号扩展、累加值溢出导致的亮度异常。
内容的提问来源于stack exchange,提问作者Anonymous
相关产品推荐
相关产品推荐

