当前位置:网站首页>Convert yv12 to rgb565 image conversion, with YUV to RGB test
Convert yv12 to rgb565 image conversion, with YUV to RGB test
2022-07-02 10:47:00 【Small waves-】
background :
Many years ago , I have made a long-term playback client , There's a problem , Some monitors cannot display YV12 Video images , Need to be converted to RGB Show , Is to use such a functional method , convert , Then insert the data into Frame Display , Here is the code used .
transformation YUV420P To RGB565, And write ddraw Surface memory pdst in , First create the conversion table , Then convert each pixel .
Code
int* colortab;
int* u_b_tab;
int* u_g_tab;
int* v_g_tab;
int* v_r_tab;
unsigned int * r_2_pix;
unsigned int * g_2_pix;
unsigned int * b_2_pix;
// Create conversion table
void CreateYUVTab()
{
int i;
int u, v;
colortab = (int *)malloc(4*256*sizeof(int));
u_b_tab = &colortab[0*256];
u_g_tab = &colortab[1*256];
v_g_tab = &colortab[2*256];
v_r_tab = &colortab[3*256];
for (i=0; i<256; i++)
{
u = v = (i-128);
u_b_tab[i] = (int) ( 1.772 * u);
u_g_tab[i] = (int) ( 0.34414 * u);
v_g_tab[i] = (int) ( 0.71414 * v);
v_r_tab[i] = (int) ( 1.402 * v);
}
rgb_2_pix = (unsigned int *)malloc(3*768*sizeof(unsigned int));
r_2_pix = &rgb_2_pix[0*768];
g_2_pix = &rgb_2_pix[1*768];
b_2_pix = &rgb_2_pix[2*768];
for(i=0; i<256; i++)
{
r_2_pix[i] = 0;
g_2_pix[i] = 0;
b_2_pix[i] = 0;
}
for(i=0; i<256; i++)
{
r_2_pix[i+256] = (i & 0xF8) << 8;
g_2_pix[i+256] = (i & 0xFC) << 3;
b_2_pix[i+256] = (i ) >> 3;
}
for(i=0; i<256; i++)
{
r_2_pix[i+512] = 0xF8 << 8;
g_2_pix[i+512] = 0xFC << 3;
b_2_pix[i+512] = 0x1F;
}
r_2_pix += 256;
g_2_pix += 256;
b_2_pix += 256;
}
// transformation YUV420P To RGB565, And write ddraw Surface memory pdst in
//y,u,v Three vector byte sequences
//src_ystride The source of y Line width
//src_uvstride The source of uv Line width
//dst_ystride Destination row width
void DisplayYUV(unsigned int *pdst, unsigned char *y, unsigned char *u, unsigned char *v, int width, int height, int src_ystride, int src_uvstride, int dst_ystride)
{
int i, j;
int r, g, b, rgb;
int yy, ub, ug, vg, vr;
const int width2 = width/2;// Half the width of the image
const int height2 = height/2;// Half the height of the image
unsigned char* yoff;
unsigned char* uoff;
unsigned char* voff;
for(j=0; j<height2; j++)// Line by line
{
yoff = y + j * 2 * src_ystride;
uoff = u + j * src_uvstride;
voff = v + j * src_uvstride;
for(i=0; i<width2; i++)// Column by column cycle
{
yy = *(yoff+(i<<1));
ub = u_b_tab[*(uoff+i)];
ug = u_g_tab[*(uoff+i)];
vg = v_g_tab[*(voff+i)];
vr = v_r_tab[*(voff+i)];
b = yy + ub;
g = yy - ug - vg;
r = yy + vr;
rgb = r_2_pix[r] + g_2_pix[g] + b_2_pix[b];
yy = *(yoff+(i<<1)+1);
b = yy + ub;
g = yy - ug - vg;
r = yy + vr;
pdst[(j*dst_ystride+i)] = (rgb)+((r_2_pix[r] + g_2_pix[g] + b_2_pix[b])<<16);
yy = *(yoff+(i<<1)+src_ystride);
b = yy + ub;
g = yy - ug - vg;
r = yy + vr;
rgb = r_2_pix[r] + g_2_pix[g] + b_2_pix[b];
yy = *(yoff+(i<<1)+src_ystride+1);
b = yy + ub;
g = yy - ug - vg;
r = yy + vr;
pdst [((2*j+1)*dst_ystride+i*2)>>1] = (rgb)+((r_2_pix[r] + g_2_pix[g] + b_2_pix[b])<<16);
}
}
}
Conversion formula
RGB to YUV Conversion
Y = (0.257 * R) + (0.504 * G) + (0.098 * B) + 16
Cr = V = (0.439 * R) - (0.368 * G) - (0.071 * B) + 128
Cb = U = -(0.148 * R) - (0.291 * G) + (0.439 * B) + 128
YUV to RGB Conversion
B = 1.164(Y - 16) + 2.018(U - 128)
G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128)
R = 1.164(Y - 16) + 1.596(V - 128)
Reference resources
http://forum.videohelp.com/topic290086.html
I played a little with the code, and I found the right conversion formulas:
#define GETR(y,u,v) ((1.164 * (y - 16)) + (1.596 * ((v) - 128)))
#define GETG(y,u,v) ((1.164 * (y - 16)) - (0.813 * ((v) - 128)) - (0.391 * ((u) - 128)))
#define GETB(y,u,v) ((1.164 * (y - 16)) + (2.018 * ((u) - 128)))
Images seems to be in the right color using these formulas.
Transform function test cases
#include <TIME.H>
#include <stdio.h>
#include <windows.h>
#include <stdlib.h>
#include <iostream>
#include <fstream>
using namespace std;
void YUV2RGB(unsigned char Y, unsigned char U, unsigned char V, unsigned char* pRGB)
{
int R, G, B;
B = (int)(1.164*(Y - 16) + 2.018*(U - 128));
G = (int)(1.164*(Y - 16) - 0.813*(V - 128) - 0.391*(U - 128));
R = (int)(1.164*(Y - 16) + 1.596*(V - 128));
// #define GETR(y,u,v) ((1.164 * (y - 16)) + (1.596 * ((v) - 128)))
// #define GETG(y,u,v) ((1.164 * (y - 16)) - (0.813 * ((v) - 128)) - (0.391 * ((u) - 128)))
// #define GETB(y,u,v) ((1.164 * (y - 16)) + (2.018 * ((u) - 128)))
//cout << "RGB("<<GETR(y,u,v)<<","<<GETG(y,u,v)<<","<<GETB(y,u,v)<<","<<")"<<endl;
//cout << "("<<(int)Y<<","<<(int)U<<","<<(int)V<<")->RGB("<<R<<","<<G<<","<<B<<","<<")"<<endl;
R= min(255,max(0,R));
G= min(255,max(0,G));
B= min(255,max(0,B));
pRGB[0] = R ;
pRGB[1] = G;
pRGB[2] = B;
return;
}
void RGB2YUV(unsigned char R, unsigned char G, unsigned char B, unsigned char* pYUV)
{
int Y, U, V;
Y = 16 + 0.257*R + 0.504*G + 0.098*B;
U = 128 - 0.148*R - 0.291*G + 0.439*B;
V = 128 + 0.439*R - 0.368*G - 0.071*B;
Y= min(255,max(0,Y));
U= min(255,max(0,U));
V= min(255,max(0,V));
pYUV[0] = Y;
pYUV[1] = U;
pYUV[2] = V;
return;
}
int __cdecl main (int argc, CHAR **argv)
{
unsigned char RGB[3];
unsigned char YUV[3];
int r=255,g=0,b=0;
RGB2YUV(r, g, b, YUV);
cout << "("<<(unsigned int)(YUV[0])<<","<<(unsigned int)(YUV[1])<<","<<(unsigned int)(YUV[2])<<")->RGB("<<r<<","<<g<<","<<b<<","<<")"<<endl;
int y=(unsigned int)(YUV[0]),u=(unsigned int)(YUV[1]),v=(unsigned int)(YUV[2]);
YUV2RGB(y, u, v, RGB);
cout << "("<<(int)y<<","<<(int)u<<","<<(int)v<<")->RGB("<<(unsigned int)(RGB[0])<<","<<(unsigned int)(RGB[1])<<","<<(unsigned int)(RGB[2])<<","<<")"<<endl;
system( "PAUSE" );
return 0;
}
边栏推荐
猜你喜欢
Session cookies and tokens
shell编程01_Shell基础
Kustomize user manual
"Talking about podcasts" vol.352 the age of children: breaking the inner scroll, what can we do before high school?
《实习报告》Skywalking分布式链路追踪?
How to get the password of cpolar?
Sum the two numbers to find the target value
LeetCode+ 76 - 80 暴搜专题
Mysql database remote access permission settings
Understand the composition of building energy-saving system
随机推荐
(五)APA场景搭建之挡位控制设置
js promise. all
Windows环境MySQL8忘记密码文件解决方案
What are the popular frameworks for swoole in 2022?
Nonlinear optimization: establishment of slam model
ERROR 1118 (42000): Row size too large (&gt; 8126)
[SUCTF2018]followme
集成学习概览
(5) Gear control setting of APA scene construction
Stm32 et développement de moteurs (système supérieur)
2021-10-04
Record attributeerror: 'nonetype' object has no attribute 'nextcall‘
Mongodb quickly get started with some simple operations of mongodb command line
简洁、快速、节约内存的Excel处理工具EasyExcel
Blender model import UE, collision settings
In the face of uncertainty, the role of supply chain
[pit avoidance guide] pit encountered using ugui: the text component cannot indent the first line by two spaces
[Lua] summary of common knowledge points (including common interview sites)
UVM learning - build a simple UVM verification platform
[unity3d] cannot correctly obtain the attribute value of recttransform, resulting in calculation error