两种方式,一种通过cvCvtColor,一种通过自己写的转换子函数
出来的bmp完全相同
#include <highgui.h>
#include "cv.h"#include <stdio.h>
#define MR(Y,U,V) (Y + (1.403)*(V-128))
#define MG(Y,U,V) (Y - (0.344) * (U-128) - (0.714) * (V-128) )
#define MB(Y,U,V) (Y + ((1.773) * (U-128)))
#define nWidth 1280
#define nHeight 720
#define nSize nWidth*nHeight*3/2
#define FrameSize nWidth*nHeight*3/2
void YUV420_C_RGB (char* pYUV, unsigned char* pRGB, int height, int width)
{
char* pY = pYUV;
char* pU = pYUV + height*width;
char* pV = pU + (height*width / 4);
unsigned char* pBGR = NULL;
unsigned char R = 0;
unsigned char G = 0;
unsigned char B = 0;
char Y = 0;
char U = 0;
char V = 0;
double tmp = 0;
for (int i = 0; i < height; ++i)
{
for (int j = 0; j < width; ++j)
{
pBGR = pRGB + i*width * 3 + j * 3;
Y = *(pY + i*width + j);
U = *pU;
V = *pV;
//B
tmp = MB (Y, U, V);
//B = (tmp > 255) ? 255 : (char)tmp;
//B = (B<0) ? 0 : B;
B = (unsigned char) tmp;
//G
tmp = MG (Y, U, V);
//G = (tmp > 255) ? 255 : (char)tmp;
// G = (G<0) ? 0 : G;
G = (unsigned char) tmp;
//R
tmp = MR (Y, U, V);
//R = (tmp > 255) ? 255 : (char)tmp;
//R = (R<0) ? 0 : R;
R = (unsigned char) tmp;
*pBGR = R;
*(pBGR + 1) = G;
*(pBGR + 2) = B;
if (i % 2 == 0 && j % 2 == 0)
{
*pU++;
//*pV++;
}
else
{
if (j % 2 == 0)
{
*pV++;
}
}
}
}
}
int main (int argc, char* argv [])
{
FILE *f;
if (!(f = fopen ("i:\\in_to_tree_420_720p50.yuv", "rb")))
{
printf ("file open error!");
}
// calculate the frame num
fseek (f, 0, SEEK_END);
int frame_count = 0;
long file_size = 0;
frame_count = (int) ((int) ftell (f) / ((nWidth * nHeight * 3) / 2)); // ftell 用于求文件大小
printf ("frame num is %d \n", frame_count);
printf ("file length is %d", ftell (f));
fseek (f, 0, SEEK_SET);//文件内位置定位到文件头
IplImage *rgbimg = cvCreateImage (cvSize (nWidth, nHeight), IPL_DEPTH_8U, 3);
IplImage *image = cvCreateImage (cvSize (nWidth, nHeight), IPL_DEPTH_8U, 3);
IplImage *yimg = cvCreateImage (cvSize (nWidth, nHeight), IPL_DEPTH_8U, 1);
IplImage *uimg = cvCreateImageHeader (cvSize (nWidth / 2, nHeight / 2), IPL_DEPTH_8U, 1);
IplImage *vimg = cvCreateImageHeader (cvSize (nWidth / 2, nHeight / 2), IPL_DEPTH_8U, 1);
IplImage *uuimg = cvCreateImage (cvSize (nWidth, nHeight), IPL_DEPTH_8U, 1);
IplImage *vvimg = cvCreateImage (cvSize (nWidth, nHeight), IPL_DEPTH_8U, 1);
//----------------------------------------------------------------------读取yuv文件的y部分 类似于播放器效果
char *pBuf = new char[nWidth*nHeight * 3 / 2];
int pos = 0;
// for (int i = 0; i < frame_count - 1; i++)
// {
int i = 1;
printf ("frame %d/%d\n", i, frame_count);
fseek (f, pos, SEEK_SET);
fread (pBuf, 1, FrameSize, f);
cvSetData (yimg, pBuf, nWidth);
cvSetData (vimg, pBuf + nWidth * nHeight, nWidth / 2);
cvSetData (uimg, pBuf + long (nWidth * nHeight * 1.25), nWidth / 2);
cvResize (uimg, uuimg, CV_INTER_NN);
cvResize (vimg, vvimg, CV_INTER_NN);
cvMerge (yimg, vvimg, uuimg, NULL, image); //yuv输入 但是420 iyuv 是yvu
cvCvtColor (image, rgbimg, CV_YCrCb2RGB);
cvNamedWindow ("RGB");
cvShowImage ("RGB", rgbimg);
cvSaveImage ("m:\\RGB.bmp", rgbimg);
cvWaitKey (10);
pos += FrameSize;
// }
cvDestroyWindow ("RGB");
unsigned char* pRGB = NULL;
pRGB = (unsigned char*) malloc (nSize*sizeof (unsigned char*) * 2);
YUV420_C_RGB (pBuf, pRGB, nWidth, nHeight);
IplImage *img;
img = cvCreateImageHeader (cvSize (nWidth, nHeight), IPL_DEPTH_8U, 3);
cvSetData (img, pRGB, nWidth * 3);
cvSaveImage ("m:\\rgb-1.bmp", rgbimg);
//cvReleaseImage (&yimg);
delete []pBuf;
fclose (f);
return 0;
}