diff --git a/src/ImageProcessor/Filters/ImageFilterExtensions.cs b/src/ImageProcessor/Filters/ImageFilterExtensions.cs
index 83d0edaa0..2690188ab 100644
--- a/src/ImageProcessor/Filters/ImageFilterExtensions.cs
+++ b/src/ImageProcessor/Filters/ImageFilterExtensions.cs
@@ -15,10 +15,11 @@ namespace ImageProcessor.Filters
///
/// The image this method extends.
/// The new opacity of the image. Must be between 0 and 100.
+ /// A delegate which is called as progress is made processing the image.
/// The .
- public static Image Alpha(this Image source, int percent)
+ public static Image Alpha(this Image source, int percent, ProgressEventHandler progressHandler = null)
{
- return Alpha(source, percent, source.Bounds);
+ return Alpha(source, percent, source.Bounds, progressHandler);
}
///
@@ -29,10 +30,21 @@ namespace ImageProcessor.Filters
///
/// The structure that specifies the portion of the image object to alter.
///
+ /// A delegate which is called as progress is made processing the image.
/// The .
- public static Image Alpha(this Image source, int percent, Rectangle rectangle)
+ public static Image Alpha(this Image source, int percent, Rectangle rectangle, ProgressEventHandler progressHandler = null)
{
- return source.Process(rectangle, new Alpha(percent));
+ Alpha processor = new Alpha(percent);
+ processor.OnProgress += progressHandler;
+
+ try
+ {
+ return source.Process(rectangle, processor);
+ }
+ finally
+ {
+ processor.OnProgress -= progressHandler;
+ }
}
///
@@ -40,10 +52,21 @@ namespace ImageProcessor.Filters
///
/// The image this method extends.
/// The color to set as the background.
+ /// A delegate which is called as progress is made processing the image.
/// The .
- public static Image BackgroundColor(this Image source, Color color)
+ public static Image BackgroundColor(this Image source, Color color, ProgressEventHandler progressHandler = null)
{
- return source.Process(source.Bounds, new BackgroundColor(color));
+ BackgroundColor processor = new BackgroundColor(color);
+ processor.OnProgress += progressHandler;
+
+ try
+ {
+ return source.Process(source.Bounds, processor);
+ }
+ finally
+ {
+ processor.OnProgress -= progressHandler;
+ }
}
///
@@ -52,10 +75,11 @@ namespace ImageProcessor.Filters
/// The image this method extends.
/// The image to blend with the currently processing image.
/// The opacity of the image image to blend. Must be between 0 and 100.
+ /// A delegate which is called as progress is made processing the image.
/// The .
- public static Image Blend(this Image source, ImageBase image, int percent = 50)
+ public static Image Blend(this Image source, ImageBase image, int percent = 50, ProgressEventHandler progressHandler = null)
{
- return source.Process(source.Bounds, new Blend(image, percent));
+ return Blend(source, image, percent, source.Bounds, progressHandler);
}
///
@@ -67,20 +91,32 @@ namespace ImageProcessor.Filters
///
/// The structure that specifies the portion of the image object to alter.
///
+ /// A delegate which is called as progress is made processing the image.
/// The .
- public static Image Blend(this Image source, ImageBase image, int percent, Rectangle rectangle)
+ public static Image Blend(this Image source, ImageBase image, int percent, Rectangle rectangle, ProgressEventHandler progressHandler = null)
{
- return source.Process(rectangle, new Blend(image, percent));
+ Blend processor = new Blend(image, percent);
+ processor.OnProgress += progressHandler;
+
+ try
+ {
+ return source.Process(rectangle, processor);
+ }
+ finally
+ {
+ processor.OnProgress -= progressHandler;
+ }
}
///
/// Applies black and white toning to the image.
///
/// The image this method extends.
+ /// A delegate which is called as progress is made processing the image.
/// The .
- public static Image BlackWhite(this Image source)
+ public static Image BlackWhite(this Image source, ProgressEventHandler progressHandler = null)
{
- return BlackWhite(source, source.Bounds);
+ return BlackWhite(source, source.Bounds, progressHandler);
}
///
@@ -90,10 +126,21 @@ namespace ImageProcessor.Filters
///
/// The structure that specifies the portion of the image object to alter.
///
+ /// A delegate which is called as progress is made processing the image.
/// The .
- public static Image BlackWhite(this Image source, Rectangle rectangle)
+ public static Image BlackWhite(this Image source, Rectangle rectangle, ProgressEventHandler progressHandler = null)
{
- return source.Process(rectangle, new BlackWhite());
+ BlackWhite processor = new BlackWhite();
+ processor.OnProgress += progressHandler;
+
+ try
+ {
+ return source.Process(rectangle, processor);
+ }
+ finally
+ {
+ processor.OnProgress -= progressHandler;
+ }
}
///
@@ -101,10 +148,11 @@ namespace ImageProcessor.Filters
///
/// The image this method extends.
/// The 'radius' value representing the size of the area to sample.
+ /// A delegate which is called as progress is made processing the image.
/// The .
- public static Image BoxBlur(this Image source, int radius = 7)
+ public static Image BoxBlur(this Image source, int radius = 7, ProgressEventHandler progressHandler = null)
{
- return BoxBlur(source, radius, source.Bounds);
+ return BoxBlur(source, radius, source.Bounds, progressHandler);
}
///
@@ -115,10 +163,21 @@ namespace ImageProcessor.Filters
///
/// The structure that specifies the portion of the image object to alter.
///
+ /// A delegate which is called as progress is made processing the image.
/// The .
- public static Image BoxBlur(this Image source, int radius, Rectangle rectangle)
+ public static Image BoxBlur(this Image source, int radius, Rectangle rectangle, ProgressEventHandler progressHandler = null)
{
- return source.Process(rectangle, new BoxBlur(radius));
+ BoxBlur processor = new BoxBlur(radius);
+ processor.OnProgress += progressHandler;
+
+ try
+ {
+ return source.Process(rectangle, processor);
+ }
+ finally
+ {
+ processor.OnProgress -= progressHandler;
+ }
}
///
@@ -126,10 +185,11 @@ namespace ImageProcessor.Filters
///
/// The image this method extends.
/// The new brightness of the image. Must be between -100 and 100.
+ /// A delegate which is called as progress is made processing the image.
/// The .
- public static Image Brightness(this Image source, int amount)
+ public static Image Brightness(this Image source, int amount, ProgressEventHandler progressHandler = null)
{
- return Brightness(source, amount, source.Bounds);
+ return Brightness(source, amount, source.Bounds, progressHandler);
}
///
@@ -140,10 +200,21 @@ namespace ImageProcessor.Filters
///
/// The structure that specifies the portion of the image object to alter.
///
+ /// A delegate which is called as progress is made processing the image.
/// The .
- public static Image Brightness(this Image source, int amount, Rectangle rectangle)
+ public static Image Brightness(this Image source, int amount, Rectangle rectangle, ProgressEventHandler progressHandler = null)
{
- return source.Process(rectangle, new Brightness(amount));
+ Brightness processor = new Brightness(amount);
+ processor.OnProgress += progressHandler;
+
+ try
+ {
+ return source.Process(rectangle, processor);
+ }
+ finally
+ {
+ processor.OnProgress -= progressHandler;
+ }
}
///
@@ -151,10 +222,11 @@ namespace ImageProcessor.Filters
///
/// The image this method extends.
/// The new contrast of the image. Must be between -100 and 100.
+ /// A delegate which is called as progress is made processing the image.
/// The .
- public static Image Contrast(this Image source, int amount)
+ public static Image Contrast(this Image source, int amount, ProgressEventHandler progressHandler = null)
{
- return Contrast(source, amount, source.Bounds);
+ return Contrast(source, amount, source.Bounds, progressHandler);
}
///
@@ -165,10 +237,21 @@ namespace ImageProcessor.Filters
///
/// The structure that specifies the portion of the image object to alter.
///
+ /// A delegate which is called as progress is made processing the image.
/// The .
- public static Image Contrast(this Image source, int amount, Rectangle rectangle)
+ public static Image Contrast(this Image source, int amount, Rectangle rectangle, ProgressEventHandler progressHandler = null)
{
- return source.Process(rectangle, new Contrast(amount));
+ Contrast processor = new Contrast(amount);
+ processor.OnProgress += progressHandler;
+
+ try
+ {
+ return source.Process(rectangle, processor);
+ }
+ finally
+ {
+ processor.OnProgress -= progressHandler;
+ }
}
///
@@ -176,10 +259,11 @@ namespace ImageProcessor.Filters
/// operating in greyscale mode.
///
/// The image this method extends.
+ /// A delegate which is called as progress is made processing the image.
/// The .
- public static Image DetectEdges(this Image source)
+ public static Image DetectEdges(this Image source, ProgressEventHandler progressHandler = null)
{
- return DetectEdges(source, source.Bounds, new Sobel { Greyscale = true });
+ return DetectEdges(source, source.Bounds, new Sobel { Greyscale = true }, progressHandler);
}
///
@@ -187,10 +271,11 @@ namespace ImageProcessor.Filters
///
/// The image this method extends.
/// The filter for detecting edges.
+ /// A delegate which is called as progress is made processing the image.
/// The .
- public static Image DetectEdges(this Image source, IEdgeDetectorFilter filter)
+ public static Image DetectEdges(this Image source, IEdgeDetectorFilter filter, ProgressEventHandler progressHandler = null)
{
- return DetectEdges(source, source.Bounds, filter);
+ return DetectEdges(source, source.Bounds, filter, progressHandler);
}
///
@@ -201,10 +286,20 @@ namespace ImageProcessor.Filters
/// The structure that specifies the portion of the image object to alter.
///
/// The filter for detecting edges.
+ /// A delegate which is called as progress is made processing the image.
/// The .
- public static Image DetectEdges(this Image source, Rectangle rectangle, IEdgeDetectorFilter filter)
+ public static Image DetectEdges(this Image source, Rectangle rectangle, IEdgeDetectorFilter filter, ProgressEventHandler progressHandler = null)
{
- return source.Process(rectangle, filter);
+ filter.OnProgress += progressHandler;
+
+ try
+ {
+ return source.Process(rectangle, filter);
+ }
+ finally
+ {
+ filter.OnProgress -= progressHandler;
+ }
}
///
@@ -212,10 +307,11 @@ namespace ImageProcessor.Filters
///
/// The image this method extends.
/// The formula to apply to perform the operation.
+ /// A delegate which is called as progress is made processing the image.
/// The .
- public static Image Greyscale(this Image source, GreyscaleMode mode = GreyscaleMode.Bt709)
+ public static Image Greyscale(this Image source, GreyscaleMode mode = GreyscaleMode.Bt709, ProgressEventHandler progressHandler = null)
{
- return Greyscale(source, source.Bounds, mode);
+ return Greyscale(source, source.Bounds, mode, progressHandler);
}
///
@@ -226,12 +322,24 @@ namespace ImageProcessor.Filters
/// The structure that specifies the portion of the image object to alter.
///
/// The formula to apply to perform the operation.
+ /// A delegate which is called as progress is made processing the image.
/// The .
- public static Image Greyscale(this Image source, Rectangle rectangle, GreyscaleMode mode = GreyscaleMode.Bt709)
+ public static Image Greyscale(this Image source, Rectangle rectangle, GreyscaleMode mode = GreyscaleMode.Bt709, ProgressEventHandler progressHandler = null)
{
- return mode == GreyscaleMode.Bt709
- ? source.Process(rectangle, new GreyscaleBt709())
- : source.Process(rectangle, new GreyscaleBt601());
+ IImageProcessor processor = mode == GreyscaleMode.Bt709
+ ? (IImageProcessor)new GreyscaleBt709()
+ : new GreyscaleBt601();
+
+ processor.OnProgress += progressHandler;
+
+ try
+ {
+ return source.Process(rectangle, processor);
+ }
+ finally
+ {
+ processor.OnProgress -= progressHandler;
+ }
}
///
@@ -239,10 +347,11 @@ namespace ImageProcessor.Filters
///
/// The image this method extends.
/// The 'sigma' value representing the weight of the blur.
+ /// A delegate which is called as progress is made processing the image.
/// The .
- public static Image GuassianBlur(this Image source, float sigma = 3f)
+ public static Image GuassianBlur(this Image source, float sigma = 3f, ProgressEventHandler progressHandler = null)
{
- return GuassianBlur(source, sigma, source.Bounds);
+ return GuassianBlur(source, sigma, source.Bounds, progressHandler);
}
///
@@ -253,10 +362,21 @@ namespace ImageProcessor.Filters
///
/// The structure that specifies the portion of the image object to alter.
///
+ /// A delegate which is called as progress is made processing the image.
/// The .
- public static Image GuassianBlur(this Image source, float sigma, Rectangle rectangle)
+ public static Image GuassianBlur(this Image source, float sigma, Rectangle rectangle, ProgressEventHandler progressHandler = null)
{
- return source.Process(rectangle, new GuassianBlur(sigma));
+ GuassianBlur processor = new GuassianBlur(sigma);
+ processor.OnProgress += progressHandler;
+
+ try
+ {
+ return source.Process(rectangle, processor);
+ }
+ finally
+ {
+ processor.OnProgress -= progressHandler;
+ }
}
///
@@ -264,10 +384,11 @@ namespace ImageProcessor.Filters
///
/// The image this method extends.
/// The 'sigma' value representing the weight of the blur.
+ /// A delegate which is called as progress is made processing the image.
/// The .
- public static Image GuassianSharpen(this Image source, float sigma = 3f)
+ public static Image GuassianSharpen(this Image source, float sigma = 3f, ProgressEventHandler progressHandler = null)
{
- return GuassianSharpen(source, sigma, source.Bounds);
+ return GuassianSharpen(source, sigma, source.Bounds, progressHandler);
}
///
@@ -278,10 +399,21 @@ namespace ImageProcessor.Filters
///
/// The structure that specifies the portion of the image object to alter.
///
+ /// A delegate which is called as progress is made processing the image.
/// The .
- public static Image GuassianSharpen(this Image source, float sigma, Rectangle rectangle)
+ public static Image GuassianSharpen(this Image source, float sigma, Rectangle rectangle, ProgressEventHandler progressHandler = null)
{
- return source.Process(rectangle, new GuassianSharpen(sigma));
+ GuassianSharpen processor = new GuassianSharpen(sigma);
+ processor.OnProgress += progressHandler;
+
+ try
+ {
+ return source.Process(rectangle, processor);
+ }
+ finally
+ {
+ processor.OnProgress -= progressHandler;
+ }
}
///
@@ -289,10 +421,11 @@ namespace ImageProcessor.Filters
///
/// The image this method extends.
/// The angle in degrees to adjust the image.
+ /// A delegate which is called as progress is made processing the image.
/// The .
- public static Image Hue(this Image source, float degrees)
+ public static Image Hue(this Image source, float degrees, ProgressEventHandler progressHandler = null)
{
- return Hue(source, degrees, source.Bounds);
+ return Hue(source, degrees, source.Bounds, progressHandler);
}
///
@@ -303,20 +436,32 @@ namespace ImageProcessor.Filters
///
/// The structure that specifies the portion of the image object to alter.
///
+ /// A delegate which is called as progress is made processing the image.
/// The .
- public static Image Hue(this Image source, float degrees, Rectangle rectangle)
+ public static Image Hue(this Image source, float degrees, Rectangle rectangle, ProgressEventHandler progressHandler = null)
{
- return source.Process(rectangle, new Hue(degrees));
+ Hue processor = new Hue(degrees);
+ processor.OnProgress += progressHandler;
+
+ try
+ {
+ return source.Process(rectangle, processor);
+ }
+ finally
+ {
+ processor.OnProgress -= progressHandler;
+ }
}
///
/// Inverts the colors of the image.
///
/// The image this method extends.
+ /// A delegate which is called as progress is made processing the image.
/// The .
- public static Image Invert(this Image source)
+ public static Image Invert(this Image source, ProgressEventHandler progressHandler = null)
{
- return Invert(source, source.Bounds);
+ return Invert(source, source.Bounds, progressHandler);
}
///
@@ -326,20 +471,32 @@ namespace ImageProcessor.Filters
///
/// The structure that specifies the portion of the image object to alter.
///
+ /// A delegate which is called as progress is made processing the image.
/// The .
- public static Image Invert(this Image source, Rectangle rectangle)
+ public static Image Invert(this Image source, Rectangle rectangle, ProgressEventHandler progressHandler = null)
{
- return source.Process(rectangle, new Invert());
+ Invert processor = new Invert();
+ processor.OnProgress += progressHandler;
+
+ try
+ {
+ return source.Process(rectangle, processor);
+ }
+ finally
+ {
+ processor.OnProgress -= progressHandler;
+ }
}
///
/// Alters the colors of the image recreating an old Kodachrome camera effect.
///
/// The image this method extends.
+ /// A delegate which is called as progress is made processing the image.
/// The .
- public static Image Kodachrome(this Image source)
+ public static Image Kodachrome(this Image source, ProgressEventHandler progressHandler = null)
{
- return Kodachrome(source, source.Bounds);
+ return Kodachrome(source, source.Bounds, progressHandler);
}
///
@@ -349,20 +506,32 @@ namespace ImageProcessor.Filters
///
/// The structure that specifies the portion of the image object to alter.
///
+ /// A delegate which is called as progress is made processing the image.
/// The .
- public static Image Kodachrome(this Image source, Rectangle rectangle)
+ public static Image Kodachrome(this Image source, Rectangle rectangle, ProgressEventHandler progressHandler = null)
{
- return source.Process(rectangle, new Kodachrome());
+ Kodachrome processor = new Kodachrome();
+ processor.OnProgress += progressHandler;
+
+ try
+ {
+ return source.Process(rectangle, processor);
+ }
+ finally
+ {
+ processor.OnProgress -= progressHandler;
+ }
}
///
/// Alters the colors of the image recreating an old Lomograph camera effect.
///
/// The image this method extends.
+ /// A delegate which is called as progress is made processing the image.
/// The .
- public static Image Lomograph(this Image source)
+ public static Image Lomograph(this Image source, ProgressEventHandler progressHandler = null)
{
- return Lomograph(source, source.Bounds);
+ return Lomograph(source, source.Bounds, progressHandler);
}
///
@@ -372,20 +541,32 @@ namespace ImageProcessor.Filters
///
/// The structure that specifies the portion of the image object to alter.
///
+ /// A delegate which is called as progress is made processing the image.
/// The .
- public static Image Lomograph(this Image source, Rectangle rectangle)
+ public static Image Lomograph(this Image source, Rectangle rectangle, ProgressEventHandler progressHandler = null)
{
- return source.Process(rectangle, new Lomograph());
+ Lomograph processor = new Lomograph();
+ processor.OnProgress += progressHandler;
+
+ try
+ {
+ return source.Process(rectangle, processor);
+ }
+ finally
+ {
+ processor.OnProgress -= progressHandler;
+ }
}
///
/// Alters the colors of the image recreating an old Polaroid camera effect.
///
/// The image this method extends.
+ /// A delegate which is called as progress is made processing the image.
/// The .
- public static Image Polaroid(this Image source)
+ public static Image Polaroid(this Image source, ProgressEventHandler progressHandler = null)
{
- return Polaroid(source, source.Bounds);
+ return Polaroid(source, source.Bounds, progressHandler);
}
///
@@ -395,10 +576,21 @@ namespace ImageProcessor.Filters
///
/// The structure that specifies the portion of the image object to alter.
///
+ /// A delegate which is called as progress is made processing the image.
/// The .
- public static Image Polaroid(this Image source, Rectangle rectangle)
+ public static Image Polaroid(this Image source, Rectangle rectangle, ProgressEventHandler progressHandler = null)
{
- return source.Process(rectangle, new Polaroid());
+ Polaroid processor = new Polaroid();
+ processor.OnProgress += progressHandler;
+
+ try
+ {
+ return source.Process(rectangle, processor);
+ }
+ finally
+ {
+ processor.OnProgress -= progressHandler;
+ }
}
///
@@ -406,10 +598,11 @@ namespace ImageProcessor.Filters
///
/// The image this method extends.
/// The size of the pixels.
+ /// A delegate which is called as progress is made processing the image.
/// The .
- public static Image Pixelate(this Image source, int size = 4)
+ public static Image Pixelate(this Image source, int size = 4, ProgressEventHandler progressHandler = null)
{
- return source.Process(source.Bounds, new Pixelate(size));
+ return Pixelate(source, size, source.Bounds, progressHandler);
}
///
@@ -420,10 +613,21 @@ namespace ImageProcessor.Filters
///
/// The structure that specifies the portion of the image object to alter.
///
+ /// A delegate which is called as progress is made processing the image.
/// The .
- public static Image Pixelate(this Image source, int size, Rectangle rectangle)
+ public static Image Pixelate(this Image source, int size, Rectangle rectangle, ProgressEventHandler progressHandler = null)
{
- return source.Process(rectangle, new Pixelate(size));
+ Pixelate processor = new Pixelate(size);
+ processor.OnProgress += progressHandler;
+
+ try
+ {
+ return source.Process(rectangle, processor);
+ }
+ finally
+ {
+ processor.OnProgress -= progressHandler;
+ }
}
///
@@ -431,10 +635,11 @@ namespace ImageProcessor.Filters
///
/// The image this method extends.
/// The new saturation of the image. Must be between -100 and 100.
+ /// A delegate which is called as progress is made processing the image.
/// The .
- public static Image Saturation(this Image source, int amount)
+ public static Image Saturation(this Image source, int amount, ProgressEventHandler progressHandler = null)
{
- return Saturation(source, amount, source.Bounds);
+ return Saturation(source, amount, source.Bounds, progressHandler);
}
///
@@ -445,20 +650,32 @@ namespace ImageProcessor.Filters
///
/// The structure that specifies the portion of the image object to alter.
///
+ /// A delegate which is called as progress is made processing the image.
/// The .
- public static Image Saturation(this Image source, int amount, Rectangle rectangle)
+ public static Image Saturation(this Image source, int amount, Rectangle rectangle, ProgressEventHandler progressHandler = null)
{
- return source.Process(rectangle, new Saturation(amount));
+ Saturation processor = new Saturation(amount);
+ processor.OnProgress += progressHandler;
+
+ try
+ {
+ return source.Process(rectangle, processor);
+ }
+ finally
+ {
+ processor.OnProgress -= progressHandler;
+ }
}
///
/// Applies sepia toning to the image.
///
/// The image this method extends.
+ /// A delegate which is called as progress is made processing the image.
/// The .
- public static Image Sepia(this Image source)
+ public static Image Sepia(this Image source, ProgressEventHandler progressHandler = null)
{
- return Sepia(source, source.Bounds);
+ return Sepia(source, source.Bounds, progressHandler);
}
///
@@ -468,10 +685,21 @@ namespace ImageProcessor.Filters
///
/// The structure that specifies the portion of the image object to alter.
///
+ /// A delegate which is called as progress is made processing the image.
/// The .
- public static Image Sepia(this Image source, Rectangle rectangle)
+ public static Image Sepia(this Image source, Rectangle rectangle, ProgressEventHandler progressHandler = null)
{
- return source.Process(rectangle, new Sepia());
+ Sepia processor = new Sepia();
+ processor.OnProgress += progressHandler;
+
+ try
+ {
+ return source.Process(rectangle, processor);
+ }
+ finally
+ {
+ processor.OnProgress -= progressHandler;
+ }
}
}
}
diff --git a/src/ImageProcessor/IImageProcessor.cs b/src/ImageProcessor/IImageProcessor.cs
index 7f1a60e8d..eb24515c7 100644
--- a/src/ImageProcessor/IImageProcessor.cs
+++ b/src/ImageProcessor/IImageProcessor.cs
@@ -5,17 +5,11 @@
namespace ImageProcessor
{
- public class ProgressEventArgs : System.EventArgs
- {
- public int numRowsProcessed;
- public int totalRows;
- }
-
///
- /// A delegate which is called as progress is made processing the image.
+ /// A delegate which is called as progress is made processing an image.
///
- ///
- ///
+ /// The source of the event.
+ /// An object that contains the event data.
public delegate void ProgressEventHandler(object sender, ProgressEventArgs e);
///
diff --git a/src/ImageProcessor/ParallelImageProcessor.cs b/src/ImageProcessor/ParallelImageProcessor.cs
index b9a843f43..1380ab68b 100644
--- a/src/ImageProcessor/ParallelImageProcessor.cs
+++ b/src/ImageProcessor/ParallelImageProcessor.cs
@@ -32,24 +32,6 @@ namespace ImageProcessor
///
private int totalRows;
- ///
- /// Must be called by derived classes after processing a single row.
- ///
- protected void OnRowProcessed()
- {
- if(this.OnProgress != null)
- {
- int currThreadNumRows = Interlocked.Add(ref this.numRowsProcessed, 1);
-
- // Multi-pass filters process multiple times more rows than totalRows, so update totalRows on the fly
- if (currThreadNumRows > this.totalRows)
- this.totalRows = currThreadNumRows;
-
- // Report progress. This may be on the client's thread, or on a Task library thread.
- this.OnProgress(this, new ProgressEventArgs { numRowsProcessed = currThreadNumRows, totalRows = this.totalRows });
- }
- }
-
///
public void Apply(ImageBase target, ImageBase source, Rectangle sourceRectangle)
{
@@ -191,5 +173,25 @@ namespace ImageProcessor
protected virtual void AfterApply(ImageBase source, ImageBase target, Rectangle targetRectangle, Rectangle sourceRectangle)
{
}
+
+ ///
+ /// Must be called by derived classes after processing a single row.
+ ///
+ protected void OnRowProcessed()
+ {
+ if (this.OnProgress != null)
+ {
+ int currThreadNumRows = Interlocked.Add(ref this.numRowsProcessed, 1);
+
+ // Multi-pass filters process multiple times more rows than totalRows, so update totalRows on the fly
+ if (currThreadNumRows > this.totalRows)
+ {
+ this.totalRows = currThreadNumRows;
+ }
+
+ // Report progress. This may be on the client's thread, or on a Task library thread.
+ this.OnProgress(this, new ProgressEventArgs { RowsProcessed = currThreadNumRows, TotalRows = this.totalRows });
+ }
+ }
}
}
diff --git a/src/ImageProcessor/ProgressEventArgs.cs b/src/ImageProcessor/ProgressEventArgs.cs
new file mode 100644
index 000000000..ff62f3822
--- /dev/null
+++ b/src/ImageProcessor/ProgressEventArgs.cs
@@ -0,0 +1,23 @@
+//
+// Copyright (c) James Jackson-South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
+
+namespace ImageProcessor
+{
+ ///
+ /// Contains event data related to the progress made processing an image.
+ ///
+ public class ProgressEventArgs : System.EventArgs
+ {
+ ///
+ /// Gets or sets the number of rows processed.
+ ///
+ public int RowsProcessed { get; set; }
+
+ ///
+ /// Gets or sets the total number of rows.
+ ///
+ public int TotalRows { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/ImageProcessor/Samplers/ImageSampleExtensions.cs b/src/ImageProcessor/Samplers/ImageSampleExtensions.cs
index b00775335..1c0b34bee 100644
--- a/src/ImageProcessor/Samplers/ImageSampleExtensions.cs
+++ b/src/ImageProcessor/Samplers/ImageSampleExtensions.cs
@@ -47,8 +47,9 @@ namespace ImageProcessor.Samplers
source = source.Resize(sourceRectangle.Width, sourceRectangle.Height);
}
- var processor = new Crop();
+ Crop processor = new Crop();
processor.OnProgress += progressHandler;
+
try
{
return source.Process(width, height, sourceRectangle, new Rectangle(0, 0, width, height), processor);
@@ -68,8 +69,9 @@ namespace ImageProcessor.Samplers
/// The
public static Image EntropyCrop(this Image source, float threshold = .5f, ProgressEventHandler progressHandler = null)
{
- var processor = new EntropyCrop(threshold);
+ EntropyCrop processor = new EntropyCrop(threshold);
processor.OnProgress += progressHandler;
+
try
{
return source.Process(source.Width, source.Height, source.Bounds, source.Bounds, processor);
@@ -135,8 +137,9 @@ namespace ImageProcessor.Samplers
height = source.Height * width / source.Width;
}
- var processor = new Resize(sampler);
+ Resize processor = new Resize(sampler);
processor.OnProgress += progressHandler;
+
try
{
return source.Process(width, height, sourceRectangle, new Rectangle(0, 0, width, height), processor);
@@ -169,8 +172,9 @@ namespace ImageProcessor.Samplers
/// The
public static Image Rotate(this Image source, float degrees, IResampler sampler, ProgressEventHandler progressHandler = null)
{
- var processor = new Rotate(sampler) { Angle = degrees };
+ Rotate processor = new Rotate(sampler) { Angle = degrees };
processor.OnProgress += progressHandler;
+
try
{
return source.Process(source.Width, source.Height, source.Bounds, source.Bounds, processor);
@@ -191,8 +195,9 @@ namespace ImageProcessor.Samplers
/// The
public static Image RotateFlip(this Image source, RotateType rotateType, FlipType flipType, ProgressEventHandler progressHandler = null)
{
- var processor = new RotateFlip(rotateType, flipType);
+ RotateFlip processor = new RotateFlip(rotateType, flipType);
processor.OnProgress += progressHandler;
+
try
{
return source.Process(source.Width, source.Height, source.Bounds, source.Bounds, processor);
diff --git a/tests/ImageProcessor.Tests/Processors/Filters/FilterTests.cs b/tests/ImageProcessor.Tests/Processors/Filters/FilterTests.cs
index 4414d79bf..8335d8024 100644
--- a/tests/ImageProcessor.Tests/Processors/Filters/FilterTests.cs
+++ b/tests/ImageProcessor.Tests/Processors/Filters/FilterTests.cs
@@ -65,9 +65,9 @@ namespace ImageProcessor.Tests
string filename = Path.GetFileNameWithoutExtension(file) + "-" + name + Path.GetExtension(file);
using (FileStream output = File.OpenWrite($"TestOutput/Filter/{ Path.GetFileName(filename) }"))
{
- processor.OnProgress += ProgressUpdate;
+ processor.OnProgress += this.ProgressUpdate;
image.Process(processor).Save(output);
- processor.OnProgress -= ProgressUpdate;
+ processor.OnProgress -= this.ProgressUpdate;
}
Trace.WriteLine($"{ name }: { watch.ElapsedMilliseconds}ms");
@@ -77,7 +77,7 @@ namespace ImageProcessor.Tests
private void ProgressUpdate(object sender, ProgressEventArgs e)
{
- Assert.InRange(e.numRowsProcessed, 1, e.totalRows);
+ Assert.InRange(e.RowsProcessed, 1, e.TotalRows);
}
}
}
diff --git a/tests/ImageProcessor.Tests/Processors/Samplers/SamplerTests.cs b/tests/ImageProcessor.Tests/Processors/Samplers/SamplerTests.cs
index d215c0083..4e3493159 100644
--- a/tests/ImageProcessor.Tests/Processors/Samplers/SamplerTests.cs
+++ b/tests/ImageProcessor.Tests/Processors/Samplers/SamplerTests.cs
@@ -57,7 +57,7 @@
string filename = Path.GetFileNameWithoutExtension(file) + "-" + name + Path.GetExtension(file);
using (FileStream output = File.OpenWrite($"TestOutput/Resize/{filename}"))
{
- image.Resize(image.Width / 2, image.Height / 2, sampler, ProgressUpdate)
+ image.Resize(image.Width / 2, image.Height / 2, sampler, this.ProgressUpdate)
.Save(output);
}
@@ -85,7 +85,7 @@
string filename = Path.GetFileNameWithoutExtension(file) + "-" + name + Path.GetExtension(file);
using (FileStream output = File.OpenWrite($"TestOutput/Resize/{filename}"))
{
- image.Resize(image.Width / 3, 0, new TriangleResampler(), ProgressUpdate)
+ image.Resize(image.Width / 3, 0, new TriangleResampler(), this.ProgressUpdate)
.Save(output);
}
@@ -113,7 +113,7 @@
string filename = Path.GetFileNameWithoutExtension(file) + "-" + name + Path.GetExtension(file);
using (FileStream output = File.OpenWrite($"TestOutput/Resize/{filename}"))
{
- image.Resize(0, image.Height / 3, new TriangleResampler(), ProgressUpdate)
+ image.Resize(0, image.Height / 3, new TriangleResampler(), this.ProgressUpdate)
.Save(output);
}
@@ -140,7 +140,7 @@
string filename = Path.GetFileNameWithoutExtension(file) + "-" + rotateType + flipType + Path.GetExtension(file);
using (FileStream output = File.OpenWrite($"TestOutput/RotateFlip/{filename}"))
{
- image.RotateFlip(rotateType, flipType, ProgressUpdate)
+ image.RotateFlip(rotateType, flipType, this.ProgressUpdate)
.Save(output);
}
@@ -167,7 +167,7 @@
string filename = Path.GetFileNameWithoutExtension(file) + "-" + name + Path.GetExtension(file);
using (FileStream output = File.OpenWrite($"TestOutput/Rotate/{filename}"))
{
- image.Rotate(45, sampler, ProgressUpdate)
+ image.Rotate(45, sampler, this.ProgressUpdate)
//.BackgroundColor(Color.Aqua)
.Save(output);
}
@@ -193,7 +193,7 @@
string filename = Path.GetFileNameWithoutExtension(file) + "-EntropyCrop" + Path.GetExtension(file);
using (FileStream output = File.OpenWrite($"TestOutput/EntropyCrop/{filename}"))
{
- image.EntropyCrop(.5f, ProgressUpdate).Save(output);
+ image.EntropyCrop(.5f, this.ProgressUpdate).Save(output);
}
}
}
@@ -215,7 +215,7 @@
string filename = Path.GetFileNameWithoutExtension(file) + "-Crop" + Path.GetExtension(file);
using (FileStream output = File.OpenWrite($"TestOutput/Crop/{filename}"))
{
- image.Crop(image.Width / 2, image.Height / 2, ProgressUpdate).Save(output);
+ image.Crop(image.Width / 2, image.Height / 2, this.ProgressUpdate).Save(output);
}
}
}
@@ -238,7 +238,7 @@
private void ProgressUpdate(object sender, ProgressEventArgs e)
{
- Assert.InRange(e.numRowsProcessed, 1, e.totalRows);
+ Assert.InRange(e.RowsProcessed, 1, e.TotalRows);
}
}
}