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