UIImage でモーション ブラー効果を得る方法はありますか? GPUImage、Filtrr、および iOS Core Image を試しましたが、これらにはすべて通常のブラーがあり、モーション ブラーはありません。
UIImage-DSPも試してみましたが、モーションブラーはほとんど見えません。もっと強いものが必要です。
リポジトリにコメントしたように、モーション ブラーとズーム ブラーを GPUImage に追加しました。これらは GPUImageMotionBlurFilter クラスと GPUImageZoomBlurFilter クラスです。これは、ズーム ブラーの例です。
モーション ブラーでは、単一方向に 9 ヒットのガウス ブラーを適用します。これは、次の頂点シェーダーとフラグメント シェーダーを使用して実現されます。
バーテックス:
attribute vec4 position;
attribute vec4 inputTextureCoordinate;
uniform highp vec2 directionalTexelStep;
varying vec2 textureCoordinate;
varying vec2 oneStepBackTextureCoordinate;
varying vec2 twoStepsBackTextureCoordinate;
varying vec2 threeStepsBackTextureCoordinate;
varying vec2 fourStepsBackTextureCoordinate;
varying vec2 oneStepForwardTextureCoordinate;
varying vec2 twoStepsForwardTextureCoordinate;
varying vec2 threeStepsForwardTextureCoordinate;
varying vec2 fourStepsForwardTextureCoordinate;
void main()
{
gl_Position = position;
textureCoordinate = inputTextureCoordinate.xy;
oneStepBackTextureCoordinate = inputTextureCoordinate.xy - directionalTexelStep;
twoStepsBackTextureCoordinate = inputTextureCoordinate.xy - 2.0 * directionalTexelStep;
threeStepsBackTextureCoordinate = inputTextureCoordinate.xy - 3.0 * directionalTexelStep;
fourStepsBackTextureCoordinate = inputTextureCoordinate.xy - 4.0 * directionalTexelStep;
oneStepForwardTextureCoordinate = inputTextureCoordinate.xy + directionalTexelStep;
twoStepsForwardTextureCoordinate = inputTextureCoordinate.xy + 2.0 * directionalTexelStep;
threeStepsForwardTextureCoordinate = inputTextureCoordinate.xy + 3.0 * directionalTexelStep;
fourStepsForwardTextureCoordinate = inputTextureCoordinate.xy + 4.0 * directionalTexelStep;
}
断片:
precision highp float;
uniform sampler2D inputImageTexture;
varying vec2 textureCoordinate;
varying vec2 oneStepBackTextureCoordinate;
varying vec2 twoStepsBackTextureCoordinate;
varying vec2 threeStepsBackTextureCoordinate;
varying vec2 fourStepsBackTextureCoordinate;
varying vec2 oneStepForwardTextureCoordinate;
varying vec2 twoStepsForwardTextureCoordinate;
varying vec2 threeStepsForwardTextureCoordinate;
varying vec2 fourStepsForwardTextureCoordinate;
void main()
{
lowp vec4 fragmentColor = texture2D(inputImageTexture, textureCoordinate) * 0.18;
fragmentColor += texture2D(inputImageTexture, oneStepBackTextureCoordinate) * 0.15;
fragmentColor += texture2D(inputImageTexture, twoStepsBackTextureCoordinate) * 0.12;
fragmentColor += texture2D(inputImageTexture, threeStepsBackTextureCoordinate) * 0.09;
fragmentColor += texture2D(inputImageTexture, fourStepsBackTextureCoordinate) * 0.05;
fragmentColor += texture2D(inputImageTexture, oneStepForwardTextureCoordinate) * 0.15;
fragmentColor += texture2D(inputImageTexture, twoStepsForwardTextureCoordinate) * 0.12;
fragmentColor += texture2D(inputImageTexture, threeStepsForwardTextureCoordinate) * 0.09;
fragmentColor += texture2D(inputImageTexture, fourStepsForwardTextureCoordinate) * 0.05;
gl_FragColor = fragmentColor;
}
最適化として、角度、ぼかしサイズ、および画像の寸法を使用して、フラグメント シェーダーの外側のテクスチャ サンプル間のステップ サイズを計算します。これは次に頂点シェーダーに渡されるため、そこでテクスチャ サンプリング位置を計算し、フラグメント シェーダーでそれらを補間できます。これにより、iOS デバイスでの依存テクスチャ読み取りが回避されます。
これらの計算はまだフラグメント シェーダーで行っているため、ズーム ブラーはかなり遅くなります。これを最適化できる方法があることは間違いありませんが、まだ試していません。ズーム ブラーは 9 ヒットのガウス ブラーを使用します。方向とサンプルごとのオフセット距離は、ピクセルの配置とブラーの中心の関数として変化します。
次のフラグメント シェーダー (および標準のパススルー頂点シェーダー) を使用します。
varying highp vec2 textureCoordinate;
uniform sampler2D inputImageTexture;
uniform highp vec2 blurCenter;
uniform highp float blurSize;
void main()
{
// TODO: Do a more intelligent scaling based on resolution here
highp vec2 samplingOffset = 1.0/100.0 * (blurCenter - textureCoordinate) * blurSize;
lowp vec4 fragmentColor = texture2D(inputImageTexture, textureCoordinate) * 0.18;
fragmentColor += texture2D(inputImageTexture, textureCoordinate + samplingOffset) * 0.15;
fragmentColor += texture2D(inputImageTexture, textureCoordinate + (2.0 * samplingOffset)) * 0.12;
fragmentColor += texture2D(inputImageTexture, textureCoordinate + (3.0 * samplingOffset)) * 0.09;
fragmentColor += texture2D(inputImageTexture, textureCoordinate + (4.0 * samplingOffset)) * 0.05;
fragmentColor += texture2D(inputImageTexture, textureCoordinate - samplingOffset) * 0.15;
fragmentColor += texture2D(inputImageTexture, textureCoordinate - (2.0 * samplingOffset)) * 0.12;
fragmentColor += texture2D(inputImageTexture, textureCoordinate - (3.0 * samplingOffset)) * 0.09;
fragmentColor += texture2D(inputImageTexture, textureCoordinate - (4.0 * samplingOffset)) * 0.05;
gl_FragColor = fragmentColor;
}
これらのぼかしは両方とも、パフォーマンス上の理由から 9 サンプルでハードコーディングされていることに注意してください。これは、ぼかしのサイズが大きくなると、ここにある限られたサンプルからアーティファクトが見られるようになることを意味します。大きなぼかしの場合は、これらのフィルターを複数回実行するか、拡張してより多くのガウス サンプルをサポートする必要があります。ただし、iOS デバイスではテクスチャ サンプリングの帯域幅が限られているため、サンプルを増やすとレンダリング時間が大幅に遅くなります。
CoreImage にはモーション ブラー フィルターがあります。
それはCIMotionBlurと呼ばれています... http://developer.apple.com/library/mac/#documentation/GraphicsImaging/Reference/CoreImageFilterReference/Reference/reference.html#//apple_ref/doc/filter/ci/CIMotionBlur