2

ビットマップにレベルを適用する次のアルゴリズム (Android/NDK 用) を作成しました。問題は、SGSIII などの高速なデバイスでは、8MP イメージの場合に最大 4 秒かかることがあるため、非常に遅いことです。また、ARMv6 を搭載したデバイスでは、時間がかかります (10 秒以上)。それを最適化する方法はありますか?

void applyLevels(unsigned int *rgb, const unsigned int width, const unsigned int height, const float exposure, const float brightness, const float contrast, const float saturation)
{
    float R, G, B;

    unsigned int pixelIndex = 0;

    float exposureFactor   = powf(2.0f, exposure);
    float brightnessFactor = brightness / 10.0f;
    float contrastFactor   = contrast > 0.0f ? contrast : 0.0f;

    for (int y = 0; y < height; y++)
    {
        for (int x = 0; x < width; x++)
        {
            const int pixelValue = buffer[pixelIndex];

            R = ((pixelValue & 0xff0000) >> 16) / 255.0f;
            G = ((pixelValue & 0xff00) >> 8) / 255.0f;
            B = (pixelValue & 0xff) / 255.0f;

            // Clamp values

            R = R > 1.0f ? 1.0f : R < 0.0f ? 0.0f : R;
            G = G > 1.0f ? 1.0f : G < 0.0f ? 0.0f : G;
            B = B > 1.0f ? 1.0f : B < 0.0f ? 0.0f : B;

            // Exposure

            R *= exposureFactor;
            G *= exposureFactor;
            B *= exposureFactor;

            // Contrast

            R = (((R - 0.5f) * contrastFactor) + 0.5f);
            G = (((G - 0.5f) * contrastFactor) + 0.5f);
            B = (((B - 0.5f) * contrastFactor) + 0.5f);

            // Saturation

            float gray = (R * 0.3f) + (G * 0.59f) + (B * 0.11f);
            R = gray * (1.0f - saturation) + R * saturation;
            G = gray * (1.0f - saturation) + G * saturation;
            B = gray * (1.0f - saturation) + B * saturation;

            // Brightness

            R += brightnessFactor;
            G += brightnessFactor;
            B += brightnessFactor;

            // Clamp values

            R = R > 1.0f ? 1.0f : R < 0.0f ? 0.0f : R;
            G = G > 1.0f ? 1.0f : G < 0.0f ? 0.0f : G;
            B = B > 1.0f ? 1.0f : B < 0.0f ? 0.0f : B;

            // Store new pixel value

            R *= 255.0f;
            G *= 255.0f;
            B *= 255.0f;

            buffer[pixelIndex] = ((int)R << 16) | ((int)G << 8) | (int)B;

            pixelIndex++;
        }
    }
}
4

4 に答える 4

0

そのコードを最適化するためのいくつかのポイント

  1. 整数計算を優先します。つまり、RGB データを [0, 255] から [0, 1] に変換する代わりに、逆を行い、すべてのコントラスト、明るさなどを 0 から 255 の間に変換します。

  2. クリッピング操作は、クリッピング テーブルを使用して if-else ステートメントを削除することで簡素化できることがよくあります。

    R = クリップ[R'];

  3. 奇妙なクリッピングセクションに気付きました

        // Clamp values
    
        R = R > 255.0f ? 255.0f : R < 0.0f ? 0.0f : R;
        G = G > 255.0f ? 255.0f : G < 0.0f ? 0.0f : G;
        B = B > 255.0f ? 255.0f : B < 0.0f ? 0.0f : B;
    

ここでは、まだ[0、1]の範囲にあるように見えるので、役に立ちません!

  1. 最後に式を見直してください。なぜなら、露出と明るさは、いくつかの操作を削除するための実際の賞品になる可能性があるからです。

最後に、そのコードは SIMD および MIMD の有力候補であるため、MMX/SSE または OpenMP がパフォーマンスの問題を解決できるかどうかを調べてください。

于 2013-07-18T12:20:17.947 に答える
0

(1.0f - saturation)どこでも同じなので、変数に代入するだけです。

代わりに>> 16) / 255.0f>> 8) / 255.0fそれらを単一の乗算に変換できます。または、それぞれ>> 10と を使用して、255 ではなく 256 で割ることができます。>> 8

 R = ((pixelValue & 0xff0000) >> 10);
 G = ((pixelValue & 0xff00) >> 2);
于 2013-07-18T12:07:42.253 に答える