]> git.sesse.net Git - movit/blobdiff - deconvolution_sharpen_effect.h
Add an implementation of sharpening by FIR Wiener filters.
[movit] / deconvolution_sharpen_effect.h
diff --git a/deconvolution_sharpen_effect.h b/deconvolution_sharpen_effect.h
new file mode 100644 (file)
index 0000000..bc0bbd4
--- /dev/null
@@ -0,0 +1,56 @@
+#ifndef _DECONVOLUTION_SHARPEN_EFFECT_H
+#define _DECONVOLUTION_SHARPEN_EFFECT_H 1
+
+// DeconvolutionSharpenEffect is an effect that sharpens by way of deconvolution
+// (i.e., trying to reverse the blur kernel, as opposed to just boosting high
+// frequencies), more specifically by FIR Wiener filters. It is the same
+// algorithm as used by the (now largely abandoned) Refocus plug-in for GIMP,
+// and I suspect the same as in Photoshop's “Smart Sharpen” filter.
+// The implementation is, however, distinct from either.
+//
+// The effect gives generally better results than unsharp masking, but can be very
+// GPU intensive, and requires a fair bit of tweaking to get good results without
+// ringing and/or excessive noise. It should be mentioned that for the larger
+// convolutions (e.g. R approaching 10), we should probably move to FFT-based
+// convolution algorithms, especially as Mesa's shader compiler starts having
+// problems compiling our shader.
+//
+// We follow the same book as Refocus was implemented from, namely
+//
+//   Jain, Anil K.: “Fundamentals of Digital Image Processing”, Prentice Hall, 1988.
+
+#include "effect.h"
+
+class DeconvolutionSharpenEffect : public Effect {
+public:
+       DeconvolutionSharpenEffect();
+       virtual std::string effect_type_id() const { return "DeconvolutionSharpenEffect"; }
+       std::string output_fragment_shader();
+
+       virtual void inform_input_size(unsigned input_num, unsigned width, unsigned height)
+       {
+               this->width = width;
+               this->height = height;
+       }
+
+       void set_gl_state(GLuint glsl_program_num, const std::string &prefix, unsigned *sampler_num);
+
+private:
+       // Input size.
+       unsigned width, height;
+
+       // The maximum radius of the (de)convolution kernel.
+       // Note that since this extends both ways, and we also have a center element,
+       // the actual convolution matrix will be (2R + 1) x (2R + 1).
+       //
+       // Must match the definition in the shader, and as such, cannot be set once
+       // the chain has been finalized.
+       int R;
+
+       // The parameters. Typical OK values are circle_radius = 2, gaussian_radius = 0
+       // (ie., blur is assumed to be a 2px circle), correlation = 0.95, and noise = 0.01.
+       // Note that once the radius starts going too far past R, you will get nonsensical results.
+       float circle_radius, gaussian_radius, correlation, noise;
+};
+
+#endif // !defined(_DECONVOLUTION_SHARPEN_EFFECT_H)