我是靠谱客的博主 怕孤单夏天,最近开发中收集的这篇文章主要介绍NV12转RGB24算法,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

#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算法所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(37)

评论列表共有 0 条评论

立即
投稿
返回
顶部