Paint提供了变焦特效是个不错玩意,弄出来了很炫的效果,但是看久了比较头晕,看了一下代码,算法很简单,就是将原始像素和给定景深处像素值(和变焦参数有关系)相加,然后结合透明度重新合成新的像素点。由于存在一个点被周围2个点的平均了,因此使图像模糊,而考虑了深度,新生成的像素点都呈现向内部汇聚的效果。
protected unsafe override void OnRender(Rectangle[] rois, int startIndex, int length)
{
Surface dst = DstArgs.Surface;
Surface src = SrcArgs.Surface;
long w = dst.Width;
long h = dst.Height;
long fox = (long)(dst.Width * this.offset.First * 32768.0);
long foy = (long)(dst.Height * this.offset.Second * 32768.0);
long fcx = fox + (w << 15);
long fcy = foy + (h << 15);
long fz = this.amount;
const int n = 64;
for (int r = startIndex; r < startIndex + length; ++r)
{
Rectangle rect = rois[r];
for (int y = rect.Top; y < rect.Bottom; ++y)
{
ColorBgra *dstPtr = dst.GetPointAddressUnchecked(rect.Left, y);
ColorBgra *srcPtr = src.GetPointAddressUnchecked(rect.Left, y);
for (int x = rect.Left; x < rect.Right; ++x)
{
long fx = (x << 16) – fcx;
long fy = (y << 16) – fcy;
int sr = 0;
int sg = 0;
int sb = 0;
int sa = 0;
int sc = 0;
sr += srcPtr->R * srcPtr->A;
sg += srcPtr->G * srcPtr->A;
sb += srcPtr->B * srcPtr->A;
sa += srcPtr->A;
++sc;
for (int i = 0; i < n; ++i)
{
fx -= ((fx >> 4) * fz) >> 10;
fy -= ((fy >> 4) * fz) >> 10;
int u = (int)(fx + fcx + 32768 >> 16);
int v = (int)(fy + fcy + 32768 >> 16);
if (src.IsVisible(u, v))
{
ColorBgra* srcPtr2 = src.GetPointAddressUnchecked(u, v);
sr += srcPtr2->R * srcPtr2->A;
sg += srcPtr2->G * srcPtr2->A;
sb += srcPtr2->B * srcPtr2->A;
sa += srcPtr2->A;
++sc;
}
}
if (sa != 0)
{
*dstPtr = ColorBgra.FromBgra(
Utility.ClampToByte(sb / sa),
Utility.ClampToByte(sg / sa),
Utility.ClampToByte(sr / sa),
Utility.ClampToByte(sa / sc));
}
else
{
dstPtr->Bgra = 0;
}
++srcPtr;
++dstPtr;
}
}
}
}