/// <summary>
        /// Dissolves two images using alphablending
        /// </summary>
        /// <param name="startImage">Image for percentage=0</param>
        /// <param name="endImage">Image for percentage=1</param>
        /// <param name="morphingProgress">Dissolve percentage from 0 to 1</param>
        /// <param name="outputImage">Target for image output data</param>
        public unsafe void DissolveImages(Morphing.ImageData startImage, Morphing.ImageData endImage, float percentage, WriteableBitmap outputImage)
        {
            System.Diagnostics.Debug.Assert(percentage >= 0.0f && percentage <= 1.0f);
            System.Diagnostics.Debug.Assert(startImage != null && endImage != null && outputImage != null);

            outputImage.Lock();

            int width = outputImage.PixelWidth;
            int height = outputImage.PixelHeight;
            float xStep = 1.0f / width;

            Color* outputData = (Color*)outputImage.BackBuffer;
            Parallel.For(0, outputImage.PixelHeight, yi =>
            {
                Color* outputDataPixel = outputData + yi * width;
                Color* lastOutputDataPixel = outputDataPixel + width;
                float y = (float)yi / height;
                for (float x = 0; outputDataPixel != lastOutputDataPixel; x += xStep, ++outputDataPixel)
                {
                    *outputDataPixel = Color.Lerp(startImage.Sample(x, y), endImage.Sample(x, y), percentage);
                }
            });

            outputImage.AddDirtyRect(new System.Windows.Int32Rect(0, 0, outputImage.PixelWidth, outputImage.PixelHeight));
            outputImage.Unlock();
        }
        unsafe void WarpingAlgorithm.WarpImage(MarkerSet markerSet, Morphing.ImageData inputImage, Morphing.ImageData outputImage, bool startImage)
        {
            System.Diagnostics.Debug.Assert(markerSet != null && inputImage != null && outputImage != null);

            PointMarkerSet pointMarkerSet = markerSet as PointMarkerSet;
            System.Diagnostics.Debug.Assert(pointMarkerSet != null);

            // minor precomputation - movevector & interppos (for more mem consistency)
            WarpMarker[] markers;
            if (startImage)
            {
                markers = pointMarkerSet.Points.Select(x => new WarpMarker
                {
                    CurrentPos = x.InterpolatedMarker,
                    MoveVec = x.StartMarker - x.InterpolatedMarker
                }).ToArray();
            }
            else
            {
                markers = pointMarkerSet.Points.Select(x => new WarpMarker
                {
                    CurrentPos = x.InterpolatedMarker,
                    MoveVec = x.EndMarker - x.InterpolatedMarker
                }).ToArray();
            }
            double xStep = 1.0 / outputImage.Width;

            if (markers.Length == 0)
                return;

            Parallel.For(0, outputImage.Height, yi =>
            {
                Color* outputDataPixel = outputImage.Data + yi * outputImage.Width;
                Color* lastOutputDataPixel = outputDataPixel + outputImage.Width;
                double y = (double)yi / outputImage.Height;

                for (double x = 0; outputDataPixel != lastOutputDataPixel; x += xStep, ++outputDataPixel)
                {
                    Vector position = new Vector(x, y);
                    Vector displacement = new Vector(0,0);

                    // fixed ptr won't work inside loop! // for(WarpMarker* pMarker = pMarkerFirst; pMarker != pMarkerEnd; ++pMarker)
                    double weightSum = 0.0f;
                    foreach (var marker in markers)
                    {
                        double distSq = (position - marker.CurrentPos).LengthSquared;
                        double weight = Math.Exp(-distSq / POINT_WEIGHT);//1.0f / (1.0f + distSq / POINT_WEIGHT);        // inverse quadratic!
                        weightSum += weight;
                        displacement += marker.MoveVec * weight;
                    }
                    displacement /= weightSum;
                    position += displacement;
                    position = position.ClampToImageArea();

                    *outputDataPixel = inputImage.Sample(position.X, position.Y);
                }
            });
        }
Example #3
1
        unsafe void WarpingAlgorithm.WarpImage(MarkerSet markerSet, Morphing.ImageData inputImage, Morphing.ImageData outputImage, bool startImage)
        {
            System.Diagnostics.Debug.Assert(markerSet != null && inputImage != null && outputImage != null);

            LineMarkerSet lineMarkerSet = markerSet as LineMarkerSet;
            System.Diagnostics.Debug.Assert(lineMarkerSet != null);

            double xStep = 1.0 / outputImage.Width;

            WarpMarker[] markers;
            if (startImage)
            {
                markers = lineMarkerSet.Lines.Select(x => new WarpMarker
                {
                    target_start = x.InterpolatedMarker.Start,
                    target_dirNorm = x.InterpolatedMarker.End - x.InterpolatedMarker.Start,
                    target_perpendicNorm = (x.InterpolatedMarker.End - x.InterpolatedMarker.Start).Perpendicular(),
                    target_lineLength = (x.InterpolatedMarker.End - x.InterpolatedMarker.Start).Length,

                    dest_start = x.StartMarker.Start,
                    dest_dirNorm = x.StartMarker.End - x.StartMarker.Start,
                    dest_perpendicNorm = (x.StartMarker.End - x.StartMarker.Start).Perpendicular(),
                }).ToArray();
            }
            else
            {
                markers =  lineMarkerSet.Lines.Select(x => new WarpMarker
                {
                    target_start = x.InterpolatedMarker.Start,
                    target_dirNorm = x.InterpolatedMarker.End - x.InterpolatedMarker.Start,
                    target_perpendicNorm = (x.InterpolatedMarker.End - x.InterpolatedMarker.Start).Perpendicular(),
                    target_lineLength = (x.InterpolatedMarker.End - x.InterpolatedMarker.Start).Length,

                    dest_start = x.EndMarker.Start,
                    dest_dirNorm = x.EndMarker.End - x.EndMarker.Start,
                    dest_perpendicNorm = (x.EndMarker.End - x.EndMarker.Start).Perpendicular(),
                }).ToArray();
            }
            for (int markerIdx = 0; markerIdx < markers.Length; ++markerIdx)
            {
             //   markers[markerIdx].target_dirLength = markers[markerIdx].target_dir.Length;
                markers[markerIdx].target_perpendicNorm.Normalize();
                markers[markerIdx].target_dirNorm.Normalize();
                markers[markerIdx].dest_perpendicNorm.Normalize();
                markers[markerIdx].dest_dirNorm.Normalize();
            }

            if (markers.Length == 0)
                return;

            Parallel.For(0, outputImage.Height, yi =>
            {
                Color* outputDataPixel = outputImage.Data + yi * outputImage.Width;
                Color* lastOutputDataPixel = outputDataPixel + outputImage.Width;
                double y = (double)yi / outputImage.Height;

                for (double x = 0; outputDataPixel != lastOutputDataPixel; x += xStep, ++outputDataPixel)
                {
                    Vector position = new Vector(x, y);
                    Vector displacement = new Vector(0, 0);
                    double weightSum = 0.0f;

                    for (int markerIdx = 0; markerIdx < markers.Length; ++markerIdx)
                    {
                        Vector toStart = position - markers[markerIdx].target_start;

                        // calc relative coordinates to line
                        double u = toStart.Dot(markers[markerIdx].target_dirNorm);
                        double v = toStart.Dot(markers[markerIdx].target_perpendicNorm);
                        // calc weight
                        double weight;
                        if (u < 0) // bellow
                            weight = toStart.LengthSquared;
                        else if (u > 1) // above
                            weight = (toStart + markers[markerIdx].target_dirNorm * markers[markerIdx].target_lineLength).LengthSquared;
                        else // beside
                            weight = v * v;
                        weight = Math.Exp(-weight / LINE_WEIGHT); //Math.Pow(markers[markerIdx].target_lineLength / (A + weight), B);
                        weightSum += weight;

                        // translation
                        Vector srcPoint = markers[markerIdx].dest_start + u * markers[markerIdx].dest_dirNorm + v * markers[markerIdx].dest_perpendicNorm;
                        displacement += (srcPoint - position) * weight;
                    }

                    displacement /= weightSum;
                    position += displacement;
                    position = position.ClampToImageArea();

                    *outputDataPixel = inputImage.Sample(position.X, position.Y);
                }
            });
        }
Example #4
0
        unsafe void WarpingAlgorithm.WarpImage(MarkerSet markerSet, Morphing.ImageData inputImage, Morphing.ImageData outputImage, bool startImage)
        {
            System.Diagnostics.Debug.Assert(markerSet != null && inputImage != null && outputImage != null);

            TriangleMarkerSet triangleMarkerSet = markerSet as TriangleMarkerSet;
            System.Diagnostics.Debug.Assert(triangleMarkerSet != null);

            if (triangleMarkerSet.Triangles.Count() == 0)
                return;

            // prepare data
                // dest
            DestTriangle[] destTriangles = triangleMarkerSet.Triangles.Select(x => new DestTriangle()
                    {
                        A = x.Vertices[0].InterpolatedMarker,
                        V0 = x.Vertices[2].InterpolatedMarker - x.Vertices[0].InterpolatedMarker,
                        V1 = x.Vertices[1].InterpolatedMarker - x.Vertices[0].InterpolatedMarker
                    }).ToArray();
            for (int i = 0; i < destTriangles.Length; ++i )
            {
                destTriangles[i].V0DotV0_divDenom = destTriangles[i].V0.LengthSquared;
                destTriangles[i].V1DotV1_divDenom = destTriangles[i].V1.LengthSquared;
                destTriangles[i].V0DotV1_divDenom = destTriangles[i].V0.Dot(destTriangles[i].V1);
                double invDenom = 1.0 / (destTriangles[i].V0DotV0_divDenom * destTriangles[i].V1DotV1_divDenom - destTriangles[i].V0DotV1_divDenom * destTriangles[i].V0DotV1_divDenom);
                destTriangles[i].V0DotV0_divDenom *= invDenom;
                destTriangles[i].V1DotV1_divDenom *= invDenom;
                destTriangles[i].V0DotV1_divDenom *= invDenom;
            }
                // src
            SourceTriangle[] sourceTriangles;
            if (startImage)
            {
                sourceTriangles = triangleMarkerSet.Triangles.Select(x => new SourceTriangle()
                    {
                        A = x.Vertices[0].StartMarker,
                        V0 = x.Vertices[2].StartMarker - x.Vertices[0].StartMarker,
                        V1 = x.Vertices[1].StartMarker - x.Vertices[0].StartMarker
                    }).ToArray();
            }
            else
            {
                sourceTriangles = triangleMarkerSet.Triangles.Select(x => new SourceTriangle()
                    {
                        A = x.Vertices[0].EndMarker,
                        V0 = x.Vertices[2].EndMarker - x.Vertices[0].EndMarker,
                        V1 = x.Vertices[1].EndMarker - x.Vertices[0].EndMarker
                    }).ToArray();
            }

            // process pixel wise
            double xStep = 1.0 / outputImage.Width;
            Parallel.For(0, outputImage.Height, yi =>
            {
                Color* outputDataPixel = outputImage.Data + yi * outputImage.Width;
                Color* lastOutputDataPixel = outputDataPixel + outputImage.Width;
                double y = (double)yi / outputImage.Height;

                double u,v;
                double dot02, dot12;
                Vector v2;

                for (double x = 0; outputDataPixel != lastOutputDataPixel; x += xStep, ++outputDataPixel)
                {
                    Vector position = new Vector(x, y);

                    for (int triangleIdx = 0; triangleIdx < destTriangles.Length; ++triangleIdx)
                    {
                        // compute barycentric - http://www.blackpawn.com/texts/pointinpoly/
                        v2 = position - destTriangles[triangleIdx].A;

                        // Compute dot products
                        dot02 = VectorExtension.Dot(destTriangles[triangleIdx].V0, v2);
                        dot12 = VectorExtension.Dot(destTriangles[triangleIdx].V1, v2);

                        // Compute barycentric coordinates
                        u = (destTriangles[triangleIdx].V1DotV1_divDenom * dot02 - destTriangles[triangleIdx].V0DotV1_divDenom * dot12);
                        v = (destTriangles[triangleIdx].V0DotV0_divDenom * dot12 - destTriangles[triangleIdx].V0DotV1_divDenom * dot02);

                        // Check if point is in triangle
                        if ((u >= 0) && (v >= 0) && (u + v < 1))
                        {
                            position = sourceTriangles[triangleIdx].A + sourceTriangles[triangleIdx].V0 * u + sourceTriangles[triangleIdx].V1 * v;
                            break;
                        }
                    }
                    position = position.ClampToImageArea();
                    *outputDataPixel = inputImage.Sample(position.X, position.Y);
                }
            });
        }