Example #1
0
        // Warp an image and return a new Bitmap32 holding the result.
        public Bitmap32 Warp(WarpOperations warp_op, bool lock_result)
        {
            // Make a copy of this Bitmap32.
            Bitmap32 result = this.Clone();

            // Lock both bitmaps.
            bool was_locked = this.IsLocked;

            this.LockBitmap();
            result.LockBitmap();

            // Warp the image.
            WarpImage(this, result, warp_op);

            // Unlock the bitmaps.
            if (!lock_result)
            {
                result.UnlockBitmap();
            }
            if (!was_locked)
            {
                this.UnlockBitmap();
            }

            // Return the result.
            return(result);
        }
Example #2
0
        private static void WarpImage(Warping bm_src, Warping bm_dest, WarpOperations warp_op)
        {
            double xmid = bm_dest.Width / 2.0;
            double ymid = bm_dest.Height / 2.0;
            double rmax = bm_dest.Width * 0.75;

            int ix_max = bm_src.Width - 2;
            int iy_max = bm_src.Height - 2;

            double x0, y0;

            for (int y1 = 0; y1 < bm_dest.Height; y1++)
            {
                for (int x1 = 0; x1 < bm_dest.Width; x1++)
                {
                    MapPixel(warp_op, xmid, ymid, rmax, x1, y1, out x0, out y0);

                    int ix0 = (int)x0;
                    int iy0 = (int)y0;

                    if ((ix0 < 0) || (ix0 > ix_max) ||
                        (iy0 < 0) || (iy0 > iy_max))
                    {
                        bm_dest.SetPixel(x1, y1, 255, 255, 255, 255);
                    }
                    else
                    {
                        double dx0 = x0 - ix0;
                        double dy0 = y0 - iy0;
                        double dx1 = 1 - dx0;
                        double dy1 = 1 - dy0;

                        byte r00, g00, b00, a00, r01, g01, b01, a01,
                             r10, g10, b10, a10, r11, g11, b11, a11;
                        bm_src.GetPixel(ix0, iy0, out r00, out g00, out b00, out a00);
                        bm_src.GetPixel(ix0, iy0 + 1, out r01, out g01, out b01, out a01);
                        bm_src.GetPixel(ix0 + 1, iy0, out r10, out g10, out b10, out a10);
                        bm_src.GetPixel(ix0 + 1, iy0 + 1, out r11, out g11, out b11, out a11);

                        int r = (int)(
                            r00 * dx1 * dy1 + r01 * dx1 * dy0 +
                            r10 * dx0 * dy1 + r11 * dx0 * dy0);
                        int g = (int)(
                            g00 * dx1 * dy1 + g01 * dx1 * dy0 +
                            g10 * dx0 * dy1 + g11 * dx0 * dy0);
                        int b = (int)(
                            b00 * dx1 * dy1 + b01 * dx1 * dy0 +
                            b10 * dx0 * dy1 + b11 * dx0 * dy0);
                        int a = (int)(
                            a00 * dx1 * dy1 + a01 * dx1 * dy0 +
                            a10 * dx0 * dy1 + a11 * dx0 * dy0);
                        bm_dest.SetPixel(x1, y1, (byte)r, (byte)g, (byte)b, (byte)a);
                    }
                }
            }
        }
Example #3
0
        public Warping Warp(WarpOperations warp_op, bool lock_result)
        {
            Warping result = this.Clone();

            bool was_locked = this.IsLocked;

            this.LockBitmap();
            result.LockBitmap();

            WarpImage(this, result, warp_op);

            if (!lock_result)
            {
                result.UnlockBitmap();
            }
            if (!was_locked)
            {
                this.UnlockBitmap();
            }

            return(result);
        }
Example #4
0
        // Map the output pixel (x1, y1) back to the input pixel (x0, y0).
        private static void MapPixel(WarpOperations warp_op, double xmid, double ymid, double rmax, int x1, int y1, out double x0, out double y0)
        {
            const double pi_over_2 = Math.PI / 2.0;
            const double K = 100.0;
            const double offset = -pi_over_2;
            double       dx, dy, r1, r2;

            switch (warp_op)
            {
            case WarpOperations.Identity:
                x0 = x1;
                y0 = y1;
                break;

            case WarpOperations.FishEye:
                dx = x1 - xmid;
                dy = y1 - ymid;
                r1 = Math.Sqrt(dx * dx + dy * dy);
                if (r1 == 0)
                {
                    x0 = xmid;
                    y0 = ymid;
                }
                else
                {
                    r2 = rmax / 2 * (1 / (1 - r1 / rmax) - 1);
                    x0 = dx * r2 / r1 + xmid;
                    y0 = dy * r2 / r1 + ymid;
                }
                break;

            case WarpOperations.Twist:
                dx = x1 - xmid;
                dy = y1 - ymid;
                r1 = Math.Sqrt(dx * dx + dy * dy);
                if (r1 == 0)
                {
                    x0 = 0;
                    y0 = 0;
                }
                else
                {
                    double theta = Math.Atan2(dx, dy) - r1 / K - offset;
                    x0 = r1 * Math.Cos(theta);
                    y0 = r1 * Math.Sin(theta);
                }
                x0 = x0 + xmid;
                y0 = y0 + ymid;
                break;

            case WarpOperations.Wave:
                x0 = x1;
                y0 = y1 - 10 * (Math.Sin(x1 / 50.0 * Math.PI) + 1) + 5;
                break;

            case WarpOperations.SmallTop:
                dx = xmid - x1;
                dx = dx * ymid * 2 / (y1 + 1);
                x0 = xmid - dx;
                y0 = y1;
                break;

            case WarpOperations.Wiggles:
                dx = xmid - x1;
                dx = dx * (Math.Sin(y1 / 50.0 * Math.PI) / 2 + 1.5);
                x0 = xmid - dx;
                y0 = y1;
                break;

            case WarpOperations.DoubleWave:
                x0 = x1 - 10 * (Math.Sin(y1 / 50.0 * Math.PI) + 1) + 5;
                y0 = y1 - 10 * (Math.Sin(x1 / 50.0 * Math.PI) + 1) + 5;
                break;

            default:        // Flip vertically and horizontally.
                x0 = 2 * xmid - x1;
                y0 = 2 * ymid - y1;
                break;
            }
        }
Example #5
0
        // Transform the image.
        private static void WarpImage(Bitmap32 bm_src, Bitmap32 bm_dest, WarpOperations warp_op)
        {
            // Calculate some image information.
            double xmid = bm_dest.Width / 2.0;
            double ymid = bm_dest.Height / 2.0;
            double rmax = bm_dest.Width * 0.75;

            int ix_max = bm_src.Width - 2;
            int iy_max = bm_src.Height - 2;

            // Generate a result for each output pixel.
            double x0, y0;

            for (int y1 = 0; y1 < bm_dest.Height; y1++)
            {
                for (int x1 = 0; x1 < bm_dest.Width; x1++)
                {
                    // Map back to the source image.
                    MapPixel(warp_op, xmid, ymid, rmax, x1, y1, out x0, out y0);

                    // Interpolate to get the result pixel's value.
                    // Find the next smaller integral position.
                    int ix0 = (int)x0;
                    int iy0 = (int)y0;

                    // See if this is out of bounds.
                    if ((ix0 < 0) || (ix0 > ix_max) ||
                        (iy0 < 0) || (iy0 > iy_max))
                    {
                        // The point is outside the image. Use white.
                        bm_dest.SetPixel(x1, y1, 255, 255, 255, 255);
                    }
                    else
                    {
                        // The point lies within the image.
                        // Calculate its value.
                        double dx0 = x0 - ix0;
                        double dy0 = y0 - iy0;
                        double dx1 = 1 - dx0;
                        double dy1 = 1 - dy0;

                        // Get the colors of the surrounding pixels.
                        byte r00, g00, b00, a00, r01, g01, b01, a01,
                             r10, g10, b10, a10, r11, g11, b11, a11;
                        bm_src.GetPixel(ix0, iy0, out r00, out g00, out b00, out a00);
                        bm_src.GetPixel(ix0, iy0 + 1, out r01, out g01, out b01, out a01);
                        bm_src.GetPixel(ix0 + 1, iy0, out r10, out g10, out b10, out a10);
                        bm_src.GetPixel(ix0 + 1, iy0 + 1, out r11, out g11, out b11, out a11);

                        // Compute the weighted average.
                        int r = (int)(
                            r00 * dx1 * dy1 + r01 * dx1 * dy0 +
                            r10 * dx0 * dy1 + r11 * dx0 * dy0);
                        int g = (int)(
                            g00 * dx1 * dy1 + g01 * dx1 * dy0 +
                            g10 * dx0 * dy1 + g11 * dx0 * dy0);
                        int b = (int)(
                            b00 * dx1 * dy1 + b01 * dx1 * dy0 +
                            b10 * dx0 * dy1 + b11 * dx0 * dy0);
                        int a = (int)(
                            a00 * dx1 * dy1 + a01 * dx1 * dy0 +
                            a10 * dx0 * dy1 + a11 * dx0 * dy0);
                        bm_dest.SetPixel(x1, y1, (byte)r, (byte)g, (byte)b, (byte)a);
                    }
                }
            }
        }
Example #6
0
        private static void WarpImage(Warping bm_src, Warping bm_dest, WarpOperations warp_op)
        {
            double xmid = bm_dest.Width / 2.0;
            double ymid = bm_dest.Height / 2.0;
            double rmax = bm_dest.Width * 0.75;

            int ix_max = bm_src.Width - 2;
            int iy_max = bm_src.Height - 2;

            double x0, y0;
            for (int y1 = 0; y1 < bm_dest.Height; y1++)
            {
                for (int x1 = 0; x1 < bm_dest.Width; x1++)
                {
                    MapPixel(warp_op, xmid, ymid, rmax, x1, y1, out x0, out y0);

                    int ix0 = (int)x0;
                    int iy0 = (int)y0;

                    if ((ix0 < 0) || (ix0 > ix_max) ||
                        (iy0 < 0) || (iy0 > iy_max))
                    {
                        bm_dest.SetPixel(x1, y1, 255, 255, 255, 255);
                    }
                    else
                    {
                        double dx0 = x0 - ix0;
                        double dy0 = y0 - iy0;
                        double dx1 = 1 - dx0;
                        double dy1 = 1 - dy0;

                        byte r00, g00, b00, a00, r01, g01, b01, a01,
                             r10, g10, b10, a10, r11, g11, b11, a11;
                        bm_src.GetPixel(ix0, iy0, out r00, out g00, out b00, out a00);
                        bm_src.GetPixel(ix0, iy0 + 1, out r01, out g01, out b01, out a01);
                        bm_src.GetPixel(ix0 + 1, iy0, out r10, out g10, out b10, out a10);
                        bm_src.GetPixel(ix0 + 1, iy0 + 1, out r11, out g11, out b11, out a11);

                        int r = (int)(
                            r00 * dx1 * dy1 + r01 * dx1 * dy0 +
                            r10 * dx0 * dy1 + r11 * dx0 * dy0);
                        int g = (int)(
                            g00 * dx1 * dy1 + g01 * dx1 * dy0 +
                            g10 * dx0 * dy1 + g11 * dx0 * dy0);
                        int b = (int)(
                            b00 * dx1 * dy1 + b01 * dx1 * dy0 +
                            b10 * dx0 * dy1 + b11 * dx0 * dy0);
                        int a = (int)(
                            a00 * dx1 * dy1 + a01 * dx1 * dy0 +
                            a10 * dx0 * dy1 + a11 * dx0 * dy0);
                        bm_dest.SetPixel(x1, y1, (byte)r, (byte)g, (byte)b, (byte)a);
                    }
                }
            }
        }
Example #7
0
        private static void MapPixel(WarpOperations warp_op, double xmid, double ymid, double rmax, int x1, int y1, out double x0, out double y0)
        {
            const double pi_over_2 = Math.PI / 2.0;
            const double K = 100.0;
            const double offset = -pi_over_2;
            double dx, dy, r1, r2;

            switch (warp_op)
            {
                case WarpOperations.Identity:
                    x0 = x1;
                    y0 = y1;
                    break;
                case WarpOperations.FishEye:
                    dx = x1 - xmid;
                    dy = y1 - ymid;
                    r1 = Math.Sqrt(dx * dx + dy * dy);
                    if (r1 == 0)
                    {
                        x0 = xmid;
                        y0 = ymid;
                    }
                    else
                    {
                        r2 = rmax / 2 * (1 / (1 - r1 / rmax) - 1);
                        x0 = dx * r2 / r1 + xmid;
                        y0 = dy * r2 / r1 + ymid;
                    }
                    break;
                case WarpOperations.Twist:
                    dx = x1 - xmid;
                    dy = y1 - ymid;
                    r1 = Math.Sqrt(dx * dx + dy * dy);
                    if (r1 == 0)
                    {
                        x0 = 0;
                        y0 = 0;
                    }
                    else
                    {
                        double theta = Math.Atan2(dx, dy) - r1 / K - offset;
                        x0 = r1 * Math.Cos(theta);
                        y0 = r1 * Math.Sin(theta);
                    }
                    x0 = x0 + xmid;
                    y0 = y0 + ymid;
                    break;
                case WarpOperations.Wave:
                    x0 = x1;
                    y0 = y1 - 10 * (Math.Sin(x1 / 50.0 * Math.PI) + 1) + 5;
                    break;
                case WarpOperations.SmallTop:
                    dx = xmid - x1;
                    dx = dx * ymid * 2 / (y1 + 1);
                    x0 = xmid - dx;
                    y0 = y1;
                    break;
                case WarpOperations.Wiggles:
                    dx = xmid - x1;
                    dx = dx * (Math.Sin(y1 / 50.0 * Math.PI) / 2 + 1.5);
                    x0 = xmid - dx;
                    y0 = y1;
                    break;
                case WarpOperations.DoubleWave:
                    x0 = x1 - 10 * (Math.Sin(y1 / 50.0 * Math.PI) + 1) + 5;
                    y0 = y1 - 10 * (Math.Sin(x1 / 50.0 * Math.PI) + 1) + 5;
                    break;
                default:
                    x0 = 2 * xmid - x1;
                    y0 = 2 * ymid - y1;
                    break;
            }
        }
Example #8
0
        public Warping Warp(WarpOperations warp_op, bool lock_result)
        {
            Warping result = this.Clone();

            bool was_locked = this.IsLocked;
            this.LockBitmap();
            result.LockBitmap();

            WarpImage(this, result, warp_op);

            if (!lock_result) result.UnlockBitmap();
            if (!was_locked) this.UnlockBitmap();

            return result;
        }