mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-12 02:40:00 +01:00
Original implementation of Sharpen Image filters
This commit is contained in:
@@ -150,6 +150,9 @@ void CloneSource::setFilter(FrameBufferFilter::Type T)
|
||||
case FrameBufferFilter::FILTER_BLUR:
|
||||
filter_ = new BlurFilter;
|
||||
break;
|
||||
case FrameBufferFilter::FILTER_SHARPEN:
|
||||
filter_ = new SharpenFilter;
|
||||
break;
|
||||
case FrameBufferFilter::FILTER_IMAGE:
|
||||
filter_ = new ImageFilter;
|
||||
break;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#include "FrameBufferFilter.h"
|
||||
|
||||
const char* FrameBufferFilter::type_label[FrameBufferFilter::FILTER_INVALID] = {
|
||||
"None", "Delay", "Blur", "Shader code"
|
||||
"None", "Delay", "Blur", "Sharpen", "Shader code"
|
||||
};
|
||||
|
||||
FrameBufferFilter::FrameBufferFilter() : enabled_(true), input_(nullptr)
|
||||
|
||||
@@ -21,6 +21,7 @@ public:
|
||||
FILTER_PASSTHROUGH = 0,
|
||||
FILTER_DELAY,
|
||||
FILTER_BLUR,
|
||||
FILTER_SHARPEN,
|
||||
FILTER_IMAGE,
|
||||
FILTER_INVALID
|
||||
} Type;
|
||||
|
||||
@@ -818,6 +818,51 @@ void ImGuiVisitor::visit (BlurFilter& f)
|
||||
|
||||
}
|
||||
|
||||
void ImGuiVisitor::visit (SharpenFilter& f)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "Blur ";
|
||||
|
||||
// Method selection
|
||||
if (ImGuiToolkit::IconButton(7, 16)) {
|
||||
f.setMethod( 0 );
|
||||
oss << SharpenFilter::method_label[0];
|
||||
Action::manager().store(oss.str());
|
||||
}
|
||||
ImGui::SameLine(0, IMGUI_SAME_LINE);
|
||||
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
|
||||
int m = (int) f.method();
|
||||
if (ImGui::Combo("Method", &m, SharpenFilter::method_label, IM_ARRAYSIZE(SharpenFilter::method_label) )) {
|
||||
f.setMethod( m );
|
||||
oss << SharpenFilter::method_label[m];
|
||||
Action::manager().store(oss.str());
|
||||
}
|
||||
|
||||
|
||||
// List of parameters
|
||||
std::map<std::string, float> filter_parameters = f.program().parameters();
|
||||
for (auto param = filter_parameters.begin(); param != filter_parameters.end(); ++param)
|
||||
{
|
||||
ImGui::PushID( param->first.c_str() );
|
||||
float v = param->second;
|
||||
if (ImGuiToolkit::IconButton(13, 14)) {
|
||||
v = 0.f;
|
||||
f.setProgramParameter(param->first, v);
|
||||
}
|
||||
ImGui::SameLine(0, IMGUI_SAME_LINE);
|
||||
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
|
||||
if (ImGui::SliderFloat( param->first.c_str(), &v, 0.f, 1.f, "%.2f")) {
|
||||
f.setProgramParameter(param->first, v);
|
||||
}
|
||||
if (ImGui::IsItemDeactivatedAfterEdit()) {
|
||||
oss << SharpenFilter::method_label[ f.method() ];
|
||||
oss << " : " << param->first << " " << std::setprecision(3) <<param->second;
|
||||
Action::manager().store(oss.str());
|
||||
}
|
||||
ImGui::PopID();
|
||||
}
|
||||
}
|
||||
|
||||
void ImGuiVisitor::visit (ImageFilter& f)
|
||||
{
|
||||
// Selection of Algorithm
|
||||
|
||||
@@ -40,6 +40,7 @@ public:
|
||||
void visit (PassthroughFilter&) override;
|
||||
void visit (DelayFilter&) override;
|
||||
void visit (BlurFilter&) override;
|
||||
void visit (SharpenFilter&) override;
|
||||
void visit (ImageFilter&) override;
|
||||
};
|
||||
|
||||
|
||||
@@ -485,15 +485,15 @@ void ImageFilter::setProgramParameter(const std::string &p, float value)
|
||||
////////////////////////////////////////
|
||||
|
||||
const char* BlurFilter::method_label[BlurFilter::BLUR_INVALID] = {
|
||||
"Gaussian", "Hash", "Openning", "Closing", "Fast 2x2"
|
||||
"Gaussian", "Scattered", "Opening", "Closing", "Fast"
|
||||
};
|
||||
|
||||
std::vector< FilteringProgram > BlurFilter::programs_ = {
|
||||
FilteringProgram("Gaussian", "shaders/filters/blur_1.glsl", "shaders/filters/blur_2.glsl", { { "Radius", 0.5} }),
|
||||
FilteringProgram("Hashed", "shaders/filters/hashedblur.glsl", "", { { "Iterations", 0.5 }, { "Radius", 0.5} }),
|
||||
FilteringProgram("Openning", "shaders/filters/hashederosion.glsl", "shaders/filters/hasheddilation.glsl", { { "Radius", 0.5} }),
|
||||
FilteringProgram("Scattered","shaders/filters/hashedblur.glsl", "", { { "Radius", 0.5}, { "Iterations", 0.25 } }),
|
||||
FilteringProgram("Opening", "shaders/filters/hashederosion.glsl", "shaders/filters/hasheddilation.glsl", { { "Radius", 0.5} }),
|
||||
FilteringProgram("Closing", "shaders/filters/hasheddilation.glsl","shaders/filters/hashederosion.glsl", { { "Radius", 0.5} }),
|
||||
FilteringProgram("Fast 2x2", "shaders/filters/blur.glsl", "", { })
|
||||
FilteringProgram("Fast", "shaders/filters/blur.glsl", "", { })
|
||||
};
|
||||
|
||||
BlurFilter::BlurFilter (): ImageFilter(), method_(BLUR_INVALID), mipmap_buffer_(nullptr)
|
||||
@@ -588,4 +588,37 @@ void BlurFilter::accept (Visitor& v)
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////
|
||||
///// //
|
||||
//// SHARPENING FILTERS ///
|
||||
/// ////
|
||||
////////////////////////////////////////
|
||||
|
||||
const char* SharpenFilter::method_label[SharpenFilter::SHARPEN_INVALID] = {
|
||||
"Unsharp mask", "Convolution", "Edge"
|
||||
};
|
||||
|
||||
std::vector< FilteringProgram > SharpenFilter::programs_ = {
|
||||
FilteringProgram("Unsharp Mask", "shaders/filters/sharpen_1.glsl", "shaders/filters/sharpen_2.glsl", { { "Amount", 0.5} }),
|
||||
FilteringProgram("Sharpen", "shaders/filters/sharp.glsl", "", { { "Amount", 0.5} }),
|
||||
FilteringProgram("Sharp Edge", "shaders/filters/bilinear.glsl", "shaders/filters/sharpenedge.glsl", { { "Strength", 0.5} }),
|
||||
};
|
||||
|
||||
SharpenFilter::SharpenFilter (): ImageFilter(), method_(SHARPEN_INVALID)
|
||||
{
|
||||
}
|
||||
|
||||
void SharpenFilter::setMethod(int method)
|
||||
{
|
||||
method_ = (SharpenMethod) CLAMP(method, SHARPEN_MASK, SHARPEN_INVALID-1);
|
||||
setProgram( programs_[ (int) method_] );
|
||||
}
|
||||
|
||||
void SharpenFilter::accept (Visitor& v)
|
||||
{
|
||||
FrameBufferFilter::accept(v);
|
||||
v.visit(*this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -137,6 +137,33 @@ private:
|
||||
};
|
||||
|
||||
|
||||
class SharpenFilter : public ImageFilter
|
||||
{
|
||||
public:
|
||||
|
||||
SharpenFilter();
|
||||
|
||||
// Algorithms used for sharpen
|
||||
typedef enum {
|
||||
SHARPEN_MASK = 0,
|
||||
SHARPEN_CONVOLUTION,
|
||||
SHARPEN_EDGE,
|
||||
SHARPEN_INVALID
|
||||
} SharpenMethod;
|
||||
static const char* method_label[SHARPEN_INVALID];
|
||||
SharpenMethod method () const { return method_; }
|
||||
void setMethod(int method);
|
||||
|
||||
// implementation of FrameBufferFilter
|
||||
Type type() const override { return FrameBufferFilter::FILTER_SHARPEN; }
|
||||
|
||||
void accept (Visitor& v) override;
|
||||
|
||||
private:
|
||||
SharpenMethod method_;
|
||||
static std::vector< FilteringProgram > programs_;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif // IMAGEFILTER_H
|
||||
|
||||
@@ -45,6 +45,7 @@ class FrameBufferFilter;
|
||||
class PassthroughFilter;
|
||||
class DelayFilter;
|
||||
class BlurFilter;
|
||||
class SharpenFilter;
|
||||
class ImageFilter;
|
||||
|
||||
class SourceCallback;
|
||||
@@ -106,6 +107,7 @@ public:
|
||||
virtual void visit (PassthroughFilter&) {}
|
||||
virtual void visit (DelayFilter&) {}
|
||||
virtual void visit (BlurFilter&) {}
|
||||
virtual void visit (SharpenFilter&) {}
|
||||
virtual void visit (ImageFilter&) {}
|
||||
|
||||
virtual void visit (SourceCallback&) {}
|
||||
|
||||
@@ -40,7 +40,7 @@ void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
||||
vec4 O = vec4(1.);
|
||||
float N = 17;
|
||||
for (float i = 0.; i < N; i++) {
|
||||
vec2 q = vec2(cos(TWOPI*((i+.5)/N)) * ar, sin(TWOPI*(i+.5)/N)) * Hash01(uv, floatBitsToUint(i));
|
||||
vec2 q = vec2(cos(TWOPI*((i+.5)/N)) * ar, sin(TWOPI*(i+.5)/N)) * (0.1 + 0.9 * Hash01(uv, floatBitsToUint(i)));
|
||||
// vec2 q = vec2(cos(TWOPI*((i+.5)/N)) * ar, sin(TWOPI*(i+.5)/N)) * hash(vec2(i + 12., uv.x * uv.y + 24.));
|
||||
O = min( texture(iChannel0, uv + q*R), O );
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
||||
vec4 O = vec4(0.);
|
||||
float N = 17;
|
||||
for (float i = 0.; i < N; i++) {
|
||||
vec2 q = vec2(cos(TWOPI*i/N) * ar, sin(TWOPI*i/N)) * Hash01(uv, floatBitsToUint(i) );
|
||||
vec2 q = vec2(cos(TWOPI*i/N) * ar, sin(TWOPI*i/N)) * (0.1 + 0.9 * Hash01(uv, floatBitsToUint(i)));
|
||||
// vec2 q = vec2(cos(TWOPI*i/N) * ar, sin(TWOPI*i/N)) * hash(vec2(i, uv.x + uv.y));
|
||||
O = max( texture(iChannel0, uv + q*R), O );
|
||||
}
|
||||
|
||||
@@ -1,30 +1,22 @@
|
||||
uniform float Amount;
|
||||
|
||||
float SCurve (float x) {
|
||||
x = x * 2.0 - 1.0;
|
||||
return -x * abs(x) * 0.5 + x + 0.5;
|
||||
#define N 7
|
||||
vec4 blur1D(vec2 U, vec2 D, float rad)
|
||||
{
|
||||
float w = rad * iResolution.y;
|
||||
float z = ceil(max(0.,log2(w/float(N)))); // LOD N/w = res/2^z
|
||||
vec4 O = vec4(0);
|
||||
float r = float(N-1)/2., g, t=0., x;
|
||||
for( int k=0; k<N; k++ ) {
|
||||
x = float(k)/r -1.;
|
||||
t += g = exp(-2.*x*x );
|
||||
O += g * textureLod(iChannel0, (U + w*x*D) / iResolution.xy, z );
|
||||
}
|
||||
|
||||
vec3 BlurV (sampler2D source, vec2 uv, float step, float radius) {
|
||||
vec3 C = vec3(0.0);
|
||||
float divisor = 0.0;
|
||||
float weight = 0.0;
|
||||
float radiusMultiplier = 1.0 / max(1.0, radius);
|
||||
|
||||
// loop on pixels in Y to apply vertical blur
|
||||
for (float y = -radius; y <= radius; y++) {
|
||||
weight = SCurve(1.0 - (abs(y) * radiusMultiplier));
|
||||
C += texture(source, uv + vec2(0.0, y * step)).rgb * weight;
|
||||
divisor += weight;
|
||||
}
|
||||
|
||||
return C / divisor;
|
||||
return O/t;
|
||||
}
|
||||
|
||||
void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
||||
{
|
||||
vec2 uv = fragCoord.xy / iResolution.xy;
|
||||
|
||||
// Apply vertical blur
|
||||
fragColor = vec4( BlurV(iChannel0, uv, 1.0 / iResolution.y, mix(1.0, 0.1*iResolution.y, Amount)), 1.0);
|
||||
fragColor = blur1D(fragCoord, vec2(1,0), 0.1 * Amount);
|
||||
}
|
||||
|
||||
@@ -1,37 +1,29 @@
|
||||
uniform float Amount;
|
||||
|
||||
float SCurve (float x) {
|
||||
x = x * 2.0 - 1.0;
|
||||
return -x * abs(x) * 0.5 + x + 0.5;
|
||||
#define N 7
|
||||
vec4 blur1D(vec2 U, vec2 D, float rad)
|
||||
{
|
||||
float w = rad * iResolution.y;
|
||||
float z = ceil(max(0.,log2(w/float(N)))); // LOD N/w = res/2^z
|
||||
vec4 O = vec4(0);
|
||||
float r = float(N-1)/2., g, t=0., x;
|
||||
for( int k=0; k<N; k++ ) {
|
||||
x = float(k)/r -1.;
|
||||
t += g = exp(-2.*x*x );
|
||||
O += g * textureLod(iChannel0, (U + w*x*D) / iResolution.xy, z );
|
||||
}
|
||||
|
||||
vec3 BlurH (sampler2D source, vec2 uv, float step, float radius) {
|
||||
vec3 C = vec3(0.0);
|
||||
float divisor = 0.0;
|
||||
float weight = 0.0;
|
||||
float radiusMultiplier = 1.0 / max(1.0, radius);
|
||||
|
||||
// loop on pixels in X to apply horizontal blur
|
||||
for (float x = -radius; x <= radius; x++) {
|
||||
weight = SCurve(1.0 - (abs(x) * radiusMultiplier));
|
||||
C += texture(source, uv + vec2(x * step, 0.0)).rgb * weight;
|
||||
divisor += weight;
|
||||
}
|
||||
|
||||
return C / divisor;
|
||||
return O/t;
|
||||
}
|
||||
|
||||
void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
||||
{
|
||||
vec2 uv = fragCoord.xy / iResolution.xy;
|
||||
|
||||
// get original image
|
||||
vec3 c = texture(iChannel1, uv).rgb;
|
||||
vec4 c = texture(iChannel1, fragCoord.xy / iResolution.xy);
|
||||
|
||||
// Remove blurred image to original image
|
||||
vec3 lumcoeff = vec3(0.299,0.587,0.114);
|
||||
float luminance = dot( c - BlurH(iChannel0, uv, 1.0 / iResolution.x, mix(1.0, 0.1*iResolution.y, Amount) ), lumcoeff);
|
||||
vec4 lumcoeff = vec4(0.299, 0.587, 0.114, 1.);
|
||||
float luminance = dot( c - blur1D(fragCoord, vec2(0,1), 0.1 * Amount ), lumcoeff);
|
||||
|
||||
// composition
|
||||
fragColor = vec4( c + vec3(luminance), 1.0);
|
||||
fragColor = c + vec4(luminance);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user