Android 关于YUV NV21转换为RGB的混淆

Android 关于YUV NV21转换为RGB的混淆,android,nv12-nv21,Android,Nv12 Nv21,根据,NV21是默认使用的格式 网上有很多关于YUVNV21到RGB转换的代码。然而,当我阅读代码时,我怀疑代码的正确性 第一个分量V应排在第一位,然后是第一个分量U 根据,NV21与NV12类似,但U和V顺序相反:它以V开头。然而,当我完成代码实现时 -假设你先来 -它假设你也是第一位的 -好像你也是第一个 R应该是最重要的位置 根据中int argbin的实现,假设R位于最重要的位置。但是,我完成了以下代码实现 -假设R处于最低有效位置 -假设R处于最低有效位置 我在想,他们是犯了常

根据,NV21是默认使用的格式

网上有很多关于YUVNV21到RGB转换的代码。然而,当我阅读代码时,我怀疑代码的正确性

第一个分量V应排在第一位,然后是第一个分量U

根据,
NV21与NV12类似,但U和V顺序相反:它以V开头。
然而,当我完成代码实现时

  • -假设你先来
  • -它假设你也是第一位的
  • -好像你也是第一个
R应该是最重要的位置 根据中
int argb
in的实现,假设R位于最重要的位置。但是,我完成了以下代码实现

  • -假设R处于最低有效位置
  • -假设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;
        }
    }
}
public static void YUV_NV21_TO_RGB(int[]argb,byte[]YUV,int width,int height){
最终整数帧大小=宽度*高度;
最终int ii=0;
最终int ij=0;
最终整数di=+1;
最终整数dj=+1;
int a=0;
对于(int i=0,ci=ii;i>1)*width+(cj&~1)+0]);
intu=(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));
INTG=(int)(1.164f*(y-16)-0.813f*(v-128)-0.391f*(u-128));
INTB=(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首先,我对图像编码不是很有经验(大约一年前我对这方面的接触有限)。因此,请对我的回答持保留态度

然而,我相信你是对的。我认为在他们的代码中 a) V和U翻转 b) R和b是翻转的

我有一种感觉,当这两个东西都被翻转时,它会产生相同的结果,就像它们没有被翻转一样。这就是为什么你可以在很多地方找到错误代码的原因(最初,有人把它弄错了,在它被复制到所有地方之后,因为结果代码工作正常(但是,变量命名不正确))

下面是另一个代码示例(其工作原理与您的相同): 像“最高有效位置”这样的术语是不明确的,因为它取决于机器的尾端

当所有数据类型都是8位时,有一个简单明确的规范:字节顺序。例如, 无符号字符rgba[4]; 将数据存储为 rgba[0]=r; rgba[1]=g; rgba[2]=b; rgba[3]=a

或{r,g,b,a},与处理器的端性无关

如果你这样做了


int32 color=(对我来说,您的代码工作得非常完美,实际上是唯一一个不改变任何图片属性(如亮度或颜色)的代码。在许多采用颜色参数或以int形式返回颜色的android函数中,它们返回时R最为重要,因此为0xAARRGGB。然而,在android位图的实际内存布局中,当您直接使用JNI并以C/C++字节访问时,它与R相反,R是内存中的第一个字节,您得到0xAABBGGRR。阅读规范问题链接到:指定了little endian字节顺序。此外,问题标记为Android,所有支持的Android版本都使用little endian硬件。