概述
#include <QtCore/QCoreApplication>
#include <QFile>
#include <QDebug>
#include <QApplication>
#include <QImage>
#include <QLabel>
#include <QPixmap>
#include <opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
#define WIDTH 1920
#define HEIGHT 1088
//改方法转换下会有色差;
void NV12_To_RGB(unsigned int width, unsigned int height, unsigned char *yuyv, unsigned char *rgb)
{
const int nv_start = width * height;
int i, j, index = 0, rgb_index = 0;
unsigned char y, u, v;
int r, g, b, nv_index = 0;
for (i = 0; i < height; i++)
{
for (j = 0; j < width; j++)
{
//nv_index = (rgb_index / 2 - width / 2 * ((i + 1) / 2)) * 2;
nv_index = i / 2 * width + j - j % 2;
y = yuyv[rgb_index];
// u = yuyv[nv_start + nv_index];
// v = yuyv[nv_start + nv_index + 1];
u = yuyv[nv_start + nv_index + 1];
v = yuyv[nv_start + nv_index];
r = y + (140 * (v - 128)) / 100; //r
g = y - (34 * (u - 128)) / 100 - (71 * (v - 128)) / 100; //g
b = y + (177 * (u - 128)) / 100; //b
if (r > 255)
r = 255;
if (g > 255)
g = 255;
if (b > 255)
b = 255;
if (r < 0)
r = 0;
if (g < 0)
g = 0;
if (b < 0)
b = 0;
index = i * width + j;// rgb_index % width + (height - i - 1) * width;
rgb[index * 3 + 0] = b;
rgb[index * 3 + 1] = g;
rgb[index * 3 + 2] = r;
rgb_index++;
}
}
}
//opencv转换nv12到rgb;
bool YV12ToBGR24_OpenCV(unsigned char* pYUV,int width, int height)
{
if (width < 1 || height < 1 || pYUV == NULL)
return false;
Mat dst(height, width, CV_8UC3);
Mat src(height + height / 2, width, CV_8UC1, pYUV);
cvtColor(src, dst, CV_YUV2BGR_NV12);
imwrite("dst_Opencv.png", dst);
return true;
}
/*
功能:NV12 转 RGB24
耗时:210ms左右
使用举例:NV12_to_rgb24(0, srcSlice[0], RGB24, tex_w, tex_h) ;
因为没有区分 格式,因此第一个参数 随便写,
同时定义一个转换之后的指针:
unsigned char RGB24[1920*1080*10] = {0};
*/
static long int crv_tab[256];
static long int cbu_tab[256];
static long int cgu_tab[256];
static long int cgv_tab[256];
static long int tab_76309[256];
static unsigned char clp[1024]; //for clip in CCIR601
void init_yuv420p_table()
{
long int crv, cbu, cgu, cgv;
int i, ind;
static int init = 0;
if (init == 1) return;
crv = 104597; cbu = 132201; /* fra matrise i global.h */
cgu = 25675; cgv = 53279;
for (i = 0; i < 256; i++)
{
crv_tab[i] = (i - 128) * crv;
cbu_tab[i] = (i - 128) * cbu;
cgu_tab[i] = (i - 128) * cgu;
cgv_tab[i] = (i - 128) * cgv;
tab_76309[i] = 76309 * (i - 16);
}
for (i = 0; i < 384; i++)
clp[i] = 0;
ind = 384;
for (i = 0; i < 256; i++)
clp[ind++] = i;
ind = 640;
for (i = 0; i < 384; i++)
clp[ind++] = 255;
init = 1;
}
/*
函数功能:将NV12或者NV21格式数据 转换成RGB24
参数说明:
frame_type:指的是pixfmt.h中结构体 AVPixelFormat 中对应的帧格式
*/
enum class FRAME_TYPE {
NV12 = 0,
NV21
};
void NV12_or_NV21_to_rgb24(FRAME_TYPE frame_type, unsigned char* yuvbuffer, unsigned char* rgbbuffer, int width, int height)
{
int y1, y2, u, v;
unsigned char *py1, *py2;
int i, j, c1, c2, c3, c4;
unsigned char *d1, *d2;
unsigned char *src_u;
static int init_yuv420p = 0;
src_u = yuvbuffer + width * height; // u
py1 = yuvbuffer; // y
py2 = py1 + width;
d1 = rgbbuffer;
d2 = d1 + 3 * width;
init_yuv420p_table();
for (j = 0; j < height; j += 2)
{
for (i = 0; i < width; i += 2)
{
if (frame_type == FRAME_TYPE::NV12)
{
u = *src_u++;
v = *src_u++; // v紧跟u,在u的下一个位置
}
if (frame_type == FRAME_TYPE::NV21)
{
v = *src_u++;
u = *src_u++; // u紧跟v,在v的下一个位置
}
c1 = crv_tab[v];
c2 = cgu_tab[u];
c3 = cgv_tab[v];
c4 = cbu_tab[u];
//up-left
y1 = tab_76309[*py1++];
*d1++ = clp[384 + ((y1 + c1) >> 16)];
*d1++ = clp[384 + ((y1 - c2 - c3) >> 16)];
*d1++ = clp[384 + ((y1 + c4) >> 16)];
//down-left
y2 = tab_76309[*py2++];
*d2++ = clp[384 + ((y2 + c1) >> 16)];
*d2++ = clp[384 + ((y2 - c2 - c3) >> 16)];
*d2++ = clp[384 + ((y2 + c4) >> 16)];
//up-right
y1 = tab_76309[*py1++];
*d1++ = clp[384 + ((y1 + c1) >> 16)];
*d1++ = clp[384 + ((y1 - c2 - c3) >> 16)];
*d1++ = clp[384 + ((y1 + c4) >> 16)];
//down-right
y2 = tab_76309[*py2++];
*d2++ = clp[384 + ((y2 + c1) >> 16)];
*d2++ = clp[384 + ((y2 - c2 - c3) >> 16)];
*d2++ = clp[384 + ((y2 + c4) >> 16)];
}
d1 += 3 * width;
d2 += 3 * width;
py1 += width;
py2 += width;
}
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QFile l_file("nv12");
if (l_file.open(QIODevice::ReadOnly) == false)
{
qDebug() << "open file error";
return 0;
}
QByteArray l_array = l_file.readAll();
qDebug() << "file size : " << l_array.size() / 1024 << "kb";
char* l_nvData = l_array.data();
QImage l_image = QImage(WIDTH, HEIGHT, QImage::Format_RGB888);
uchar* l_rgbData = l_image.bits();
//NV12_T_RGB(WIDTH, HEIGHT, (uchar*)l_nvData, l_rgbData);
NV12_or_NV21_to_rgb24( FRAME_TYPE::NV12,(uchar*)l_nvData, l_rgbData, WIDTH, HEIGHT);
//使用opencv转换;
YV12ToBGR24_OpenCV((uchar*)l_nvData, WIDTH, HEIGHT);
l_image.save("dst.png");
QLabel* l_label = new QLabel;
l_label->setPixmap(QPixmap::fromImage(l_image));
l_label->show();
return a.exec();
}
有使用公式转换和opencv进行转换
算法来源:
https://blog.csdn.net/yuanwuwei/article/details/85340134
https://blog.csdn.net/morixinguan/article/details/52671706
最后
以上就是怕孤单夏天为你收集整理的NV12转RGB24算法的全部内容,希望文章能够帮你解决NV12转RGB24算法所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复