Lanczos のリサンプリングをお探しの場合は、オープン ソースの 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;
}
これは 2 つのパスで適用されます。1 つ目は水平方向のダウンサンプリングを実行し、2 つ目は垂直方向のダウンサンプリングを実行します。texelWidthOffset
とuniforms は交互に 0.0 に設定され、画像内の単一ピクセルのtexelHeightOffset
幅の割合または高さの割合が設定されます。
頂点シェーダーでテクセル オフセットを厳密に計算するのは、これでターゲットにしているモバイル デバイスで依存するテクスチャーの読み取りを回避し、そこでのパフォーマンスが大幅に向上するためです。ただし、少し冗長です。
このランチョス リサンプリングの結果:
通常のバイリニア ダウンサンプリング:
最近傍ダウンサンプリング: