public static void intBilinear32(BmpProc32 dst, BmpProc32 src,
                                int dstX, int dstY, double srcX, double srcY)
        {
            int x1 = (int)Math.Floor(srcX);
            int x2 = x1 + 1;
            double fx2 = srcX - x1;
            double fx1 = 1 - fx2;

            int y1 = (int)Math.Floor(srcY);
            int y2 = y1 + 1;
            double fy2 = srcY - y1;
            double fy1 = 1 - fy2;

            byte aa =
                (byte)(src[x1, y1, eRGB.a] * fx1 * fy1 +
                       src[x2, y1, eRGB.a] * fx2 * fy1 +
                       src[x1, y2, eRGB.a] * fx1 * fy2 +
                       src[x2, y2, eRGB.a] * fx2 * fy2);

            dst[dstX, dstY, eRGB.a] = aa;

            if (aa != 0)
            {

                dst[dstX, dstY, eRGB.r] =
                    (byte)((src[x1, y1, eRGB.r] * src[x1, y1, eRGB.a] * fx1 * fy1 +
                           src[x2, y1, eRGB.r] * src[x2, y1, eRGB.a] * fx2 * fy1 +
                           src[x1, y2, eRGB.r] * src[x1, y2, eRGB.a] * fx1 * fy2 +
                           src[x2, y2, eRGB.r] * src[x2, y2, eRGB.a] * fx2 * fy2) /
                           aa);

                dst[dstX, dstY, eRGB.g] =
                    (byte)((src[x1, y1, eRGB.g] * src[x1, y1, eRGB.a] * fx1 * fy1 +
                           src[x2, y1, eRGB.g] * src[x2, y1, eRGB.a] * fx2 * fy1 +
                           src[x1, y2, eRGB.g] * src[x1, y2, eRGB.a] * fx1 * fy2 +
                           src[x2, y2, eRGB.g] * src[x2, y2, eRGB.a] * fx2 * fy2) /
                           aa);

                dst[dstX, dstY, eRGB.b] =
                    (byte)((src[x1, y1, eRGB.b] * src[x1, y1, eRGB.a] * fx1 * fy1 +
                           src[x2, y1, eRGB.b] * src[x2, y1, eRGB.a] * fx2 * fy1 +
                           src[x1, y2, eRGB.b] * src[x1, y2, eRGB.a] * fx1 * fy2 +
                           src[x2, y2, eRGB.b] * src[x2, y2, eRGB.a] * fx2 * fy2) /
                           aa);

            }
        }
        public static bool Ellipse2(ref Bitmap bmp)
        {
            if (bmp.PixelFormat != PixelFormat.Format24bppRgb)
                return false;

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

            int mg = 3; // margin for interpolations

            int q = Math.Max(w, h);

            RectangleF rct = new RectangleF(-1, -1, q + 1, q + 1);

            Bitmap tmp1 = new Bitmap(q + mg * 2, q + mg * 2, PixelFormat.Format32bppArgb);

            Graphics g = Graphics.FromImage(tmp1);
            g.InterpolationMode = InterpolationMode.HighQualityBicubic;
            g.DrawImage(bmp, mg, mg, q, q);
            g.Dispose();

            Bitmap tmp2 = new Bitmap(q, q, PixelFormat.Format32bppArgb);
            g = Graphics.FromImage(tmp2);
            g.Dispose();

            double l, xx, yy;
            double r = (double)q / 2d;

            BmpProc32 src = new BmpProc32(tmp1);
            BmpProc32 dst = new BmpProc32(tmp2);

            for (int y = 1; y < q; y++)
                for (int x = 0; x < q; x++)
                {
                    l = Math.Sqrt(2d * r * y - y * y);
                    if (l == 0) xx = 0; else xx = r * (x - r) / l + r;
                    yy = y;

                    if (rct.Contains(new PointF((float)xx, (float)yy)))
                    {
                        xx = xx + mg;
                        yy = yy + mg;

                        intBicubic32(dst, src, x, y, xx, yy);
                    }
                }

            CallDispose(dst, src, tmp1);

            Bitmap tmp3 = new Bitmap(w, h, PixelFormat.Format32bppArgb);

            g = Graphics.FromImage(tmp3);
            g.InterpolationMode = InterpolationMode.HighQualityBicubic;
            g.DrawImage(tmp2, 0, 0, w, h);
            g.Dispose();

            tmp2.Dispose();

            bmp.Dispose();

            bmp = tmp3;

            return true;
        }
        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] = ImageUtility.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 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;
        }
        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 SetAlpha(ref Bitmap bmp, int percent)
        {
            int w = bmp.Width;
            int h = bmp.Height;

            Bitmap tmp = new Bitmap(w, h, PixelFormat.Format32bppArgb);
            Graphics g = Graphics.FromImage(tmp);
            g.DrawImageUnscaled(bmp, 0, 0);
            g.Dispose();

            byte alpha = (byte)(255 * percent / 100);

            BmpProc32 dst = new BmpProc32(tmp);

            for (int y = 0; y < h; y++)
                for (int x = 0; x < w; x++)
                    dst[x, y, eRGB.a] = alpha;

            dst.Dispose();
            bmp.Dispose();

            bmp = tmp;

            return true;
        }
        public static bool AlphaSheet(ref Bitmap bmp, bool stretch, bool bInvert)
        {
            if (bmp.PixelFormat != PixelFormat.Format24bppRgb)
                return false;

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

            Bitmap tmp = new Bitmap(w, h, PixelFormat.Format32bppArgb);
            Graphics g = Graphics.FromImage(tmp);
            g.DrawImageUnscaled(bmp, 0, 0);
            g.Dispose();

            ImageUtility.GrayScale(ref bmp);
            if (stretch) ImageUtility.HistoStretch(ref bmp);

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

            if (bInvert)
                for (int y = 0; y < h; y++)
                    for (int x = 0; x < w; x++)
                        dst[x, y, eRGB.a] = (byte)(255 - src[x, y]);
            else
                for (int y = 0; y < h; y++)
                    for (int x = 0; x < w; x++)
                        dst[x, y, eRGB.a] = src[x, y];

            CallDispose(dst, src, bmp);

            bmp = tmp;

            return true;
        }
        public static bool Diacross(ref Bitmap bmp, bool bFine,
                                            Color penColor, Color bkColor)
        {
            if (bmp.PixelFormat != PixelFormat.Format24bppRgb)
                return false;

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

            Graphics g;

            GrayScale(ref bmp);
            HistoStretch(ref bmp);

            Bitmap[] pattern = new Bitmap[4];
            TextureBrush[] tb = new TextureBrush[4];

            if (bFine)
            {
                Pen pn = new Pen(penColor, 1.8f);
                pn.Alignment = PenAlignment.Center;

                PointF[] start = { new PointF(0f, 0.5f), new PointF(0.5f, 0F), 
                                            new PointF(0f, 2.5f), new PointF(2.5f, 0f) };
                PointF[] stop = { new PointF(4f, 0.5f), new PointF(0.5f, 4f), 
                                            new PointF(4f, 2.5f), new PointF(2.5f, 4f) };

                float[] angle = { -37f, -53f };

                for (int i = 0; i < 4; i++)
                {
                    pattern[i] = new Bitmap(4, 4, PixelFormat.Format24bppRgb);
                    g = Graphics.FromImage(pattern[i]);
                    g.Clear(Color.White);
                    g.DrawLine(pn, start[i], stop[i]);
                    g.Dispose();

                    tb[i] = MakePatternBrush(pattern[i], angle[i % 2]);
                }

                pn.Dispose();
            }
            else
            {
                Pen pn = new Pen(penColor, 2.2f);
                pn.Alignment = PenAlignment.Center;

                Point[] start = { new Point(0, 1), new Point(1, 0), 
                                        new Point(0, 4), new Point(4, 0) };
                Point[] stop = { new Point(9, 1), new Point(1, 9), 
                                        new Point(9, 4), new Point(4, 9) };

                float[] angle = { -30f, -60f };

                for (int i = 0; i < 4; i++)
                {
                    pattern[i] = new Bitmap(6, 6, PixelFormat.Format32bppArgb);
                    g = Graphics.FromImage(pattern[i]);
                    g.Clear(Color.White);
                    g.DrawLine(pn, start[i], stop[i]);
                    g.Dispose();

                    tb[i] = MakePatternBrush(pattern[i], angle[i % 2]);
                }

                pn.Dispose();
            }

            Bitmap dst = new Bitmap(w, h, PixelFormat.Format24bppRgb);
            Graphics gdst = Graphics.FromImage(dst);
            gdst.Clear(bkColor);

            byte[] th = { 255, 191, 128, 64 };

            Bitmap tgt;

            BmpProc8 mod = new BmpProc8(bmp);

            for (int i = 0; i < 4; i++)
            {

                tgt = new Bitmap(w, h, PixelFormat.Format32bppArgb);

                g = Graphics.FromImage(tgt);
                g.FillRectangle(tb[i], 0, 0, w, h);
                g.Dispose();
                tb[i].Dispose();
                pattern[i].Dispose();

                BmpProc32 src = new BmpProc32(tgt);

                for (int y = 0; y < h; y++)
                    for (int x = 0; x < w; x++)
                    {
                        if (mod[x, y] < th[i])
                            src[x, y, eRGB.a] =
                                AdjustByte((double)(255 - src[x, y, eRGB.r]) *
                                    ((1d - ((double)mod[x, y] / (double)th[i]))));
                        else
                            src[x, y, eRGB.a] = 0;
                    }

                src.Dispose();

                gdst.DrawImageUnscaled(tgt, 0, 0);

                tgt.Dispose();
            }

            mod.Dispose();
            bmp.Dispose();
            gdst.Dispose();

            bmp = dst;
            return true;
        }
        public static bool AlphaGradient(ref Bitmap bmp, float[] factor,
                                              float[] position, GradientSide gs)
        {
            if (bmp.PixelFormat != PixelFormat.Format24bppRgb)
                return false;

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

            Bitmap tmp = new Bitmap(w, h, PixelFormat.Format32bppArgb);
            Graphics g = Graphics.FromImage(tmp);
            g.DrawImageUnscaled(bmp, 0, 0);
            g.Dispose();

            Color startColor = Color.White;
            Color endColor = Color.Black;

            Point start = new Point(-1, 0);
            Point end = new Point(0, 0);

            switch (gs)
            {
                case GradientSide.Left:
                    end.X = w;
                    break;

                case GradientSide.Right:
                    start.X = w;
                    break;

                case GradientSide.Upper:
                    end.Y = h;
                    break;

                case GradientSide.Lower:
                    start.Y = h;
                    break;

                case GradientSide.UpperLeft:
                    end.X = w;
                    end.Y = h;
                    break;

                case GradientSide.UpperRight:
                    start.X = w;
                    end.Y = h;
                    break;

                case GradientSide.LowerLeft:
                    start.Y = h;
                    end.X = w;
                    break;

                case GradientSide.LowerRight:
                    start.X = w;
                    start.Y = h;
                    break;
            }

            Blend bl = new Blend();
            bl.Factors = factor;
            bl.Positions = position;

            LinearGradientBrush br = new LinearGradientBrush(
                                        start, end, startColor, endColor);
            br.Blend = bl;
            //br.GammaCorrection = true;

            Rectangle rct = new Rectangle(0, 0, w, h);

            g = Graphics.FromImage(bmp);
            g.FillRectangle(br, rct);
            g.Dispose();

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

            for (int y = 0; y < h; y++)
                for (int x = 0; x < w; x++)
                    dst[x, y, eRGB.a] = src[x, y, eRGB.r];

            CallDispose(dst, src, bmp);

            bmp = tmp;

            return true;
        }
        public static bool AlphaRects(ref Bitmap bmp, byte offset,
                                                       params Rectangle[] rct)
        {
            if (bmp.PixelFormat != PixelFormat.Format24bppRgb)
                return false;

            if (rct.Length == 0) return false;

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

            Bitmap tmp = new Bitmap(w, h, PixelFormat.Format32bppArgb);
            Graphics g = Graphics.FromImage(tmp);
            g.DrawImageUnscaled(bmp, 0, 0);
            g.Dispose();

            double pi = Math.PI;
            double f;

            BmpProc32 src = new BmpProc32(tmp);

            for (int y = 0; y < h; y++)
                for (int x = 0; x < w; x++)
                    src[x, y, eRGB.a] = offset;

            for (int i = 0; i < rct.Length; i++)
            {

                for (int y = rct[i].Y; y < rct[i].Y + rct[i].Height; y++)
                    for (int x = rct[i].X; x < rct[i].X + rct[i].Width; x++)
                    {
                        if ((x < 0) | (x > w - 1) |
                                       (y < 0) | (y > h - 1)) continue;

                        f = 1.2 * Math.Sin((x - rct[i].X) * pi / rct[i].Width) *
                                       Math.Sin((y - rct[i].Y) * pi / rct[i].Height);
                        if (f > 1d) f = 1d;
                        src[x, y, eRGB.a] = Math.Max(src[x, y, eRGB.a], (byte)(f * 255));
                    }

            }

            src.Dispose();

            bmp.Dispose();

            bmp = tmp;

            return true;
        }
        public static bool AlphaSpots(ref Bitmap bmp, byte offset,
                                                               params RadiusPos[] rp)
        {
            if (bmp.PixelFormat != PixelFormat.Format24bppRgb)
                return false;

            if (rp.Length == 0) return false;

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

            Bitmap tmp = new Bitmap(w, h, PixelFormat.Format32bppArgb);
            Graphics g = Graphics.FromImage(tmp);
            g.DrawImageUnscaled(bmp, 0, 0);
            g.Dispose();

            double cx, cy, rr, r, f;

            BmpProc32 src = new BmpProc32(tmp);

            for (int y = 0; y < h; y++)
                for (int x = 0; x < w; x++)
                    src[x, y, eRGB.a] = offset;

            for (int i = 0; i < rp.Length; i++)
            {
                cx = rp[i].PosX; cy = rp[i].PosY;
                rr = rp[i].Radius; rr = rr * rr;

                for (int y = 0; y < h; y++)
                    for (int x = 0; x < w; x++)
                    {
                        r = (x - cx) * (x - cx) + (y - cy) * (y - cy);
                        f = 1.2d * (1d - r / rr);
                        if (f > 1d) f = 1d;
                        if (f > 0)
                            src[x, y, eRGB.a] = Math.Max(src[x, y, eRGB.a], AdjustByte(255 * f));
                    }
            }

            src.Dispose();

            bmp.Dispose();

            bmp = tmp;

            return true;
        }
        public static bool SetFramedAlpha(ref Bitmap bmp)
        {
            if (bmp.PixelFormat != PixelFormat.Format24bppRgb) return false;

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

            Bitmap tmp = new Bitmap(w, h, PixelFormat.Format32bppArgb);

            Graphics g = Graphics.FromImage(tmp);
            g.DrawImageUnscaled(bmp, 0, 0);
            g.Dispose();

            double pi = Math.PI;
            double f;

            BmpProc32 dst = new BmpProc32(tmp);

            for (int y = 0; y < h; y++)
            {
                for (int x = 0; x < w; x++)
                {
                    f = Math.Sin(y * pi / h) * Math.Sin(x * pi / w);
                    dst[x, y, eRGB.a] = (byte)(255 * f);
                }
            }

            dst.Dispose();

            bmp.Dispose();
            bmp = tmp;

            return true;
        }