web-dev-qa-db-ja.com

YUV NV21からRGBへの変換に関する混乱

http://developer.Android.com/reference/Android/graphics/ImageFormat.html#NV21 によると、NV21はデフォルトで使用される形式です。

YUV NV21からRGBへの変換に関して、Web上には非常に多くのコードがあります。ただし、コードを調べてみると、コードの正確性には疑問があります。

最初のコンポーネントVが最初に来て、その後に最初のコンポーネントUが続きます

http://wiki.videolan.org/YUV#NV21NV21 is like NV12, but with U and V order reversed: it starts with V.ただし、コードの実装を行ったとき

Rが最も重要な位置でなければなりませんint argb in Color.Java 、Rは、最も重要な位置にあるとします。しかし、私は次のコード実装を試しました

私は疑問に思っていました、彼らはよく間違えているのですか、それとも何かを見落としていましたか?

現在、私の実装は次のとおりです。

public static void YUV_NV21_TO_RGB(int[] argb, byte[] yuv, int width, int height) {
    final int frameSize = width * height;

    final int ii = 0;
    final int ij = 0;
    final int di = +1;
    final int dj = +1;

    int a = 0;
    for (int i = 0, ci = ii; i < height; ++i, ci += di) {
        for (int j = 0, cj = ij; j < width; ++j, cj += dj) {
            int y = (0xff & ((int) yuv[ci * width + cj]));
            int v = (0xff & ((int) yuv[frameSize + (ci >> 1) * width + (cj & ~1) + 0]));
            int u = (0xff & ((int) yuv[frameSize + (ci >> 1) * width + (cj & ~1) + 1]));
            y = y < 16 ? 16 : y;

            int r = (int) (1.164f * (y - 16) + 1.596f * (v - 128));
            int g = (int) (1.164f * (y - 16) - 0.813f * (v - 128) - 0.391f * (u - 128));
            int b = (int) (1.164f * (y - 16) + 2.018f * (u - 128));

            r = r < 0 ? 0 : (r > 255 ? 255 : r);
            g = g < 0 ? 0 : (g > 255 ? 255 : g);
            b = b < 0 ? 0 : (b > 255 ? 255 : b);

            argb[a++] = 0xff000000 | (r << 16) | (g << 8) | b;
        }
    }
}
32
Cheok Yan Cheng

まず第一に、私は画像のエンコードについてあまり経験がありません(約1年前にこれにある程度の露出がありました)。だから、塩の粒で私の答えを取る。

しかし、私はあなたが正しいと信じています。私は彼らのコードでa)VとUが反転していると思うb)RとBが反転している

私は、これらの両方がひっくり返されると、あたかもひっくり返されたかのように同じ結果を生むと感じています。これが、多くの場所で間違ったコードを見つけることができる理由です(元々、結果のコードが機能するために誰かが間違って、それがすべての場所にコピーされた後です(ただし、変数の名前が間違っています))。

コードの別の例(これはあなたのものと同じように機能します): http://www.41post.com/3470/programming/Android-retrieving-the-camera-preview-as-a-pixel-array

12
Victor Ronin

「最上位の位置」などの用語は、マシンのエンディアンに依存するため、あいまいです。

すべてのデータ型が8ビットの場合、簡単な明確な仕様、バイトオーダーがあります。たとえば、unsigned char rgba [4];データはrgba [0] = rとして保存されます。 rgba [1] = g; rgba [2] = b; rgba [3] = a;

または、プロセッサのエンディアンに関係なく{r、g、b、a}。

代わりにした場合

int32 color =(r << 24)| (g << 16)| (b << 8)| (a << 0);

ビッグエンディアンシステムでは{r、g、b、a}を取得し、リトルエンディアンシステムでは{a、r、g、b}を取得します。異種プロセッサを搭載したシステムで作業していますか? CPUとGPUを持っているかもしれませんか?彼らは、他のエンディアンがどのエンディアンを使用しているかをどのように知るのですか?バイト順を定義する方がはるかに良いでしょう。

0
Reality Pixels