/// <summary> /// Processes the image. /// </summary> /// <param name="factory"> /// The current instance of the <see cref="T:ImageProcessor.ImageFactory"/> class containing /// the image to process. /// </param> /// <returns> /// The processed image from the current instance of the <see cref="T:ImageProcessor.ImageFactory"/> class. /// </returns> public Image ProcessImage(ImageFactory factory) { Bitmap newImage = null; Image image = factory.Image; try { Tuple <Color, Color, int> parameters = this.DynamicParameter; Color original = parameters.Item1; Color replacement = parameters.Item2; byte originalR = original.R; byte originalG = original.G; byte originalB = original.B; byte originalA = original.A; byte replacementR = replacement.R; byte replacementG = replacement.G; byte replacementB = replacement.B; byte replacementA = replacement.A; int fuzziness = parameters.Item3; byte minR = (originalR - fuzziness).ToByte(); byte minG = (originalG - fuzziness).ToByte(); byte minB = (originalB - fuzziness).ToByte(); byte maxR = (originalR + fuzziness).ToByte(); byte maxG = (originalG + fuzziness).ToByte(); byte maxB = (originalB + fuzziness).ToByte(); newImage = new Bitmap(image); newImage.SetResolution(image.HorizontalResolution, image.VerticalResolution); int width = image.Width; int height = image.Height; using (FastBitmap fastBitmap = new FastBitmap(newImage)) { Parallel.For( 0, height, y => { for (int x = 0; x < width; x++) { // Get the pixel color. // ReSharper disable once AccessToDisposedClosure Color currentColor = fastBitmap.GetPixel(x, y); byte currentR = currentColor.R; byte currentG = currentColor.G; byte currentB = currentColor.B; byte currentA = currentColor.A; // Test whether it is in the expected range. if (ImageMaths.InRange(currentR, minR, maxR)) { if (ImageMaths.InRange(currentG, minG, maxG)) { if (ImageMaths.InRange(currentB, minB, maxB)) { // Ensure the values are within an acceptable byte range // and set the new value. byte r = (originalR - currentR + replacementR).ToByte(); byte g = (originalG - currentG + replacementG).ToByte(); byte b = (originalB - currentB + replacementB).ToByte(); // Allow replacement with transparent color. byte a = currentA; if (originalA != replacementA) { a = replacementA; } // ReSharper disable once AccessToDisposedClosure fastBitmap.SetPixel(x, y, Color.FromArgb(a, r, g, b)); } } } } }); } image.Dispose(); image = newImage; } catch (Exception ex) { newImage?.Dispose(); throw new ImageProcessingException("Error processing image with " + this.GetType().Name, ex); } return(image); }