public Maybe<Image> TryTransform()
        {
            try
            {
                using (var sourceLockbitImage = new WritableLockBitImage(_sourceImage))
                using (var outputLockbitImage = new WritableLockBitImage(_sourceImage.Width, _sourceImage.Height))
                {
                    // Get boxes
                    int index = 0;
                    foreach (int boxWidth in this.EnumerateBoxesForGauss(_radius, 3))
                    {
                        if (index % 2 == 0)
                        {
                            PerformSplitBoxBlurAcc(sourceLockbitImage, outputLockbitImage, (boxWidth - 1) / 2);
                        }
                        else
                        {
                            PerformSplitBoxBlurAcc(outputLockbitImage, sourceLockbitImage, (boxWidth - 1) / 2);
                        }
                        index++;
                    }

                    outputLockbitImage.Lock();
                    return outputLockbitImage.GetImage().ToMaybe();
                }
            }
            catch (Exception)
            {
            }

            return Maybe<Image>.Nothing;
        }
コード例 #2
0
 public static void CopyPixels(this IBoxBlur _, WritableLockBitImage sourceImage, WritableLockBitImage destImage)
 {
     for (int row = 0; row < sourceImage.Height; row++)
     {
         for (int col = 0; col < sourceImage.Width; col++)
         {
             destImage.SetPixel(col, row, sourceImage.GetPixel(col, row));
         }
     }
 }
        private static void PerformHorizontalBoxBlurAcc(WritableLockBitImage sourceImage, WritableLockBitImage outputImage, int radius)
        {
            double iarr = 1 / ((double)radius + radius + 1);
            for (int row = 0; row < sourceImage.Height; row++)
            {
                Color firstPixel = sourceImage.GetPixel(0, row);
                Color lastPixel = sourceImage.GetPixel(sourceImage.Width - 1, row);
                int cumRedValue = (radius + 1) * firstPixel.R;
                int cumGreenValue = (radius + 1) * firstPixel.G;
                int cumBlueValue = (radius + 1) * firstPixel.B;

                int currentLastColIndex = 0; // li
                int currentRadiusColIndex = radius; // ri

                for (int col = 0; col < radius; col++)
                {
                    Color chosenPixel = sourceImage.GetPixel(col, row);
                    cumRedValue += chosenPixel.R;
                    cumGreenValue += chosenPixel.G;
                    cumBlueValue += chosenPixel.B;
                }

                for (int col = 0; col <= radius; col++)
                {
                    Color chosenPixel = sourceImage.GetPixel(currentRadiusColIndex, row);
                    cumRedValue += chosenPixel.R - firstPixel.R;
                    cumGreenValue += chosenPixel.G - firstPixel.G;
                    cumBlueValue += chosenPixel.B - firstPixel.B;
                    currentRadiusColIndex++;

                    outputImage.SetPixel(
                        col,
                        row,
                        Color.FromArgb(
                            (int)Math.Round(cumRedValue * iarr),
                            (int)Math.Round(cumGreenValue * iarr),
                            (int)Math.Round(cumBlueValue * iarr)
                        )
                    );
                }

                for (int col = radius + 1; col < sourceImage.Width - radius; col++)
                {
                    Color chosenRadiusPixel = sourceImage.GetPixel(currentRadiusColIndex, row);
                    Color chosenLastPixel = sourceImage.GetPixel(currentLastColIndex, row);
                    cumRedValue += chosenRadiusPixel.R - chosenLastPixel.R;
                    cumGreenValue += chosenRadiusPixel.G - chosenLastPixel.G;
                    cumBlueValue += chosenRadiusPixel.B - chosenLastPixel.B;
                    currentRadiusColIndex++;
                    currentLastColIndex++;

                    outputImage.SetPixel(
                        col,
                        row,
                        Color.FromArgb(
                            (int)Math.Round(cumRedValue * iarr),
                            (int)Math.Round(cumGreenValue * iarr),
                            (int)Math.Round(cumBlueValue * iarr)
                        )
                    );
                }

                for (int col = sourceImage.Width - radius; col < sourceImage.Width; col++)
                {
                    Color chosenLastPixel = sourceImage.GetPixel(currentLastColIndex, row);
                    cumRedValue += lastPixel.R - chosenLastPixel.R;
                    cumGreenValue += lastPixel.G - chosenLastPixel.G;
                    cumBlueValue += lastPixel.B - chosenLastPixel.B;
                    currentLastColIndex++;

                    outputImage.SetPixel(
                        col,
                        row,
                        Color.FromArgb(
                            (int)Math.Round(cumRedValue * iarr),
                            (int)Math.Round(cumGreenValue * iarr),
                            (int)Math.Round(cumBlueValue * iarr)
                        )
                    );
                }
            }
        }
        private void PerformSplitBoxBlurAcc(WritableLockBitImage sourceImage, WritableLockBitImage outputImage, int radius)
        {
            // Copy pixels from source to output
            this.CopyPixels(sourceImage, outputImage);

            // The switching of outputImage and souceImage is INTENTIONAL!
            PerformHorizontalBoxBlurAcc(outputImage, sourceImage, radius);
            PerformTotalBoxBlurAcc(sourceImage, outputImage, radius);
        }
        private static void PerformTotalBoxBlurAcc(WritableLockBitImage sourceImage, WritableLockBitImage outputImage, int radius)
        {
            double iarr = 1 / ((double)radius + radius + 1);
            for (int col = 0; col < sourceImage.Width; col++)
            {
                Color topPixel = sourceImage.GetPixel(col, 0);
                Color bottomPixel = sourceImage.GetPixel(col, sourceImage.Height - 1);

                int cumRedValue = (radius + 1) * topPixel.R;
                int cumGreenValue = (radius + 1) * topPixel.G;
                int cumBlueValue = (radius + 1) * topPixel.B;

                for (int row = 0; row < radius; row++)
                {
                    Color chosenPixel = sourceImage.GetPixel(col, row);
                    cumRedValue += chosenPixel.R;
                    cumGreenValue += chosenPixel.G;
                    cumBlueValue += chosenPixel.B;
                }

                for (int row = 0; row <= radius; row++)
                {
                    Color chosenPixel = sourceImage.GetPixel(col, row + radius);
                    cumRedValue += chosenPixel.R - topPixel.R;
                    cumGreenValue += chosenPixel.G - topPixel.G;
                    cumBlueValue += chosenPixel.B - topPixel.B;

                    outputImage.SetPixel(
                        col,
                        row,
                        Color.FromArgb(
                            (int)Math.Round(cumRedValue * iarr),
                            (int)Math.Round(cumGreenValue * iarr),
                            (int)Math.Round(cumBlueValue * iarr)
                        )
                    );
                }

                for (int row = radius + 1; row < sourceImage.Height - radius; row++)
                {
                    Color radiusPixel = sourceImage.GetPixel(col, radius + row);
                    Color laggingPixel = sourceImage.GetPixel(col, row - radius - 1);
                    cumRedValue += radiusPixel.R - laggingPixel.R;
                    cumGreenValue += radiusPixel.G - laggingPixel.G;
                    cumBlueValue += radiusPixel.B - laggingPixel.B;

                    outputImage.SetPixel(
                        col,
                        row,
                        Color.FromArgb(
                            (int)Math.Round(cumRedValue * iarr),
                            (int)Math.Round(cumGreenValue * iarr),
                            (int)Math.Round(cumBlueValue * iarr)
                        )
                    );
                }

                for (int row = sourceImage.Height - radius; row < sourceImage.Height; row++)
                {
                    Color laggingPixel = sourceImage.GetPixel(col, row - radius);
                    cumRedValue += bottomPixel.R - laggingPixel.R;
                    cumGreenValue += bottomPixel.G - laggingPixel.G;
                    cumBlueValue += bottomPixel.B - laggingPixel.B;

                    outputImage.SetPixel(
                        col,
                        row,
                        Color.FromArgb(
                            (int)Math.Round(cumRedValue * iarr),
                            (int)Math.Round(cumGreenValue * iarr),
                            (int)Math.Round(cumBlueValue * iarr)
                        )
                    );
                }

            }
        }
 private static void PerformHorizontalBoxBlur(WritableLockBitImage sourceImage, WritableLockBitImage outputImage, int radius)
 {
     double valueDivisor = radius + radius + 1;
     for (int row = 0; row < sourceImage.Height; row++)
     {
         for (int col = 0; col < sourceImage.Width; col++)
         {
             int totalValueRed = 0, totalValueGreen = 0, totalValueBlue = 0;
             for (int colIndex = col - radius; colIndex < col + radius + 1; colIndex++)
             {
                 int chosenCol = Math.Min(sourceImage.Width - 1, Math.Max(0, colIndex));
                 Color chosenPixel = sourceImage.GetPixel(chosenCol, row);
                 totalValueRed += chosenPixel.R;
                 totalValueGreen += chosenPixel.G;
                 totalValueBlue += chosenPixel.B;
             }
             outputImage.SetPixel(col, row, Color.FromArgb(
                 (int)Math.Round(totalValueRed / valueDivisor),
                 (int)Math.Round(totalValueGreen / valueDivisor),
                 (int)Math.Round(totalValueBlue / valueDivisor)
             ));
         }
     }
 }
        private static void BoxBlurForGaussianBlurHelper(WritableLockBitImage inputImage, WritableLockBitImage outputImage, int radius)
        {
            double radiusDivisor = (radius + radius + 1) * (radius + radius + 1);
            for (int row = 0; row < inputImage.Height; row++)
            {
                for (int col = 0; col < inputImage.Width; col++)
                {
                    int cumulativeSourceRedValue = 0,
                        cumulativeSourceGreenValue = 0,
                        cumulativeSourceBlueValue = 0;
                    for (int rowIndex = row - radius; rowIndex < row + radius + 1; rowIndex++)
                    {
                        for (int colIndex = col - radius; colIndex < col + radius + 1; colIndex++)
                        {
                            int chosenRow = Math.Min(inputImage.Height - 1, Math.Max(0, rowIndex));
                            int chosenCol = Math.Min(inputImage.Width - 1, Math.Max(0, colIndex));

                            Color chosenPixel = inputImage.GetPixel(chosenCol, chosenRow);
                            cumulativeSourceRedValue += chosenPixel.R;
                            cumulativeSourceGreenValue += chosenPixel.G;
                            cumulativeSourceBlueValue += chosenPixel.B;
                        }
                    }

                    Color bluredColor = Color.FromArgb(
                        (int)Math.Round(cumulativeSourceRedValue / radiusDivisor),
                        (int)Math.Round(cumulativeSourceGreenValue / radiusDivisor),
                        (int)Math.Round(cumulativeSourceBlueValue / radiusDivisor)
                    );
                    outputImage.SetPixel(col, row, bluredColor);
                }
            }
        }
コード例 #8
0
        public Maybe<Image> TryTransform()
        {
            try
            {
                // Output color matrix
                using (var outputBitmap = new WritableLockBitImage(_sourceImage.Width, _sourceImage.Height))
                {
                    // Setting up some constants up here
                    double exponentDenominator = 2 * _radius * _radius;
                    double gaussianWeightDenominator = exponentDenominator * Math.PI;

                    int radiusEffectiveRange = (int)Math.Ceiling(_radius * GAUSSIAN_RADIUS_RANGE);
                    // Go through every single pixel
                    for (int row = 0; row < _sourceImage.Height; row++)
                    {
                        for (int col = 0; col < _sourceImage.Width; col++)
                        {
                            // Calculate the weighted sum of all of the neighboring pixels,
                            // governed by the radiusEffectiveRange variable above, and take
                            // the average value and then set it to the value of whatever
                            // pixel is at (row, col)
                            double neighborhoodRedPixelWeightedSum = 0,
                                neighborhoodGreenPixelWeightedSum = 0,
                                neighborhoodBluePixelWeightedSum = 0,
                                sumOfGaussianValues = 0;

                            for (
                                int neighboringPixelRow = row - radiusEffectiveRange;
                                neighboringPixelRow <= row + radiusEffectiveRange;
                                neighboringPixelRow++
                            )
                            {
                                for (
                                    int neighboringPixelCol = col - radiusEffectiveRange;
                                    neighboringPixelCol <= col + radiusEffectiveRange;
                                    neighboringPixelCol++
                                )
                                {
                                    // This is used so we don't try to get a pixel that's outside the boundaries
                                    // of the image (e.g. (-1, 0))
                                    int chosenRow = Math.Min(_sourceImage.Height - 1, Math.Max(0, neighboringPixelRow));
                                    int chosenCol = Math.Min(_sourceImage.Width - 1, Math.Max(0, neighboringPixelCol));

                                    // The Gaussian Formula is: (e ^ ((x^2 + y^2) / 2 * radius^2)) / (2 * PI * radius^2)
                                    // Here, x = col and y = row. We have to subtract the neighboringPixelCol/Row from
                                    // col/row so that we can translate the coordinate back to the origin. This is because
                                    // the gaussian function is expressed as a function from the distance from the origin
                                    double exponentNumerator = ((neighboringPixelCol - col) * (neighboringPixelCol - col)) +
                                        ((neighboringPixelRow - row) * (neighboringPixelRow - row));

                                    double gaussianWeight = Math.Exp(-exponentNumerator / exponentDenominator)
                                        / gaussianWeightDenominator;

                                    Color currentPixel = _sourceImage.GetPixel(chosenCol, chosenRow);
                                    neighborhoodRedPixelWeightedSum += currentPixel.R * gaussianWeight;
                                    neighborhoodGreenPixelWeightedSum += currentPixel.G * gaussianWeight;
                                    neighborhoodBluePixelWeightedSum += currentPixel.B * gaussianWeight;

                                    sumOfGaussianValues += gaussianWeight;
                                }
                            }
                            outputBitmap.SetPixel(col, row, Color.FromArgb(
                                (int)Math.Round(neighborhoodRedPixelWeightedSum / sumOfGaussianValues),
                                (int)Math.Round(neighborhoodGreenPixelWeightedSum / sumOfGaussianValues),
                                (int)Math.Round(neighborhoodBluePixelWeightedSum / sumOfGaussianValues)
                            ));
                        }
                    }
                    outputBitmap.Lock();
                    return outputBitmap.GetImage().ToMaybe<Image>();
                }
            }
            catch (Exception)
            {
            }

            return Maybe<Image>.Nothing;
        }