图像的双线性插值放大算法中,目标图像中新创造的象素值,是由源图像位置在它附近的2*2区域4个邻近象素的值通过加权平均计算得出的。双线性内插值算法放大后的图像质量较高,不会出现像素值不连续的的情况。然而次算法具有低通滤波器的性质,使高频分量受损,所以可能会使图像轮廓在一定程度上变得模糊。
图1
X方向的线性插值
对于标准的双线性差值算法,X方向的线性插值:
[通用1]
[通用2]
具体到我们所实现的算法中,我们使Q11、Q12、Q21、Q22为光栅上相邻的四点,即P只能落于这四点其中一点上。Δcol是当前像素离像素所属区域原点的水平距离,比如图2,各种不同的颜色代表一个区域,区域原点为区域左上角的像素。
δ R2 = Color Q22 −Color Q12 ∙Δcol+Color Q12 ∙256 (1)
δ R1 = Color Q21 −Color Q11 ∙Δcol+Color Q11 ∙256 (2)
其中:Δcol=(DestColNumber∙((SrcWidth≪8)/DestWidth))&255, Color(X)表示点X的颜色,具体算法使用的是24位真彩色格式。
Y方向的线性插值
做完X方向的插值后再做Y方向的插值,对于一般情况,有:
[通用3]
而我们的具体算法中,Y方向的线性插值方法如(3)所示。Δrow是当前像素离像素所属区域原点的垂直距离,比如图2,各种不同的颜色代表一个区域,区域原点为区域左上角的像素。
Color P = δ R2 ∙256+ δ R2 −δ R1 ∙Δrow ≫16 (3)
其中:Δrow=(DestRowNumber∙((SrcHeight≪8)/DestHeight))&255,由于前面为了便于计算左移了16位,因此最后需要右移16位保持匹配。
算法描述
类 C 伪码如下:
- for (目标图像第一行的像素++)
- {
- // 源图像上Q12, Q22, Q11, Q21的选取见下一节
- 获取源图像Q12, Q22, Q11, Q21的颜色;
-
- // X 方向的插值
- δ(R2) = (Color(Q22) - Color(Q12)) * δcol+ Color(Q12) * 256;
- δ(R1) = (Color(Q21) - Color(Q11)) * δcol+ Color(Q11) * 256;
-
- // 保存 δ(R1)到一个临时数组,因为下一行的δ(R2)等于这一行的δ(R1)
- temp[i++] = δ(R1);
-
- // Y 方向的插值
- Color(P) = (δ(R2) * 256 + (δ(R2) - δ(R1)) *δrow) >> 16;
-
- 将 P 输出到目标位图中。
- }
-
- for (目标图像第二行到最末行)
- {
- for (行上的像素++)
- {
- // 源图像上Q12, Q22, Q11, Q21的选取见下一节
- 获取源图像Q12, Q22, Q11, Q21的颜色;
-
- // X 方向的插值
- δ(R2) = temp[i++]; // 下一行的δ(R2)等于上一行的δ(R1)
- δ(R1) = (Color(Q21) - Color(Q11)) *δcol+ Color(Q11) * 256;
-
- // 保存 δ(R1)到一个临时数组,因为下一行的δ(R2)等于这一行的δ(R1)
- temp[i++] = δ(R1);
-
- // Y 方向的插值
- Color(P) = (δ(R2) * 256 + (δ(R2) - δ(R1)) * δrow) >> 16;
-
- 将 P 输出到目标位图中。
- }
- }
算法中Q12, Q22, Q11, Q21的选取
我们以放大两倍为例,说明选取Q12, Q22, Q11, Q21的过程。源图像3*3区域放大为目标区域6*6区域。设以下为目标图像:
A
|
A
|
B
|
B
|
|
|
A
|
A
|
B
|
B
|
|
|
|
|
C
|
C
|
|
|
|
|
C
|
C
|
|
|
|
|
|
|
D
|
D
|
|
|
|
|
D
|
D
|
图2
目标图像A像素区域对应的Q21,Q22,Q11,Q12,以红色区域为原点向右下方扩展的2*2区域。
图3
目标图像B像素区域对应的Q21,Q22,Q11,Q12,以蓝色区域为原点向右下方扩展的2*2区域。
图4
目标图像C像素区域对应的Q21,Q22,Q11,Q12,以绿色区域为原点向右下方扩展的2*2区域。
图5
目标图像D像素区域对应的Q21,Q22,Q11,Q12,目标图像处于最后两行的边界情况,将Q21,Q22,Q11,Q12这四个点的值设为一样。
图6
程序流程图
流程图右边虚线框中为相关过程的注解。