public static void intBicubic32(BmpProc32 dst, BmpProc32 src,
                                int dstX, int dstY, double srcX, double srcY)
        {
            int xi = (int)Math.Floor(srcX);
            int yi = (int)Math.Floor(srcY);

            double rr, gg, bb, aa;
            double dx, dy, wx, wy;

            rr = gg = bb = aa = 0;
            for (int iy = yi - 1; iy < yi + 3; iy++)
                for (int ix = xi - 1; ix < xi + 3; ix++)
                {
                    dx = Math.Abs(srcX - ix);
                    dy = Math.Abs(srcY - iy);

                    if (dx < 1) wx = (dx - 1d) * (dx * dx - dx - 1d);
                    else wx = -(dx - 1d) * (dx - 2d) * (dx - 2d);

                    if (dy < 1) wy = (dy - 1d) * (dy * dy - dy - 1d);
                    else wy = -(dy - 1d) * (dy - 2d) * (dy - 2d);

                    src.SetXY(ix, iy);

                    aa += src.A * wx * wy;
                    rr += src.R * src.A * wx * wy;
                    gg += src.G * src.A * wx * wy;
                    bb += src.B * src.A * wx * wy;
                }

            dst[dstX, dstY, eRGB.a] = ImageUtils.AdjustByte(aa);

            if (aa != 0)
            {
                dst.SetXY(dstX, dstY);

                dst.R = AdjustByte(rr / aa);
                dst.G = AdjustByte(gg / aa);
                dst.B = AdjustByte(bb / aa);
            }
        }
        public static bool MotionBlur32(ref Bitmap bmp, int range, double angle)
        {
            if (bmp.PixelFormat != PixelFormat.Format32bppArgb)
                return false;

            if (range < 2) return false;

            int w = bmp.Width;
            int h = bmp.Height;

            angle += 180;

            double sn = Math.Sin(angle * Math.PI / 180d);
            double cs = Math.Cos(angle * Math.PI / 180d);

            int[] dx = new int[range];
            int[] dy = new int[range];

            for (int i = 0; i < range; i++)
            {
                dx[i] = (int)(cs * (i + 1) + 0.5d);
                dy[i] = (int)(sn * (i + 1) + 0.5d);
            }

            int xx, yy, aa, rr, gg, bb, count;

            Bitmap tmp = bmp.Clone() as Bitmap;

            BmpProc32 src = new BmpProc32(tmp);
            BmpProc32 dst = new BmpProc32(bmp);

            for (int y = 0; y < h; y++)
                for (int x = 0; x < w; x++)
                {
                    src.SetXY(x, y);

                    aa = src.A;
                    rr = src.R * src.A;
                    gg = src.G * src.A;
                    bb = src.B * src.A;

                    count = 1;

                    for (int i = 1; i <= range; i++)
                    {
                        xx = x + dx[i - 1];
                        yy = y + dy[i - 1];

                        if ((xx < 0) | (xx > w - 1) | (yy < 0) | (yy > h - 1))
                            continue;

                        src.SetXY(xx, yy);
                        aa += src.A;
                        rr += src.R * src.A;
                        gg += src.G * src.A;
                        bb += src.B * src.A;
                        count++;
                    }

                    dst.SetXY(x, y);

                    dst.A = (byte)(aa / count);
                    dst.R = AdjustByte((double)rr / aa);
                    dst.G = AdjustByte((double)gg / aa);
                    dst.B = AdjustByte((double)bb / aa);
                }

            CallDispose(dst, src, tmp);

            return true;
        }
        public static bool Blur32(ref Bitmap bmp, int zone)
        {
            if (bmp.PixelFormat != PixelFormat.Format32bppArgb)
                return false;

            if ((zone < 1) | (zone > 10)) return false;

            int w = bmp.Width;
            int h = bmp.Height;

            int suma, sumr, sumg, sumb, count;

            Bitmap tmp = (Bitmap)bmp.Clone();

            BmpProc32 src = new BmpProc32(tmp);
            BmpProc32 dst = new BmpProc32(bmp);

            for (int y = 0; y < h; y++)
                for (int x = 0; x < w; x++)
                {
                    suma = sumr = sumg = sumb = count = 0;

                    for (int iy = y - zone; iy <= y + zone; iy++)
                        for (int ix = x - zone; ix <= x + zone; ix++)
                        {
                            if ((ix < 0) | (ix > w - 1)) continue;
                            if ((iy < 0) | (iy > h - 1)) continue;

                            src.SetXY(ix, iy);

                            suma += src.A;
                            sumr += src.R * src.A;
                            sumg += src.G * src.A;
                            sumb += src.B * src.A;
                            count++;
                        }

                    dst.SetXY(x, y);

                    dst.A = (byte)(suma / count);
                    dst.R = AdjustByte((double)sumr / suma);
                    dst.G = AdjustByte((double)sumg / suma);
                    dst.B = AdjustByte((double)sumb / suma);
                }

            CallDispose(dst, src, tmp);

            return true;
        }