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

C语言实现PGM图像模糊时出现部分图像翻转右侧异常问题

PGM图像模糊功能异常排查

问题现象

  • 开发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函数的核心流程是对的,仅存在一个不影响显示的冗余写法问题。
异常本质是行内存越界写入导致的行卷绕错位,核心原因出在模糊功能的输出图像初始化环节:

  1. 创建模糊输出图像final时宽高参数传反:如果你的create_image函数参数顺序为(width, height),你错传为(blurred->height, blurred->width),会导致final每行分配的内存长度等于原始图像高度,而非实际需要的原始图像宽度。
  2. 当原始图像宽度大于高度时,列遍历y超过final每行的实际分配长度后,像素值会被写入下一行的起始内存位置。最终保存时PGM头声明的宽度是原始宽度,图像查看器每行读取对应宽度的字节时,就会把下一行开头的像素拼接到本行末尾,表现为“部分内容翻转到右侧”,和你描述的现象完全一致。
  3. 额外逻辑隐患:如果blurred没有存储原始图像的独立副本,和输入原图像、输出final共享内存,计算邻域时会读取到已经被模糊修改过的像素,导致模糊效果不均匀、出现拖影。
  4. save函数的冗余问题:二进制P5格式PGM不需要在像素末尾追加换行,最后一行fprintf(writeFile, "\n");会多写入1字节,不符合格式规范,不过大部分查看器会忽略该字节,不会造成显示异常。

修复方案

  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);
    
  2. 保证模糊计算读取原始像素
    模糊计算前必须将原始输入图像拷贝到独立的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);
    
  3. 清理save函数冗余代码
    删除像素写入循环结束后的fprintf(writeFile, "\n");语句,避免写入多余字节。
  4. 可选类型修正
    将图像像素存储类型改为unsigned char,累加和sum保持int类型,避免有符号字符符号扩展、累加值溢出导致的亮度异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 07:09:16