I am using WebGL to resize images clientside very quickly within an app I am working on. I have written a GLSL shader that performs simple bilinear filtering on the images that I am downsizing.
It works fine for the most part but there are many occasions where the resize is huge e.g. from a 2048x2048 image down to 110x110 in order to generate a thumbnail. In these instances the quality is poor and far too blurry.
My current GLSL shader is as follows:
uniform float textureSizeWidth;\
uniform float textureSizeHeight;\
uniform float texelSizeX;\
uniform float texelSizeY;\
varying mediump vec2 texCoord;\
uniform sampler2D texture;\
\
vec4 tex2DBiLinear( sampler2D textureSampler_i, vec2 texCoord_i )\
{\
vec4 p0q0 = texture2D(textureSampler_i, texCoord_i);\
vec4 p1q0 = texture2D(textureSampler_i, texCoord_i + vec2(texelSizeX, 0));\
\
vec4 p0q1 = texture2D(textureSampler_i, texCoord_i + vec2(0, texelSizeY));\
vec4 p1q1 = texture2D(textureSampler_i, texCoord_i + vec2(texelSizeX , texelSizeY));\
\
float a = fract( texCoord_i.x * textureSizeWidth );\
\
vec4 pInterp_q0 = mix( p0q0, p1q0, a );\
vec4 pInterp_q1 = mix( p0q1, p1q1, a );\
\
float b = fract( texCoord_i.y * textureSizeHeight );\
return mix( pInterp_q0, pInterp_q1, b );\
}\
void main() { \
\
gl_FragColor = tex2DBiLinear(texture,texCoord);\
}');
TexelsizeX and TexelsizeY are simply (1.0 / texture width) and height respectively...
I would like to implement a higher quality filtering technique, ideally a [Lancosz][1] filter which should produce far better results but I cannot seem to get my head around how to implement the algorithm with GLSL as I am very new to WebGL and GLSL in general.
Could anybody point me in the right direction?
Thanks in advance.
If you're looking for Lanczos resampling, the following is the shader program I use in my open source GPUImage library:
Vertex shader:
Fragment shader:
This is applied in two passes, with the first performing a horizontal downsampling and the second a vertical downsampling. The
texelWidthOffset
andtexelHeightOffset
uniforms are alternately set to 0.0 and the width fraction or height fraction of a single pixel in the image.I hard-calculate the texel offsets in the vertex shader because this avoids dependent texture reads on the mobile devices I'm targeting with this, leading to significantly better performance there. It is a little verbose, though.
Results from this Lanczos resampling:
Normal bilinear downsampling:
Nearest-neighbor downsampling: