混乱的YUV NV21转换为RGB [英] Confusion on YUV NV21 conversion to RGB
问题描述
据<一href="http://developer.android.com/reference/android/graphics/ImageFormat.html#NV21">http://developer.android.com/reference/android/graphics/ImageFormat.html#NV21, NV21是默认使用的格式。
有相当数量的code网络上关于YUV NV21到RGB转换。然而,当我经过code,我怀疑的code是正确的。
第一分量V应该是第一位的,其次是第一个组件U
据<一href="http://msdn.microsoft.com/en-us/library/ms867704.aspx#yuvformats_420formats_12bitsperpixel">http://wiki.videolan.org/YUV#NV21, NV21就像是NV12,但与U和V顺序颠倒:它采用V开头
然而,当我在code实现去
- http://pastebin.com/T0my7zSc - 它假定ü至上
- http://stackoverflow.com/a/8394202/72437 - 它假定ü至上太李>
- http://stackoverflow.com/a/10125048/72437 - 它assmesü至上太李>
研究应该是最有显著位置
根据实施 INT的argb
的<一个href="http://www.netmite.com/android/mydroid/frameworks/base/graphics/java/android/graphics/Color.java">Color.java, ř假设是在最显著的位置。但是,我通过以下code实现去
- http://pastebin.com/T0my7zSc - 它假定r是至少显著位置
- http://stackoverflow.com/a/8394202/72437 - 它假定r是至少显著位置
我在想,是他们使常见的错误,或者我忽略了一些东西?
目前,我实现如下。
公共静态无效YUV_NV21_TO_RGB(INT [] ARGB,byte []的YUV,诠释的宽度,高度INT){
最终诠释框架尺寸=宽*高;
最终诠释II = 0;
最终诠释IJ = 0;
最终诠释迪= + 1;
最终诠释DJ = + 1;
INT一个= 0;
的for(int i = 0,CI = II; I&LT;高度; ++我,CI + =二){
对于(INT J = 0,CJ = IJ; J&LT;宽度; ++Ĵ,CJ + = DJ){
INT Y =(0xFF的及((int)的YUV [CI *宽+ CJ]));
INT V =(0xFF的及((int)的YUV [框架尺寸+(CI&GT;&GT; 1)*宽+(CJ&安培;〜1)+ 0]));
INT U =(0xFF的及((int)的YUV [框架尺寸+(CI&GT;&GT; 1)*宽+(CJ&安培;〜1)+ 1]));
Y = Y&LT; 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&LT; 0? 0:(R&GT; 255 255:ΔR);
G = G&LT; 0? 0:(g取代; 255 255:克);
B = b将0? 0:(B个255 255:二);
ARGB [A +] = 0xff000000 | (为r&所述; 16)| (G&LT;&LT; 8)| B:
}
}
}
首先,我不是超级经验与图像编码(有一些有限的接触到这个大约一年前)。所以,把我的回答与盐粮。
不过,我相信你是对的。我想,在他们的code这两种 A)V和U翻转 二)R和B翻转
我有一种感觉,当这两个东西翻转,它会产生相同的结果,如果他们不是'翻转。这就是为什么你可以找到错误的code在很多地方的原因(最初,有人听错了,它被复制遍布的地方,因为得到的code ++工程(但是,变量命名错误)之后)。
下面是code另一个例子(它的工作原理和你的一样): <一href="http://www.41post.com/3470/programming/android-retrieving-the-camera-$p$pview-as-a-pixel-array">http://www.41post.com/3470/programming/android-retrieving-the-camera-$p$pview-as-a-pixel-array
According to http://developer.android.com/reference/android/graphics/ImageFormat.html#NV21, NV21 is the default used format.
There are quite a number of code on web regarding YUV NV21 to RGB conversion. However, when I go through the code, I doubt on the correctness of the code.
The first component V should come first, followed by first component U
According to http://wiki.videolan.org/YUV#NV21, NV21 is like NV12, but with U and V order reversed: it starts with V.
However, when I went through the code implementation
- http://pastebin.com/T0my7zSc - It assumes U comes first
- http://stackoverflow.com/a/8394202/72437 - It assumes U comes first too
- http://stackoverflow.com/a/10125048/72437 - It assmes U comes first too
R should be the most significant position
According implementation of int argb
in Color.java, R suppose to be at the most significant position. However, I went through the following code implementation
- http://pastebin.com/T0my7zSc - It assumes R is in least significant position
- http://stackoverflow.com/a/8394202/72437 - It assumes R is in least significant position
I was wondering, are they making common mistake, or I have overlooked something?
Currently, my implementation is as follow.
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;
}
}
}
First of all, I am not super experienced with image encoding (has some limited exposure to this about a year ago). So, take my answer with grain of salt.
However, I believe you are right. I think in their code both a) V and U are flipped b) R and B are flipped
I have a feeling that when both of these things are flipped, it will produce the same result as if they arent' flipped. That's the reason why you can find wrong code in many places (originally, somebody got it wrong and after it was copied all over the places, because the resulting code works (however, variables named incorrectly)).
Here is another example of code (which works the same as yours): http://www.41post.com/3470/programming/android-retrieving-the-camera-preview-as-a-pixel-array
这篇关于混乱的YUV NV21转换为RGB的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!