2013-01-16 45 views
9

में सुधार कैसे कर सकता हूं, मैं वेब एपी का उपयोग कर रहा हूं ताकि मैं जिस ऐप पर काम कर रहा हूं, उसके भीतर छवियों का आकार बदल सकूं। मैंने एक जीएलएसएल शेडर लिखा है जो छवियों पर सरल बिलीनेर फ़िल्टरिंग करता है जिसे मैं डाउनसाइज कर रहा हूं।मैं इस वेबजीएल/जीएलएसएल छवि को डाउनस्प्लिंग शेडर

यह अधिकांश भाग के लिए ठीक काम करता है लेकिन कई अवसर हैं जहां आकार बड़ा है उदा। एक थंबनेल उत्पन्न करने के लिए 2048x2048 छवि से 110x110 तक। इन मामलों में गुणवत्ता खराब और बहुत धुंधली है।

मेरे वर्तमान GLSL शेडर इस प्रकार है:

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 और TexelsizeY बस कर रहे हैं (1.0/बनावट चौड़ाई) और क्रमशः ऊंचाई ...

मैं एक उच्च गुणवत्ता को छानने तकनीक लागू करने के लिए चाहते हैं , आदर्श रूप से एक [लैंकोज़] [1] फ़िल्टर जो बहुत बेहतर परिणाम उत्पन्न करना चाहिए, लेकिन मुझे लगता है कि जीएलएसएल के साथ एल्गोरिदम को कार्यान्वित करने के तरीके के बारे में मेरा सिर नहीं मिल रहा है क्योंकि मैं सामान्य रूप से वेबजीएल और जीएलएसएल के लिए बहुत नया हूं।

क्या कोई मुझे सही दिशा में इंगित कर सकता है?

अग्रिम धन्यवाद।

उत्तर

15

आप Lanczos resampling के लिए देख रहे हैं, तो निम्न शेडर कार्यक्रम मैं अपने खुला स्रोत GPUImage पुस्तकालय में उपयोग करते हैं:

वर्टेक्स शेडर:

attribute vec4 position; 
attribute vec2 inputTextureCoordinate; 

uniform float texelWidthOffset; 
uniform float texelHeightOffset; 

varying vec2 centerTextureCoordinate; 
varying vec2 oneStepLeftTextureCoordinate; 
varying vec2 twoStepsLeftTextureCoordinate; 
varying vec2 threeStepsLeftTextureCoordinate; 
varying vec2 fourStepsLeftTextureCoordinate; 
varying vec2 oneStepRightTextureCoordinate; 
varying vec2 twoStepsRightTextureCoordinate; 
varying vec2 threeStepsRightTextureCoordinate; 
varying vec2 fourStepsRightTextureCoordinate; 

void main() 
{ 
    gl_Position = position; 

    vec2 firstOffset = vec2(texelWidthOffset, texelHeightOffset); 
    vec2 secondOffset = vec2(2.0 * texelWidthOffset, 2.0 * texelHeightOffset); 
    vec2 thirdOffset = vec2(3.0 * texelWidthOffset, 3.0 * texelHeightOffset); 
    vec2 fourthOffset = vec2(4.0 * texelWidthOffset, 4.0 * texelHeightOffset); 

    centerTextureCoordinate = inputTextureCoordinate; 
    oneStepLeftTextureCoordinate = inputTextureCoordinate - firstOffset; 
    twoStepsLeftTextureCoordinate = inputTextureCoordinate - secondOffset; 
    threeStepsLeftTextureCoordinate = inputTextureCoordinate - thirdOffset; 
    fourStepsLeftTextureCoordinate = inputTextureCoordinate - fourthOffset; 
    oneStepRightTextureCoordinate = inputTextureCoordinate + firstOffset; 
    twoStepsRightTextureCoordinate = inputTextureCoordinate + secondOffset; 
    threeStepsRightTextureCoordinate = inputTextureCoordinate + thirdOffset; 
    fourStepsRightTextureCoordinate = inputTextureCoordinate + fourthOffset; 
} 

टुकड़ा शेडर:

precision highp float; 

uniform sampler2D inputImageTexture; 

varying vec2 centerTextureCoordinate; 
varying vec2 oneStepLeftTextureCoordinate; 
varying vec2 twoStepsLeftTextureCoordinate; 
varying vec2 threeStepsLeftTextureCoordinate; 
varying vec2 fourStepsLeftTextureCoordinate; 
varying vec2 oneStepRightTextureCoordinate; 
varying vec2 twoStepsRightTextureCoordinate; 
varying vec2 threeStepsRightTextureCoordinate; 
varying vec2 fourStepsRightTextureCoordinate; 

// sinc(x) * sinc(x/a) = (a * sin(pi * x) * sin(pi * x/a))/(pi^2 * x^2) 
// Assuming a Lanczos constant of 2.0, and scaling values to max out at x = +/- 1.5 

void main() 
{ 
    lowp vec4 fragmentColor = texture2D(inputImageTexture, centerTextureCoordinate) * 0.38026; 

    fragmentColor += texture2D(inputImageTexture, oneStepLeftTextureCoordinate) * 0.27667; 
    fragmentColor += texture2D(inputImageTexture, oneStepRightTextureCoordinate) * 0.27667; 

    fragmentColor += texture2D(inputImageTexture, twoStepsLeftTextureCoordinate) * 0.08074; 
    fragmentColor += texture2D(inputImageTexture, twoStepsRightTextureCoordinate) * 0.08074; 

    fragmentColor += texture2D(inputImageTexture, threeStepsLeftTextureCoordinate) * -0.02612; 
    fragmentColor += texture2D(inputImageTexture, threeStepsRightTextureCoordinate) * -0.02612; 

    fragmentColor += texture2D(inputImageTexture, fourStepsLeftTextureCoordinate) * -0.02143; 
    fragmentColor += texture2D(inputImageTexture, fourStepsRightTextureCoordinate) * -0.02143; 

    gl_FragColor = fragmentColor; 
} 

यह दो पास में लागू होता है, जिसमें पहले क्षैतिज डाउनस्प्लिंग और दूसरा वर्टिकल डाउनसमलिंग होता है। texelWidthOffset और texelHeightOffset वर्दी वैकल्पिक रूप से 0.0 पर सेट की गई हैं और छवि में एक पिक्सेल की चौड़ाई अंश या ऊंचाई अंश है।

मैं कशेरुक शेडर में टेक्सल ऑफ़सेट की हार्ड-गणना करता हूं क्योंकि यह उन मोबाइल उपकरणों पर निर्भर बनावट को पढ़ता है जो मैं इसके साथ लक्षित कर रहा हूं, जिससे वहां काफी बेहतर प्रदर्शन होता है। हालांकि, यह एक छोटी verbose है।

इस Lanczos resampling से

परिणाम:

Lanczos

सामान्य द्विरेखीय downsampling:

Bilinear

निकटतम-पड़ोसी downsampling:

Nearest-neighbor

+0

एक खूबसूरती से निर्मित उत्तर। धन्यवाद। मुझे आपके द्वारा पोस्ट किए गए कोड से वहां पहुंचने में सक्षम होना चाहिए। चीयर्स! – gordyr

+0

बस आपको बताने के लिए मुझे पता है कि यह पूरी तरह से काम कर रहा है और परिणाम सुंदर हैं। आश्चर्यजनक रूप से मुझे टेक्सलोफसेट्स को (1.0/(गंतव्यविड्थ * 3)) और (1.0/(गंतव्यहाइट * 3)) को सर्वोत्तम परिणामों के लिए सेट करना पड़ा। मुझे यकीन नहीं है कि मैं समझता हूं कि क्यों मानक चौड़ाई/ऊंचाई का उपयोग करके एक बहुत ही धुंधली छवि उत्पन्न हुई। भले ही यह शानदार है। बहुत धन्यवाद! – gordyr

+0

@gordyr - सुनने के लिए अच्छा है। आपका मतलब है कि आपको texelWidthOffset = 3.0/(छवि चौड़ाई पिक्सेल में) या texelWidthOffset = 1.0/(3.0 * (छवि चौड़ाई पिक्सल में) का उपयोग करने की आवश्यकता है)?मैंने उपरोक्त छवियों को texelWidthOffset = 1.0/(छवि चौड़ाई पिक्सल में) और texelHeightOffset = 1.0/(छवि ऊंचाई पिक्सल में) के साथ उत्पन्न किया है, लेकिन यदि आपके लिए तीन कार्यों का एक कारक है, तो इसके साथ जाएं। –