private void GenerateElasticPixels <TColor>( int kernelSize, double sigma, double alpha, Span <TColor> sourcePixels, Span <TColor> destPixels, int width, int height, Vector2[] facePointsSource, Vector2[] facePointsDest) where TColor : struct, IPixel <TColor> { //var length = width * height; double[] kernel = GeometryHelpers.Create2Dgaussian(kernelSize, sigma); double[] displacementX = ArrayPoolManager.DoubleArrayPool.Rent(width * height).Random(-1, 1).Multiply(alpha).Convolve(width, height, kernel, kernelSize); double[] displacementY = ArrayPoolManager.DoubleArrayPool.Rent(width * height).Random(-1, 1).Multiply(alpha).Convolve(width, height, kernel, kernelSize); //double[,] displacementX = new double[width, height]; //double[,] displacementY = new double[width, height]; double[] distances = ArrayPoolManager.DoubleArrayPool.Rent(facePointsSource.Length); for (int i = 0; i < facePointsSource.Length; i++) { distances[i] = double.MaxValue; } try { //displacementX = displacementX.Random(-1, 1).Multiply(alpha).Convolve(kernel); //displacementY = displacementY.Random(-1, 1).Multiply(alpha).Convolve(kernel); Parallel.For(0, width, Bootstrapper.Instance.MaxDegreeOfParalelism, xDest => { for (int yDest = 0; yDest < height; yDest++) { var position = xDest + yDest * width; double xOrg = xDest + displacementX[position]; double yOrg = yDest + displacementY[position]; SetNearest(facePointsSource, facePointsDest, distances, xOrg, yOrg); int xI1 = (int)Math.Floor(xOrg); int xI2 = (int)Math.Ceiling(xOrg); int yI1 = (int)Math.Floor(yOrg); int yI2 = (int)Math.Ceiling(yOrg); int xOrgI1 = xI1.ClampDown(0).ClampUp(width - 1); int xOrgI2 = xI2.ClampDown(0).ClampUp(width - 1); int yOrgI1 = yI1.ClampDown(0).ClampUp(height - 1); int yOrgI2 = yI2.ClampDown(0).ClampUp(height - 1); TColor colorPosI1 = sourcePixels[xOrgI1 + yOrgI1 * width]; TColor colorPosI2 = sourcePixels[xOrgI2 + yOrgI1 * width]; TColor colorPosI3 = sourcePixels[xOrgI1 + yOrgI2 * width]; TColor colorPosI4 = sourcePixels[xOrgI2 + yOrgI2 * width]; var colorPosI1Vector = colorPosI1.ToVector4(); var colorPosI2Vector = colorPosI2.ToVector4(); var colorPosI3Vector = colorPosI3.ToVector4(); var colorPosI4Vector = colorPosI4.ToVector4(); var rgbVector = new Vector4(); rgbVector.X = Interpolate(xOrg, yOrg, xI1, xI2, yI1, yI2, colorPosI1Vector.X, colorPosI2Vector.X, colorPosI3Vector.X, colorPosI4Vector.X); rgbVector.Y = Interpolate(xOrg, yOrg, xI1, xI2, yI1, yI2, colorPosI1Vector.Y, colorPosI2Vector.Y, colorPosI3Vector.Y, colorPosI4Vector.Y); rgbVector.Z = Interpolate(xOrg, yOrg, xI1, xI2, yI1, yI2, colorPosI1Vector.Z, colorPosI2Vector.Z, colorPosI3Vector.Z, colorPosI4Vector.Z); rgbVector.W = 255; TColor newColor = new TColor(); newColor.PackFromVector4(rgbVector); destPixels[xDest + yDest * width] = newColor; } }); } finally { ArrayPoolManager.DoubleArrayPool.Return(displacementX); ArrayPoolManager.DoubleArrayPool.Return(displacementY); ArrayPoolManager.DoubleArrayPool.Return(distances); } }