C语言实现灰度滤镜:能否批量赋值二维数组中RGB结构体成员?
灰度滤镜实现疑问:结构体成员批量赋值问题
我想要实现一个灰度滤镜,需将每个像素RGB三个分量的平均值赋值给这三个分量。因处理的是位图图像,我采用二维数组存储每个像素(每个像素为RGBTRIPLE结构体)。结构体定义如下(其中BYTE为uint8_t):
typedef struct { BYTE rgbtBlue; BYTE rgbtGreen; BYTE rgbtRed; } __attribute__((__packed__)) RGBTRIPLE;
当前我通过分别为结构体的每个成员赋值实现功能,代码如下:
void grayscale(int height, int width, RGBTRIPLE image[height][width]) { for (int i = 0; i < height; i++) { for (int j = 0 ; j < width; j++) { image[i][j].rgbtBlue = (image[i][j].rgbtBlue + image[i][j].rgbtRed + image[i][j].rgbtGreen)/3; image[i][j].rgbtGreen = (image[i][j].rgbtBlue + image[i][j].rgbtRed + image[i][j].rgbtGreen)/3; image[i][j].rgbtRed = (image[i][j].rgbtBlue + image[i][j].rgbtRed + image[i][j].rgbtGreen)/3; } } return; }
现询问:是否必须逐个为结构体成员赋值,还是可以一次性将该平均值赋值给结构体的所有成员?
回答
先指出你当前代码的问题:给rgbtBlue赋值后,后续计算rgbtGreen和rgbtRed时用的是修改后的rgbtBlue值,并非原始三个分量的总和,这会导致最终结果错误。正确做法是先计算好原始分量的平均值,再统一赋值。
回到你的核心问题:不需要逐个赋值,可以一次性给结构体所有成员赋值,有两种靠谱的实现方式:
1. 直接构造结构体赋值(推荐)
先算出平均值,再构造一个三个成员均为该值的RGBTRIPLE实例,直接赋值给目标像素,可读性和安全性都很高:
void grayscale(int height, int width, RGBTRIPLE image[height][width]) { for (int i = 0; i < height; i++) { for (int j = 0 ; j < width; j++) { BYTE avg = (image[i][j].rgbtBlue + image[i][j].rgbtRed + image[i][j].rgbtGreen) / 3; image[i][j] = (RGBTRIPLE){.rgbtBlue = avg, .rgbtGreen = avg, .rgbtRed = avg}; } } return; }
2. 利用内存操作(依赖结构体布局)
因为你的结构体加了__attribute__((__packed__))属性,三个BYTE成员连续存储、无填充字节,所以可以用memset直接把整个结构体的内存区域设为平均值:
#include <string.h> void grayscale(int height, int width, RGBTRIPLE image[height][width]) { for (int i = 0; i < height; i++) { for (int j = 0 ; j < width; j++) { BYTE avg = (image[i][j].rgbtBlue + image[i][j].rgbtRed + image[i][j].rgbtGreen) / 3; memset(&image[i][j], avg, sizeof(RGBTRIPLE)); } } return; }
这种方式的局限性很强——如果后续去掉packed属性或者修改结构体成员,内存布局改变后就会失效,因此更推荐第一种方式。
内容的提问来源于stack exchange,提问作者oomertaa
相关产品推荐
相关产品推荐

