RGB与UYVY之间的转换

const int BMP_WIDTH = 720;
const int BMP_HEIGTH = 576;
#define BMP_FILE _T(".\\res\\test1.bmp")
#define YUV_FILE _T(".\\res\\test.yuv")

/*RGBUYVY公式如下:

公式:(RGB => YCbCr)
Y = 0.257R′ + 0.504G′ + 0.098B′ + 16
Cb = -0.148R′ - 0.291G′ + 0.439B′ + 128
Cr = 0.439R′ - 0.368G′ - 0.071B′ + 128*/

void RGB2YUV(byte *pRGB, byte *pYUV)
{
byte r,g,b;
r = *pRGB; 
pRGB++;
g = *pRGB; 
pRGB++;
b = *pRGB;

*pYUV = static_cast<byte>(0.257*r + 0.504*g + 0.098*b + 16);// y 
pYUV++;
*pYUV = static_cast<byte>(-0.148*r - 0.291*g + 0.439*b + 128);// u
pYUV++;
*pYUV = static_cast<byte>(0.439*r - 0.368*g - 0.071*b + 128);// v
}

/*反变换公式

R= 1.0Y + 0 +1.402(V-128)

G= 1.0Y - 0.34413 (U-128)-0.71414(V-128)

B= 1.0Y + 1.772 (U-128)+0*/

void YUV2RGB(byte *pRGB, byte *pYUV)
{
byte y, u, v;
y = *pYUV; 
pYUV++;
u = *pYUV; 
pYUV++;
v = *pYUV;

*pRGB = static_cast<byte>(1.0*y + 8 + 1.402*(v-128));                // r
pRGB++; 
*pRGB = static_cast<byte>(1.0*y - 0.34413*(u-128) - 0.71414*(v-128));// g
pRGB++;
*pRGB = static_cast<byte>(1.0*y + 1.772*(u-128) + 0); // b
}

void WriteYUV(byte *pbyData1,byte *pbyData2,UINT size)
{
CFile* f;
f = new CFile();
CFileException ex;
f->Open(YUV_FILE,CFile::modeCreate | CFile::modeReadWrite,&ex);
TCHAR tcError[1024] = {0};
ex.GetErrorMessage(tcError,1024);

f->SeekToBegin();
f->Write((const void*)pbyData1,size);
f->Seek(size,0);
f->Write((const void*)pbyData2,size);
f->Close();
delete f;
f = NULL;
}

void doTestRGB2YUV()
{
CDC *pDC = GetDC();
CRect rect;
CBrush brush(RGB(128,128,128));
GetClientRect(&rect);
pDC->FillRect(&rect, &brush);

int CurrentXRes = BMP_WIDTH;
int CurrentYRes = BMP_HEIGTH;
int size        = CurrentXRes * CurrentYRes;

// 分配内存
byte *Video_Field0 = (byte*)malloc(CurrentXRes*CurrentYRes); 
byte *Video_Field1 = (byte*)malloc(CurrentXRes*CurrentYRes);

// 初始化内存
ZeroMemory(Video_Field0, CurrentXRes*CurrentYRes);
ZeroMemory(Video_Field1, CurrentXRes*CurrentYRes);

// 保存内存指针
byte *Video_Field0_ = Video_Field0;
byte *Video_Field1_ = Video_Field1;

byte yuv_y0, yuv_u0, yuv_v0, yuv_v1; // {y0, u0, v0, v1};
byte bufRGB[3]; // 临时保存{R,G,B}
byte bufYUV[3]; // 临时保存{Y,U,V}

// 初始化数组空间
ZeroMemory(bufRGB, sizeof(byte)*3);
ZeroMemory(bufYUV, sizeof(byte)*3);

// BMP 位图操作
BITMAPFILEHEADER bmfh;
BITMAPINFOHEADER bmih;

TRACE(_T("%d\t%d\n"),sizeof(BITMAPFILEHEADER),sizeof(BITMAPINFOHEADER));

CFile* f;
f = new CFile();
CFileException ex;
f->Open(BMP_FILE, CFile::modeRead,&ex);
TCHAR tcError[1024] = {0};
ex.GetErrorMessage(tcError,1024);
f->SeekToBegin();
f->Read(&bmfh, sizeof(bmfh));
f->Read(&bmih, sizeof(bmih));

// 分配图片像素内存
RGBTRIPLE *rgb;
rgb = new RGBTRIPLE[bmih.biWidth*bmih.biHeight];

f->SeekToBegin();
f->Seek(54,CFile::begin); // BMP 54个字节之后的是位像素数据
f->Read(rgb, bmih.biWidth * bmih.biHeight * 3); // 这里只读24位RGB(r,g,b)图像

// 上场 (1,3,5,7...行)
for (int i = bmih.biHeight-1; i>=0; i--) {
   for (int j = 0; j<bmih.biWidth; j++) {
    if(!(i%2)==0) 
    {
     bufRGB[0] = rgb[i*bmih.biWidth+j].rgbtRed;   //R
     bufRGB[1] = rgb[i*bmih.biWidth+j].rgbtGreen; // G
     bufRGB[2] = rgb[i*bmih.biWidth+j].rgbtBlue; // B

     // RGB转换为YUV
     RGB2YUV(bufRGB,bufYUV);
     yuv_y0 = bufYUV[0];   // y
     yuv_u0 = bufYUV[1];   // u
     yuv_v0 = bufYUV[2];   // v

     for (int k=0; k<1000; k++) ; //延时
     // 视图中显示
     pDC->SetPixel(j, (bmih.biHeight-1)-i, RGB(bufRGB[0], bufRGB[1], bufRGB[2]));

     // UYVY标准 [U0 Y0 V0 Y1] [U1 Y2 V1 Y3] [U2 Y4 V2 Y5] 每像素点两个字节,[内]为四个字节 
     if ((j%2)==0) 
     {
      *Video_Field0 = yuv_u0;
      Video_Field0++;
      yuv_v1 = yuv_v0;   // v保存起来供下一字节使用
     }
     else
     {
      *Video_Field0 = yuv_v1; 
      Video_Field0++;
     }
     *Video_Field0 = yuv_y0;      
     Video_Field0++;
    }// end if i%2
   }
}


// 下场 (2,4,6,8...行)
for (int i_ = bmih.biHeight-1; i_>=0; i_--) {
   for (int j_ = 0; j_<bmih.biWidth; j_++) {
    if((i_%2)==0) 
    {
     bufRGB[0] = rgb[i_*bmih.biWidth+j_].rgbtRed;   // R
     bufRGB[1] = rgb[i_*bmih.biWidth+j_].rgbtGreen; // G
     bufRGB[2] = rgb[i_*bmih.biWidth+j_].rgbtBlue; // B

     // RGB转换为YUV
     RGB2YUV(bufRGB,bufYUV);
     yuv_y0 = bufYUV[0];   // y
     yuv_u0 = bufYUV[1];   // u
     yuv_v0 = bufYUV[2];   // v

     for (int k=0; k<1000; k++) ; //延时
     // 视图中显示
     pDC->SetPixel(j_, (bmih.biHeight-1)-i_, RGB(bufRGB[0], bufRGB[1], bufRGB[2]));

     // UYVY标准 [U0 Y0 V0 Y1] [U1 Y2 V1 Y3] [U2 Y4 V2 Y5] 每像素点两个字节,[内]为四个字节 
     if ((j_%2)==0) 
     {
      *Video_Field1 = yuv_u0; 
      Video_Field1++;
      yuv_v1 = yuv_v0;   // v保存起来供下一字节使用
     } 
     else
     {
      *Video_Field1 = yuv_v1; 
      Video_Field1++;
     }
     *Video_Field1 = yuv_y0;      
     Video_Field1++;
    }
   }
}

WriteYUV(Video_Field0_,Video_Field1_,size);

f->Close();
delete f;
f = NULL;

free( Video_Field0_ ); 
Video_Field0_ = NULL;
free( Video_Field1_ );
Video_Field1_ = NULL;

delete []rgb;
rgb = NULL;

}

void doTestYUV2RGB()
{
CDC *pDC = GetDC();
CRect rect;
CBrush brush(RGB(128,128,128));
GetClientRect(&rect);
pDC->FillRect(&rect, &brush);

int CurrentXRes = BMP_WIDTH;
int CurrentYRes = BMP_HEIGTH;
int size        = CurrentXRes * CurrentYRes;

// 分配内存
byte *Video_Field0 = (byte*)malloc(CurrentXRes*CurrentYRes); 
byte *Video_Field1 = (byte*)malloc(CurrentXRes*CurrentYRes);

// 保存内存指针
byte *Video_Field0_ = Video_Field0;
byte *Video_Field1_ = Video_Field1;

// 初始化内存
ZeroMemory(Video_Field0, CurrentXRes*CurrentYRes);
ZeroMemory(Video_Field1, CurrentXRes*CurrentYRes);

byte yuv_y0, yuv_u0, yuv_v0; // yuv_v1; // {y0, u0, v0, v1};
byte r, g, b;
byte bufRGB[3]; // 临时保存{R,G,B}
byte bufYUV[3]; // 临时保存{Y,U,V}

// 初始化数组空间
memset(bufRGB,0, sizeof(byte)*3); 
memset(bufYUV,0, sizeof(byte)*3);

// 分配图片像素内存
RGBTRIPLE *rgb;
rgb = new RGBTRIPLE[CurrentXRes*CurrentYRes];

memset(rgb,0, sizeof(RGBTRIPLE)*CurrentXRes*CurrentYRes); // 初始化内存空间

CFile* f;
f = new CFile();
f->Open(YUV_FILE, CFile::modeRead);
f->SeekToBegin();
f->Read(Video_Field0, CurrentXRes*CurrentYRes);
f->Read(Video_Field1, CurrentXRes*CurrentYRes);

// 上场 (1,3,5,7...行)
for ( int i = CurrentYRes-1; i>=0; i--) {
   for ( int j = 0; j<CurrentXRes; j++) {
    if(!(i%2)==0) 
    {
     // UYVY标准 [U0 Y0 V0 Y1] [U1 Y2 V1 Y3] [U2 Y4 V2 Y5] 每像素点两个字节,[内]为四个字节 
     if ((j%2)==0) 
     {
      yuv_u0 = *Video_Field0; 
      Video_Field0++;
     } 
     else
     {
      yuv_v0 = *Video_Field0; 
      Video_Field0++;
     }
     yuv_y0 = *Video_Field0;      
     Video_Field0++;

     bufYUV[0] = yuv_y0; // Y
     bufYUV[1] = yuv_u0; // U
     bufYUV[2] = yuv_v0; // V

     // RGB转换为YUV
     YUV2RGB(bufRGB,bufYUV);
     r = bufRGB[0];   // y
     g = bufRGB[1];   // u
     b = bufRGB[2];   // v
     if (r>255) r=255; if (r<0) r=0;
     if (g>255) g=255; if (g<0) g=0;
     if (b>255) b=255; if (b<0) b=0;

     for (int k=0; k<1000; k++) ; //延时
     // 视图中显示
     pDC->SetPixel(j, CurrentYRes-1-i, RGB(r, g, b));

    }// end if i%2
   }
}

// 下场 (2,4,6,8...行)
for ( int i_ = CurrentYRes-1; i_>=0; i_--) {
   for ( int j_ = 0; j_<CurrentXRes; j_++) {
    if((i_%2)==0) 
    {
     // UYVY标准 [U0 Y0 V0 Y1] [U1 Y2 V1 Y3] [U2 Y4 V2 Y5] 每像素点两个字节,[内]为四个字节 
     if ((j_%2)==0) 
     {
      yuv_u0 = *Video_Field1; 
      Video_Field1++;
     } 
     else
     {
      yuv_v0 = *Video_Field1; 
      Video_Field1++;
     }
     yuv_y0 = *Video_Field1;      
     Video_Field1++;

     bufYUV[0] = yuv_y0; // Y
     bufYUV[1] = yuv_u0; // U
     bufYUV[2] = yuv_v0; // V

     // RGB转换为YUV
     YUV2RGB(bufRGB,bufYUV);
     r = bufRGB[0];   // y
     g = bufRGB[1];   // u
     b = bufRGB[2];   // v
     if (r>255) r=255; if (r<0) r=0;
     if (g>255) g=255; if (g<0) g=0;
     if (b>255) b=255; if (b<0) b=0;

     for (int k=0; k<1000; k++) ; //延时
     // 视图中显示
     pDC->SetPixel(j_, CurrentYRes-1-i_, RGB(r, g, b));
    }
   }
}
f->Close();
// 释放内存
free( Video_Field0_ ); 
free( Video_Field1_ );
delete f;
delete rgb;
}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要使用FFmpeg打开UYVY相机,将其转换RGB格式并推流到RTSP,可以使用以下命令: ``` ffmpeg -f v4l2 -video_size 640x480 -pixel_format uyvy422 -i /dev/video0 \ -c:v libx264 -pix_fmt yuv420p -preset ultrafast -tune zerolatency \ -f rtsp rtsp://localhost/live/stream ``` 这个命令的含义如下: - `-f v4l2`:指定使用v4l2(Video4Linux2)驱动程序访问视频设备。 - `-video_size 640x480`:设置视频分辨率为640x480,这可以根据实际情况进行更改。 - `-pixel_format uyvy422`:指定UYVY像素格式,如果您的相机支持其他格式,可以相应地更改此选项。 - `-i /dev/video0`:指定要打开的视频设备的路径。在本例中,我们将视频设备设置为/dev/video0。如果您的设备路径不同,请更改此选项。 - `-c:v libx264`:指定要使用x264编解码器进行视频编码。 - `-pix_fmt yuv420p`:指定输出视频的像素格式为YUV420P。 - `-preset ultrafast`:设置编码速度为最快,这可以确保最小的延迟。 - `-tune zerolatency`:设置调优选项,以减少延迟。 - `-f rtsp`:指定输出格式为RTSP。 - `rtsp://localhost/live/stream`:指定输出流的URL。在本例中,我们将其设置为rtsp://localhost/live/stream。如果您的输出URL不同,请相应地更改此选项。 这个命令将打开相机,将其转换RGB格式,并将视频流推流到RTSP URL。如果您需要更改输入或输出格式或URL,则需要相应地修改命令。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值