CS50 Pset4 filter-more 任务blur()函数输出异常问题排查
BMP图像3x3盒模糊功能输出异常排查
问题背景
- 对应练习:CS50x 2022课程pset4 filter(more难度)板块
- 实现逻辑:遍历图像每个像素,计算其周边3x3邻域内所有有效像素的RGB通道平均值,作为该像素模糊后的新值,实现BMP图像的模糊效果
- 故障表现:代码可正常编译,调试过程未发现显性报错,但输出图像无预期模糊效果,反而垂直重复3次黑白彩色相间的异常图案
- 当前进展:已根据评论建议做过部分代码调整,仍未得到符合预期的输出
相关代码
blur主函数
// Blur image void blur(int height, int width, RGBTRIPLE image[height][width]) { // Array for storing corresponding blur values of the pixels. RGBTRIPLE(*blur)[width] = calloc(height, width * sizeof(RGBTRIPLE)); if (image == NULL) { printf("Not enough memory to store blur pixels.\n"); return; } for (int row = 0; row < height; row++) { for (int col = 0; col < width; col++) { sum3x3(row, col, height, width, image, blur); } } for (int row = 0; row < height; row++) { for (int col = 0; col < width; col++) { image[row][col] = blur[row][col]; } } free(blur); return; }
sum3x3邻域计算子函数
void sum3x3(int row, int col, int height, int width, RGBTRIPLE matrix[row][col], RGBTRIPLE new_matrix[row][col] ) { float counter = 0; float blue = 0; float green = 0; float red = 0; for (int i = -1; i < 2; i++) { for (int j = -1; j < 2; j++) { // skip rows out of range. if ( (i + row) < 0 || (i + row >= height)) continue; // skip columns out of range. if ( (j + col) < 0 || (j + col >= width)) continue; // add to sum. counter ++; blue += matrix[i + row][j + col].rgbtBlue; green += matrix[i + row][j + col].rgbtGreen; red += matrix[i + row][j + col].rgbtRed; } } new_matrix[row][col].rgbtBlue += round(blue/counter); new_matrix[row][col].rgbtGreen += round(green/counter); new_matrix[row][col].rgbtRed += round(red/counter); }
RGBTRIPLE结构体定义
typedef struct { BYTE rgbtBlue; BYTE rgbtGreen; BYTE rgbtRed; } __attribute__((__packed__)) RGBTRIPLE;
问题根因与修复方案
代码共有3处错误,其中第二处是导致输出异常图案的核心原因:
- 空指针判断逻辑写反:
calloc申请的是blur数组的堆内存,判断内存申请是否失败时,错误检查了输入参数image是否为空,完全没有校验blur指针。如果内存不足申请失败,后续对blur的写入操作会直接触发内存访问错误。
修复:将判断条件改为if (blur == NULL)。 - 变长数组形参维度定义错误:
sum3x3函数的二维数组形参写为RGBTRIPLE matrix[row][col]、RGBTRIPLE new_matrix[row][col],这里第二维度误用了当前遍历的列号col,实际应为图像总宽度width,第一维度应为图像总高度height。C语言中访问二维数组时,会根据形参定义的第二维度计算每行的内存步长,维度写错会导致内存偏移计算完全错误,越界读取到非图像区域的垃圾值,最终输出重复的异常图案。
修复:将两个二维数组形参改为RGBTRIPLE matrix[height][width]、RGBTRIPLE new_matrix[height][width]。 - 赋值逻辑冗余:
calloc会将申请的内存全部初始化为0,此处用+=给通道赋值虽然不会出错,但逻辑上属于直接赋值场景,改用=可以避免后续更换内存分配方式(比如用malloc)时,因内存未初始化出现值累加的隐性bug。
修复:将三个通道的+=改为=。
修复后的sum3x3函数核心代码:
void sum3x3(int row, int col, int height, int width, RGBTRIPLE matrix[height][width], RGBTRIPLE new_matrix[height][width] ) { float counter = 0; float blue = 0; float green = 0; float red = 0; for (int i = -1; i < 2; i++) { for (int j = -1; j < 2; j++) { if ( (i + row) < 0 || (i + row >= height)) continue; if ( (j + col) < 0 || (j + col >= width)) continue; counter ++; blue += matrix[i + row][j + col].rgbtBlue; green += matrix[i + row][j + col].rgbtGreen; red += matrix[i + row][j + col].rgbtRed; } } new_matrix[row][col].rgbtBlue = round(blue/counter); new_matrix[row][col].rgbtGreen = round(green/counter); new_matrix[row][col].rgbtRed = round(red/counter); }
内容的提问来源于stack exchange,提问作者nishkant
相关产品推荐
相关产品推荐

