根据http://developer.android.com/reference/android/graphics/ImageFormat.html#NV21,NV21是默认使用的格式。
网上有很多关于YUV NV21到RGB转换的代码。但是,当我查看代码时,我怀疑代码的正确性。
第一个组件V应首先出现,然后是第一个组件U
根据http://wiki.videolan.org/YUV#NV21,NV21 is like NV12, but with U and V order reversed: it starts with V.
然而,当我完成代码实现时
R应该是最重要的位置
根据{{3}}中int argb
的实现,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;
}
}
}
答案 0 :(得分:12)
首先,我对图像编码没有超级经验(大约一年前对此有一定的了解)。所以,请用我的答案。
但是,我相信你是对的。我认为在他们的代码中 a)翻转V和U. b)R和B被翻转
我有一种感觉,当这些东西都被翻转时,它会产生相同的结果,好像它们没有被翻转一样。这就是为什么你可以在许多地方找到错误的代码的原因(最初,有人弄错了,并且在它被复制到整个地方之后,因为生成的代码有效(但是,变量命名不正确))。
这是另一个代码示例(与您的代码相同): http://www.41post.com/3470/programming/android-retrieving-the-camera-preview-as-a-pixel-array
答案 1 :(得分:0)
“最重要的位置”之类的术语含糊不清,因为它取决于机器的结尾。
当所有数据类型都是8位时,有一个简单明确的规范:字节顺序。例如, unsigned char rgba [4]; 将数据存储为 rgba [0] = r; rgba [1] = g; rgba [2] = b; rgba [3] = a;
或{r,g,b,a},无论处理器的字节顺序如何。
如果你做了
int32 color =(r <&lt; 24)| (g <&lt; 16)| (b <&lt; 8)| (a&lt;&lt; 0);
你会得到的 {r,g,b,a} 在大端系统上,和 {a,r,g,b} 在小端系统上。 您是否在具有异构处理器的系统上工作?也许你有CPU和GPU?他们如何知道对方使用的是哪个端?你最好定义字节顺序。