GDI+图像扭曲变形 [转]

出来的效果是椭圆或圆形,呈涡状,视原始图片而定。

总体来说,这个代码处理的速度很慢,如果使用不安全代码的话,在性能上会有很大的提升。

 

        private void button1_Click(object sender, EventArgs e)
        {
            Bitmap image = new Bitmap(@"c:/DSC_0096_S.JPG");
            int x, y;
            float x1, y1;
            float fx, fy, xmid, ymid, ar;
            Bitmap image2 = new Bitmap(image);
            xmid = (float)(image.Width / 2.0);
            ymid = (float)(image.Height / 2.0);
            ar = (float)(image.Height) / (float)(image.Width);
            for (y = 0; y < image.Height; y++)
            {
                for (x = 0; x < image.Width; x++)
                {
                    ComputePixel(ar * (x - xmid), y - ymid, out fx, out fy);
                    x1 = xmid + fx / ar;
                    y1 = ymid + fy;
                    image2.SetPixel(x, y, GetPixelColorInterpolated(ref image, x1, y1));
                }
            }
            this.pictureBox1.Image = image2;
        }

        static int ComputePixel(float x, float y, out float x1, out float y1)
        {
            double r, nn;
            if (x == 0 && y == 0)
            {
                x1 = x;
                y1 = y;
                return 1;
            }
            nn = Math.Sqrt(x * x + y * y);
            r = (Math.Abs(x) > Math.Abs(y)) ? Math.Abs(nn / x) : Math.Abs(nn / y);
            x1 = (float)(r * x);
            y1 = (float)(r * y);
            return 1;
        }

        static Color GetPixelColorInterpolated(ref Bitmap image, float x, float y)
        {
            int xi = (int)(x);
            if (x < 0) xi--;
            int yi = (int)(y);
            if (y < 0) yi--;
            if (xi < -1 || xi >= image.Width || yi < -1 || yi >= image.Height)
            {
                return GetPixelColorWithOverflow(ref image, -999, -999);
            }
            //get four neighbouring pixels
            if ((xi + 1) < image.Width && xi >= 0 && (yi + 1) < image.Height && yi >= 0)
            {
                ushort wt1 = (ushort)((x - xi) * 256.0f), wt2 = (ushort)((y - yi) * 256.0f);
                ushort wd = (ushort)(wt1 * wt2 >> 8);
                ushort wb = (ushort)(wt1 - wd);
                ushort wc = (ushort)(wt2 - wd);
                ushort wa = (ushort)(256 - wt1 - wc);
                ushort wrr, wgg, wbb;
                Color clr = image.GetPixel(xi, yi);
                wbb = (ushort)(wa * clr.B);
                wgg = (ushort)(wa * clr.G);
                wrr = (ushort)(wa * clr.R);
                clr = image.GetPixel(xi + 1, yi);
                wbb += (ushort)(wb * clr.B);
                wgg += (ushort)(wb * clr.G);
                wrr += (ushort)(wb * clr.R);
                clr = image.GetPixel(xi, yi + 1);
                wbb += (ushort)(wc * clr.B);
                wgg += (ushort)(wc * clr.G);
                wrr += (ushort)(wc * clr.R);
                clr = image.GetPixel(xi + 1, yi + 1);
                wbb += (ushort)(wd * clr.B);
                wgg += (ushort)(wd * clr.G);
                wrr += (ushort)(wd * clr.R);
                return Color.FromArgb(255, wrr >> 8, wgg >> 8, wbb >> 8);
            }
            else
            {
                float t1 = x - xi, t2 = y - yi;
                float d = t1 * t2;
                float b = t1 - d;
                float c = t2 - d;
                float a = 1 - t1 - c;
                Color rgb11, rgb21, rgb12, rgb22;
                rgb11 = GetPixelColorWithOverflow(ref image, xi, yi);
                rgb21 = GetPixelColorWithOverflow(ref image, xi + 1, yi);
                rgb12 = GetPixelColorWithOverflow(ref image, xi, yi + 1);
                rgb22 = GetPixelColorWithOverflow(ref image, xi + 1, yi + 1);
                //calculate linear interpolation
                return Color.FromArgb(255,
                    (byte)(a * rgb11.R + b * rgb21.R + c * rgb12.R + d * rgb22.R),
                    (byte)(a * rgb11.G + b * rgb21.G + c * rgb12.G + d * rgb22.G),
                    (byte)(a * rgb11.B + b * rgb21.B + c * rgb12.B + d * rgb22.B));
            }
        }

        static Color GetPixelColorWithOverflow(ref Bitmap image, long x, long y)
        {
            if (!IsInside(ref image, x, y))
            {
                return Color.FromArgb(255, 255, 255, 255);
            }
            return image.GetPixel((int)x, (int)y);
        }

        static bool IsInside(ref Bitmap image, long x, long y)
        {
            return (0 <= y && y < image.Height && 0 <= x && x < image.Width);
        }

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值