ComponentOne Imaging for UWP
Imaging for UWP / Bitmap / Working with Bitmap for UWP / Warping an Image
In This Topic
    Warping an Image
    In This Topic

    Just for fun, you might want to be able to warp an image. The code needed to create the warp effect is somewhat complex, but it uses the C1DragHelpers and some math to apply the warp effect to your image. In the FaceWarp sample, you can load your own image, export your completed image, and reset the image if you don't like how the warp looks.

    C#
    Copy Code
    InitializeComponent();
                LoadDefaultImage();
                image.Source = screen.ImageSource;
                var mouseHelper = new C1DragHelper(image, captureElementOnPointerPressed: true);
                var line = new Line();
                mouseHelper.DragStarted += (s, e) =>
                {
                    _position = e.GetPosition(image);
                    line = new Line
                    {
                        X1 = _position.X,
                        Y1 = _position.Y,
                        X2 = _position.X,
                        Y2 = _position.Y,
                        Stroke = new SolidColorBrush(Colors.Blue),
                        StrokeThickness = 7,
                        StrokeEndLineCap = PenLineCap.Triangle,
                        StrokeStartLineCap = PenLineCap.Round
                    };
                    imageGrid.Children.Add(line);
                };
                mouseHelper.DragDelta += (s, e) =>
                {
                    var pos = e.GetPosition(image);
                    line.X2 = pos.X;
                    line.Y2 = pos.Y;
                };
                mouseHelper.DragCompleted += (s, e) =>
                {
                    imageGrid.Children.Remove(line);
                    var start = _position;
                    var end = new Point(_position.X + e.CumulativeTranslation.X, _position.Y + e.CumulativeTranslation.Y);
                    bitmap = new C1Bitmap(screen);
                    Warp(bitmap, screen, start, end);
                };
            }
    void Warp(C1Bitmap src, C1Bitmap dst, Point start, Point end)
            {
                dst.BeginUpdate();
                dst.Copy(src, false);
                var dist = Distance(start, end);
                var affectedDist = dist * 1.5;
                var affectedDistSquared = affectedDist * affectedDist;
                for (int row = 0; row < dst.Height; ++row)
                {
                    for (int col = 0; col < dst.Width; ++col)
                    {
                        var point = new Point(col, row);
                        if (DistanceSq(start, point) > affectedDistSquared)
                        {
                            continue;
                        }
                        if (DistanceSq(end, point) < 0.25)
                        {
                            dst.SetPixel(col, row, src.GetPixel((int)start.X, (int)start.Y));
                            continue;
                        }
                        var dir = new Point(point.X - end.X, point.Y - end.Y);
                        var t = IntersectRayCircle(end, dir, start, affectedDist);
                        TryT(-end.X / dir.X, ref t);
                        TryT(-end.Y / dir.Y, ref t);
                        TryT((dst.Width - end.X) / dir.X, ref t);
                        TryT((dst.Height - end.X) / dir.X, ref t);
                        var anchor = new Point(end.X + (point.X - end.X) * t, end.Y + (point.Y - end.Y));
                        var x = start.X + (anchor.X - start.X) / t;
                        var y = start.Y + (anchor.Y - start.Y) / t;
                        dst.SetPixel(col, row, src.GetInterpolatedPixel(x, y));
                    }
                }
                dst.EndUpdate();
            }
            static double Distance(Point a, Point b)
            {
                return Math.Sqrt(DistanceSq(a, b));
            }
            static double DistanceSq(Point a, Point b)
            {
                var dx = a.X - b.X;
                var dy = a.Y - b.Y;
                return dx * dx + dy * dy;
            }
            static void TryT(double t2, ref double t)
            {
                if (t2 > 0 && t2 < t)
                {
                    t = t2;
                }
            }
            static double IntersectRayCircle(Point rayOri, Point rayDir, Point center, double radius)
            {
                var a = rayDir.X;
                var b = rayOri.X;
                var c = center.X;
                var d = rayDir.Y;
                var e = rayOri.Y;
                var f = center.Y;
                var g = radius * radius;
                var num1 = Math.Sqrt(d * (2 * a * (b - c) * (e - f) - d * (b * b - 2 * b * c + c * c - g)) - a * a * (e * e - 2 * e * f + f * f - g));
                var num2 = a * (c - b) + d * (f - e);
                return (num1 + num2 > 0 ? num1 + num2 : num1 - num2) / (a * a + d * d);
            }
    

     

    See Also