YUV와 YIQ는 TV에 사용되는 색 표현방식이다.
YUV방식은 사람의 눈이 색상보다는 밝기에 민감하다는 사실에 착안한 방식으로,
색을 밝기(Luminance)인 Y성분과 색상(Chrominance)인 U(Cb)와 V(Cr) 성분으로
구분한다.
Y성분은 오차에 민감하므로 색상성분인 U와 V보다 많은 비트를 코딩한다.
전형적인 Y:U:V의 비율은 4:2:2 이다.
YUV 방식은 CD-I와 DYI (Digital Video Interactive)에서도 사용된다.
(Y 성분은 이미지를 Gray로 만든 것과 같다)
왜 RGB 정보를 그냥 이용하지 않고 YUV로 포맷을 변화시키냐면,
단순히 RGB 정보로 그 값을 기록했을 경우보다 YUV를 통하면 더 작은 데이터를
만들어내서, 특히 대역폭(bandwidth)이 낮은
경우에 적합하게 표현할 수 있기 때문이다
+주의점+
YUV 파일 형식은, U,V data의 배열에 따라 Direction이 존재하는데 보통
Direction Vertical의 YUV420을 주로 사용한다.
그래서 파일로 저장할때는, Direction을 염두에 두고, 파일에 저장해야 하는데-
Direction Vertical은 Y에 덧붙여 U를 쓰고, V를 모두 쓴다
Direction Horizontal은 Y에 덧붙여서 U를 width/2 화소만큼,
V를 width/2 화소만큼 번갈아가며 저장하게 된다
저장방법이 복잡해서 Direction Vertical을 주로 쓴다
(1) 전형적 Y:U:V 비율은 4:2:2로,, Y 4픽셀당 U, V는 2픽셀씩이라는 의미임.
ex> YUYV,YUYV,YUYV..
변환식은-
______________________________________________
Y = 0.3*R + 0.59*G + 0.11*B
U = (B-Y) x 0.493
V = (R-Y) x 0.877
..or..
Y = 0.299f * R + 0.587f * G + 0.114f * B;
U = -0.1687f * R - 0.3313f * G + 0.5f * B + 128;
V = 0.5f*R - 0.4187f*G - 0.0813f*B + 128;
R = Y + 0.956*U + 0.621*V
G = Y + 0.272*U + 0.647*V
B = Y + 1.1061*U + 1.703*V
R = 1.00000*Y + 1.40200*V;
G = 1.00000*Y - 0.34414*U - 0.71414*V;
B = 1.00000*Y + 1.77200*U;
R = 1.164*(Y - 16.0) + 1.596*(V - 128.0);
G = 1.164*(Y - 16.0) - 0.813*(V - 128.0) - 0.391*(U - 128.0);
B = 1.164*(Y - 16.0) + 2.018*(U - 128.0);
───────────────────────────────
...
(2) Y:U:V 비율이 4:2:0인 경우,, Y 4픽셀 당 U, V는 가로/세로 2픽셀당
1픽셀씩이라는 의미임.
ex> 4x4 이미지일 경우,,
Y1 Y2 Y3 Y4 Y5 Y6 Y7 Y8 Y9 Y10 Y11 Y12 Y13 Y14 Y15 Y16 U1 U2 U3 U4
V1 V2 V3 V4..
(3) Y:U:V 4:1:1은 화상을 구성하는 화소를 4개씩 묶어서 각각의 휘도(Y)를 샘플링하고, 색차(U,V)는 4개의 화소의 평균값을 취한다.
그러므로 4개의 화소에 4개의 휘도( Y)와 각 1개씩의 색차(U,V)가 있으므로
전체 6개의 샘플이 된다
ex > U2 Y0 Y1 V2 Y2 Y3
(4) YUV444에서 YUV420으로 변환하는 경우,, UV의 4화소를 평균하여 1화소로
바꿔 줄여준다
bool Yuv4442Yuv420(BYTE*U444,BYTE*V444,BYTE *U,BYTE *V,int wid,int hei)
{
int i, j;
register int addr;
register int pos0, pos1, pos2, pos3;
addr = 0;
for (i=0; i<hei; i+=2) for(j=0; j<wid; j+=2)
{
pos0 = i*wid + j; pos1 = pos0 + 1;
pos2 = pos0 + wid; pos3 = pos2 + 1;
//오른쪽 쉬프트 연산 2번
U[addr] = (BYTE)MyClip(((int)
U444[pos0]+(int)U444[pos1]+(int)U444[pos2]+(int)U444[pos3])>>2);
//즉 나누기 4 : 평균내기
V[addr] = (BYTE)MyClip(((int)
V444[pos0]+(int)V444[pos1]+(int)V444[pos2]+(int)V444[pos3])>>2);
addr++;
}
return true;
}