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; }
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; }