/// <summary> /// Post-processes the result bitmap /// </summary> /// <param name="resultBitmap">The result bitmap to post-process</param> /// <returns>The processed bitmap</returns> protected override Bitmap PostProcess(Bitmap resultBitmap) { StainedGlassParameters parameters = this.DynamicParameter; if (parameters.Edges) { return(resultBitmap.GradientBasedEdgeDetectionFilter(parameters.EdgesColor, parameters.EdgesThreshold)); } return(resultBitmap); }
/// <summary> /// Processes the image using a pixel buffer /// </summary> /// <param name="pixelBuffer">The pixel buffer to use</param> /// <param name="sourceWidth">The source image width</param> /// <param name="sourceHeight">The source image height</param> /// <param name="sourceStride">The source data stride</param> /// <returns>The processed pixel buffer</returns> protected override byte[] Process(byte[] pixelBuffer, int sourceWidth, int sourceHeight, int sourceStride) { StainedGlassParameters parameters = this.DynamicParameter; byte[] resultBuffer = new byte[sourceStride * sourceHeight]; int neighbourHoodTotal = 0; int sourceOffset = 0; int resultOffset = 0; int currentPixelDistance = 0; int nearestPixelDistance = 0; int nearesttPointIndex = 0; Random randomizer = new Random(); List <VoronoiPoint> randomPointList = new List <VoronoiPoint>(); int blockSize = parameters.Size; for (int row = 0; row < sourceHeight - blockSize; row += blockSize) { for (int col = 0; col < sourceWidth - blockSize; col += blockSize) { sourceOffset = (row * sourceStride) + (col * 4); neighbourHoodTotal = 0; for (int y = 0; y < blockSize; y++) { for (int x = 0; x < blockSize; x++) { resultOffset = sourceOffset + (y * sourceStride) + (x * 4); neighbourHoodTotal += pixelBuffer[resultOffset]; neighbourHoodTotal += pixelBuffer[resultOffset + 1]; neighbourHoodTotal += pixelBuffer[resultOffset + 2]; } } randomizer = new Random(neighbourHoodTotal); VoronoiPoint randomPoint = new VoronoiPoint(); randomPoint.XOffset = randomizer.Next(0, blockSize) + col; randomPoint.YOffset = randomizer.Next(0, blockSize) + row; randomPointList.Add(randomPoint); } } int rowOffset = 0; int colOffset = 0; for (int bufferOffset = 0; bufferOffset < pixelBuffer.Length - 4; bufferOffset += 4) { rowOffset = bufferOffset / sourceStride; colOffset = (bufferOffset % sourceStride) / 4; currentPixelDistance = 0; nearestPixelDistance = blockSize * 4; nearesttPointIndex = 0; List <VoronoiPoint> pointSubset = new List <VoronoiPoint>(); pointSubset.AddRange(from t in randomPointList where rowOffset >= t.YOffset - (blockSize * 2) && rowOffset <= t.YOffset + (blockSize * 2) select t); for (int k = 0; k < pointSubset.Count; k++) { if (parameters.DistanceFormula == StainedGlassParameters.Formula.Euclidean) { currentPixelDistance = CalculateDistanceEuclidean(pointSubset[k].XOffset, colOffset, pointSubset[k].YOffset, rowOffset); } else if (parameters.DistanceFormula == StainedGlassParameters.Formula.Manhattan) { currentPixelDistance = CalculateDistanceManhattan(pointSubset[k].XOffset, colOffset, pointSubset[k].YOffset, rowOffset); } else if (parameters.DistanceFormula == StainedGlassParameters.Formula.Chebyshev) { currentPixelDistance = CalculateDistanceChebyshev(pointSubset[k].XOffset, colOffset, pointSubset[k].YOffset, rowOffset); } if (currentPixelDistance <= nearestPixelDistance) { nearestPixelDistance = currentPixelDistance; nearesttPointIndex = k; if (nearestPixelDistance <= blockSize / parameters.Factor) { break; } } } Pixel tmpPixel = new Pixel(); tmpPixel.XOffset = colOffset; tmpPixel.YOffset = rowOffset; tmpPixel.Blue = pixelBuffer[bufferOffset]; tmpPixel.Green = pixelBuffer[bufferOffset + 1]; tmpPixel.Red = pixelBuffer[bufferOffset + 2]; pointSubset[nearesttPointIndex].AddPixel(tmpPixel); } for (int k = 0; k < randomPointList.Count; k++) { randomPointList[k].CalculateAverages(); for (int i = 0; i < randomPointList[k].PixelCollection.Count; i++) { resultOffset = (randomPointList[k].PixelCollection[i].YOffset * sourceStride) + (randomPointList[k].PixelCollection[i].XOffset * 4); resultBuffer[resultOffset] = (byte)randomPointList[k].BlueAverage; resultBuffer[resultOffset + 1] = (byte)randomPointList[k].GreenAverage; resultBuffer[resultOffset + 2] = (byte)randomPointList[k].RedAverage; resultBuffer[resultOffset + 3] = 255; } } return(resultBuffer); }