此函數實作三種經典 3×3 卷積核影像處理效果:模糊、銳化、浮雕。採用鄰域像素加權運算,支援自訂除數 (Div) 與效果選擇 (xg)。
void S_Filter(Graphics::TBitmap *Source, Graphics::TBitmap *NewPic, int Div, int xg);
// xg: 0=模糊, 1=銳化, 其他=浮雕
void S_Filter(Graphics::TBitmap *Source, Graphics::TBitmap *NewPic, int Div, int xg) {
// 0:模糊 1:銳化 3:浮雕
int flt[9];
switch (xg) {
case 0: { // 模糊核
flt[0]=5; flt[1]=5; flt[2]=5;
flt[3]=5; flt[4]=60; flt[5]=5;
flt[6]=5; flt[7]=5; flt[8]=5;
}; break;
case 1: { // 銳化核
flt[0]=0; flt[1]=-5; flt[2]=0;
flt[3]=-5; flt[4]=30; flt[5]=-5;
flt[6]=0; flt[7]=-5; flt[8]=0;
}; break;
default: { // 浮雕核
flt[0]=-15; flt[1]=-15; flt[2]=0;
flt[3]=-15; flt[4]=15; flt[5]=15;
flt[6]=0; flt[7]=15; flt[8]=0;
};
}
int XX[3];
BYTE *ptr, *ptru, *ptrd, *ptr1;
NewPic->Assign(Source); // 複製來源影像
for (int y = 1; y < NewPic->Height - 1; y++) {
ptr = (BYTE *)NewPic->ScanLine[y]; // 目標掃描列
ptr1 = (BYTE *)Source->ScanLine[y]; // 來源當前列
ptru = (BYTE *)Source->ScanLine[y - 1]; // 來源上一列
ptrd = (BYTE *)Source->ScanLine[y + 1]; // 來源下一列
for (int x = 3; x < (Source->Width - 1) * 3; x += 3) {
XX[0] = XX[1] = XX[2] = 0;
// 當前列卷積運算 (flt[3]~flt[5] 對應索引 3,4,5)
for (int i = -1; i <= 1; i++)
for (int j = 0; j < 3; j++)
XX[j] += ptr1[x + 3 * i + j] * flt[4 + i];
// 上一列卷積運算 (flt[0]~flt[2] 對應索引 0,1,2)
for (int i = -1; i <= 1; i++)
for (int j = 0; j < 3; j++)
XX[j] += ptru[x + 3 * i + j] * flt[1 + i];
// 下一列卷積運算 (flt[6]~flt[8] 對應索引 6,7,8)
for (int i = -1; i <= 1; i++)
for (int j = 0; j < 3; j++)
XX[j] += ptrd[x + 3 * i + j] * flt[7 + i];
// 歸一化、飽和處理、寫入目標
for (int i = 0; i < 3; i++) {
XX[i] = XX[i] / Div;
XX[i] = max(XX[i], 0);
XX[i] = min(XX[i], 255);
ptr[x + i] = (BYTE)XX[i];
}
}
}
}
flt 陣列按行優先儲存 3×3 核,索引 0~8 對應 (-1,-1) 到 (1,1) 相對位置。XX[3] 分別累積 R、G、B 三通道加權和。y=1..Height-2、x=3..(Width-2)*3,忽略影像邊緣 1 像素,避免越界。Div,再限制在 0~255 範圍。Div=100,銳化 Div=10,浮雕 Div=1(視核數值調整)。// 模糊效果
S_Filter(SourceBitmap, DestBitmap, 100, 0);
// 銳化效果
S_Filter(SourceBitmap, DestBitmap, 10, 1);
// 浮雕效果
S_Filter(SourceBitmap, DestBitmap, 1, 2);