(转)RGB 与 YUV420 相互转换

RGB to YUV420 原代码:  RGB2YUV.CPP文件

RGB to YUV420 原代码:  RGB2YUV.CPP文件

#include <stdio.h>
#include <stdlib.h>
#include
<string.h>
#include<iostream>

//转换矩阵
#define MY(a,b,c) (( a*  0.2989  + b*  0.5866 
+ c*  0.1145))
#define MU(a,b,c) (( a*(-0.1688) + b*(-0.3312) + c* 
0.5000 + 128))
#define MV(a,b,c) (( a*  0.5000  + b*(-0.4184) +
c*(-0.0816) + 128))
//大小判断
#define DY(a,b,c) (MY(a,b,c) > 255 ? 255 :
(MY(a,b,c) < 0 ? 0 : MY(a,b,c)))
#define DU(a,b,c) (MU(a,b,c) > 255 ?
255 : (MU(a,b,c) < 0 ? 0 : MU(a,b,c)))
#define DV(a,b,c) (MV(a,b,c) >
255 ? 255 : (MV(a,b,c) < 0 ? 0 : MV(a,b,c)))
//只处理352*288文件
#define
WIDTH 352
#define HEIGHT 288

//读BMP
void ReadBmp(unsigned char *RGB,FILE *fp);

//转换函数
void Convert(unsigned char *RGB, unsigned char *YUV);

//入口
int main()
{
    int i=1;
   
char file[255];
    FILE *fp;
    FILE
*fp2;
    unsigned char *YUV = NULL;
   
unsigned char *RGB = NULL;
    unsigned int imgSize =
WIDTH*HEIGHT;

if((fp2 = fopen("test.cif", "wb")) ==
NULL)//生成文件名
   
{
        return 0;
   
}

RGB = (unsigned
char*)malloc(imgSize*6);
    YUV = (unsigned
char*)malloc(imgSize +
(imgSize>>1));
   
    for(i=1;
i<2; i++)
   
{
        sprintf(file, "test.bmp",
i);//读取文件
        if((fp = fopen(file,
"rb")) == NULL)
    continue;

printf("打开文件%s\n",
file);
        ReadBmp(RGB,
fp);
        Convert(RGB,
YUV);
        fwrite(YUV, 1,
imgSize+(imgSize>>1),
fp2);//写入文件
       
fclose(fp);
    }

fclose(fp2);
   
if(RGB)
        free(RGB);

if(YUV)
       
free(YUV);

printf("完成\n");
   
system("pause");
    return 1;
}

//读BMP
void ReadBmp(unsigned char *RGB,FILE
*fp)
{
    int i,j;
    unsigned char
temp;

fseek(fp,54, SEEK_SET);

fread(RGB+WIDTH*HEIGHT*3, 1, WIDTH*HEIGHT*3,
fp);//读取
    for(i=HEIGHT-1,j=0; i>=0;
i--,j++)//调整顺序
   
{
       
memcpy(RGB+j*WIDTH*3,RGB+WIDTH*HEIGHT*3+i*WIDTH*3,WIDTH*3);
   
}
    
    //顺序调整
   
for(i=0; (unsigned int)i < WIDTH*HEIGHT*3; i+=3)
   
{
        temp =
RGB[i];
        RGB[i] =
RGB[i+2];
        RGB[i+2] =
temp;
    }
}

void Convert(unsigned char *RGB, unsigned char
*YUV)
{
    //变量声明
    unsigned int
i,x,y,j;
    unsigned char *Y = NULL;
   
unsigned char *U = NULL;
    unsigned char *V =
NULL;
    
    Y =
YUV;
    U = YUV + WIDTH*HEIGHT;
    V = U +
((WIDTH*HEIGHT)>>2);

for(y=0; y < HEIGHT;
y++)
        for(x=0; x < WIDTH;
x++)
       
{
            j =
y*WIDTH +
x;
            i =
j*3;
            Y[j]
= (unsigned char)(DY(RGB[i], RGB[i+1], RGB[i+2]));

if(x%2 ==
1 && y%2 ==
1)
           
{
               
j = (WIDTH>>1) * (y>>1) +
(x>>1);
               
//上面i仍有效
               
U[j] = (unsigned
char)
                      
((DU(RGB[i  ], RGB[i+1], RGB[i+2])

                        
DU(RGB[i-3], RGB[i-2], RGB[i-1])
+
                        
DU(RGB[i  -WIDTH*3], RGB[i+1-WIDTH*3], RGB[i+2-WIDTH*3])
+
                        
DU(RGB[i-3-WIDTH*3], RGB[i-2-WIDTH*3], RGB[i-1-WIDTH*3]))/4);

V[j] = (unsigned
char)
                      
((DV(RGB[i  ], RGB[i+1], RGB[i+2])

                        
DV(RGB[i-3], RGB[i-2], RGB[i-1])
+
                        
DV(RGB[i  -WIDTH*3], RGB[i+1-WIDTH*3], RGB[i+2-WIDTH*3])
+
                        
DV(RGB[i-3-WIDTH*3], RGB[i-2-WIDTH*3],
RGB[i-1-WIDTH*3]))/4);
           
}

}
}

YUV420 to RGB 原代码: yuv2rgb.cpp文件

#include <stdio.h>
#include <stdlib.h>
#include
<iostream>
#define WIDTH 352
#define HEIGHT 288
//转换矩阵
double
YuvToRgb[3][3] = {1,       0, 
1.4022,
                        
1,    -0.3456,
-0.7145,
                        
1,   1.771,       0};

//根据RGB三分量写BMP,不必关注
int WriteBmp(int width, int height, unsigned char
*R,unsigned char *G,unsigned char *B, char *BmpFileName);

//转换函数
int Convert(char *file, int width, int height, int
n)
{
    //变量声明
    int i =
0;
    int temp = 0;
    int x =
0;
    int y = 0;
    int fReadSize =
0;
    int ImgSize = width*height;
    FILE
*fp = NULL;
    unsigned char* yuv =
NULL;
    unsigned char* rgb = NULL;
   
unsigned char* cTemp[6];
    char BmpFileName[256];

//申请空间
    int FrameSize = ImgSize +
(ImgSize >> 1);
    yuv = (unsigned char
*)malloc(FrameSize);
    rgb = (unsigned char
*)malloc(ImgSize*3);
    //读取指定文件中的指定帧
   
if((fp = fopen(file, "rb")) ==
NULL)
        return
0;
    fseek(fp, FrameSize*(n-1),
SEEK_CUR);
    fReadSize = fread(yuv, 1, FrameSize,
fp);
    fclose(fp);
    if(fReadSize <
FrameSize)
        return
0;
    //转换指定帧  如果你不是处理文件 主要看这里
   
cTemp[0] =
yuv;                       
//y分量地址
    cTemp[1] = yuv +
ImgSize;           
//u分量地址
    cTemp[2] = cTemp[1] +
(ImgSize>>2);    //v分量地址
    cTemp[3] =
rgb;                       
//r分量地址
    cTemp[4] = rgb +
ImgSize;           
//g分量地址
    cTemp[5] = cTemp[4] +
ImgSize;        //b分量地址
   
for(y=0; y < height; y++)
       
for(x=0; x < width; x++)
       
{
           
//r分量
            temp
= cTemp[0][y*width+x] + (cTemp[2][(y/2)*(width/2)+x/2]-128) *
YuvToRgb[0][2];
           
cTemp[3][y*width+x] = temp<0 ? 0 : (temp>255 ? 255 :
temp);
           
//g分量
            temp
= cTemp[0][y*width+x] + (cTemp[1][(y/2)*(width/2)+x/2]-128) *
YuvToRgb[1][1]
                                      
+ (cTemp[2][(y/2)*(width/2)+x/2]-128) *
YuvToRgb[1][2];
           
cTemp[4][y*width+x] = temp<0 ? 0 : (temp>255 ? 255 :
temp);
           
//b分量
            temp
= cTemp[0][y*width+x] + (cTemp[1][(y/2)*(width/2)+x/2]-128) *
YuvToRgb[2][1];
           
cTemp[5][y*width+x] = temp<0 ? 0 : (temp>255 ? 255 :
temp);
        }

//写到BMP文件中
    sprintf(BmpFileName,
"test.bmp", file, n);
    WriteBmp(width, height, cTemp[3],
cTemp[4], cTemp[5], BmpFileName);

free(yuv);
   
free(rgb);
    return n;
}
//入口 没啥东西
void
main()
{
    int i=1;
//    for( i=0;
i<260; i++)
        Convert("test.cif",
WIDTH, HEIGHT, i);//调用上面的Convert,获取文件的第i帧
}

//写BMP  不必关注
int WriteBmp(int width, int height, unsigned char
*R,unsigned char *G,unsigned char *B, char
*BmpFileName)
{
    int x=0;
    int
y=0;
    int i=0;
    int
j=0;
    FILE *fp;
    unsigned char
*WRGB;
    unsigned char *WRGB_Start;
   
int yu = width*3%4;
    int BytePerLine = 0;

yu = yu!=0 ? 4-yu : yu;
    BytePerLine
= width*3+yu;

if((fp = fopen(BmpFileName, "wb")) ==
NULL)
        return
0;
    WRGB = (unsigned
char*)malloc(BytePerLine*height+54);
    memset(WRGB, 0,
BytePerLine*height+54);
    
   
//BMP头
    WRGB[0] = ‘B‘;
    WRGB[1] =
‘M‘;
    *((unsigned int*)(WRGB+2)) =
BytePerLine*height+54;
    *((unsigned int*)(WRGB+10)) =
54;
    *((unsigned int*)(WRGB+14)) =
40;
    *((unsigned int*)(WRGB+18)) =
width;
    *((unsigned int*)(WRGB+22)) =
height;
    *((unsigned short*)(WRGB+26)) =
1;
    *((unsigned short*)(WRGB+28)) =
24;
    *((unsigned short*)(WRGB+34)) =
BytePerLine*height;

WRGB_Start = WRGB + 54;

for(y=height-1,j=0; y >= 0;
y--,j++)
    {
       
for(x=0,i=0; x<width; x++)
       
{
           
WRGB_Start[y*BytePerLine+i++] =
B[j*width+x];
           
WRGB_Start[y*BytePerLine+i++] =
G[j*width+x];
           
WRGB_Start[y*BytePerLine+i++] =
R[j*width+x];
       
}
    }

fwrite(WRGB, 1, BytePerLine*height+54,
fp);
    free(WRGB);
   
fclose(fp);
    return 1;
}

转自:http://ctfysj.blog.hexun.com/14194936_d.html

时间: 2024-08-25 23:55:49

(转)RGB 与 YUV420 相互转换的相关文章

C# RGB和HSB相互转换

背景 最近做的项目中有这样一个场景,设置任意一种颜色,得到这种颜色偏深和偏浅的两种颜色.也就是说取该颜色同色系的深浅两种颜色.首先想到的是调节透明度,但效果不理想.后来尝试调节颜色亮度,发现这才是正解.但是.NET中不能直接改变Color的亮度,需要将Color转换成HSB模式,然后改变B的值调节亮度.调节亮度后需要再转换成我们熟悉的RGB模式才能使用.下面给出颜色转换方法. 代码 1 /// <summary> 2 /// 颜色转换帮助类 3 /// </summary> 4 p

YUV / RGB 格式及快速转换算法

1 前言 自然界的颜色千变万化,为了给颜色一个量化的衡量标准,就需要建立色彩空间模型来描述各种各样的颜色,由于人对色彩的感知是一个复杂的生理和心理联合作用 的过程,所以在不同的应用领域中为了更好更准确的满足各自的需求,就出现了各种各样的色彩空间模型来量化的描述颜色.我们比较常接触到的就包括 RGB / CMYK / YIQ / YUV / HSI等等. 对于数字电子多媒体领域来说,我们经常接触到的色彩空间的概念,主要是RGB , YUV这两种(实际上,这两种体系包含了许多种具体的颜色表达方式和模

cv::Mat到YUV420的转换

某些特定场合我们会经常遇到yuv420格式的视频文件,这种视频帧无法直接用于opencv,故而,需要进行格式转换:幸运的是,opencv提供了rgb到yuv420的格式转换函数:下面给出基本用法: 函数1:读取avi格式的视频文件,转换成Yuv420格式,并写入文件: void WriteYuv() { cv::VideoCapture vc; bool flag = vc.open("S1000008.avi"); if (!flag) { printf("avi file

Camera图像处理原理及实例分析-重要图像概念

Camera图像处理原理及实例分析 作者:刘旭晖  [email protected]  转载请注明出处 BLOG:http://blog.csdn.net/colorant/ 主页:http://rgbbones.googlepages.com/ 做为拍照手机的核心模块之一,camera sensor 效果的调整,涉及到众多的参数,如果对基本的光学原理及 sensor 软/硬件对图像处理的原理能有深入的理解和把握的话,对我们的工作将会起到事半功倍的效果.否则,缺乏了理论的指导,只能是凭感觉和经

Camera图像处理原理及实例分析

Camera图像处理原理及实例分析 作者:刘旭晖  [email protected]  转载请注明出处 BLOG:http://blog.csdn.net/colorant/ 主页:http://rgbbones.googlepages.com/ 做为拍照手机的核心模块之一,camera sensor 效果的调整,涉及到众多的参数,如果对基本的光学原理及 sensor 软/硬件对图像处理的原理能有深入的理解和把握的话,对我们的工作将会起到事半功倍的效果.否则,缺乏了理论的指导,只能是凭感觉和经

视频滤镜参数

在配置编译FFmpeg时可以通过--disable-filters来禁止所有滤镜的编译.也可以配置编译脚本来输出所有包含进编译的滤镜信息.下面是当前可用的视频滤镜介绍. alphaextract 把输入视频作为灰度视频来提取透明通道,它通常和alphamerge滤镜联用. alphamerge 通过添加或者替换透明通道,让主要视频与另外一路视频混合.这里主要是使用alphaextract来让不支持透明通道的视频成为允许传输或存储帧透明的帧序列 例如:为了重建完整的帧,让一个普通的YUV编码视频和

camera摄像原理之二:色彩空间【转】

转自:http://blog.csdn.net/ghostyu/article/details/7912854 对于sensor 来说,我们经常接触到的色彩空间的概念,主要是RGB , YUV这两种(实际上,这两种体系包含了许多种不同的颜色表达方式和模型,如sRGB, Adobe RGB, YUV422, YUV420 …),RGB如前所述就是按三基色加光系统的原理来描述颜色,而YUV则是按照亮度,色差的原理来描述颜色. 不比其它颜色空间的转换有一个标准的转换公式,因为YUV在很大程度上是与硬件

FFmpeg源代码分析:sws_getContext()

打算写两篇文章记录FFmpeg中的图像处理(缩放,YUV/RGB格式转换)类库libswsscale的源代码.libswscale是一个主要用于处理图片像素数据的类库.可以完成图片像素格式的转换,图片的拉伸等工作.有关libswscale的使用可以参考文章: <最简单的基于FFmpeg的libswscale的示例(YUV转RGB)> libswscale常用的函数数量很少,一般情况下就3个: sws_getContext():初始化一个SwsContext. sws_scale():处理图像数

乐学成语项目的实现

首先给软件取名为HappyIdiom,在开始编码之前,需要先对程序进行需求分析,想一想HappyIdiom中应该具备哪些功能.将这些功能全部整理出来之后,我们才好动手一一实现.这里我认为HappyIdiom中至少应该具备以下功能: 1.成语分类学习:你可以根据自己喜欢的分类(动物类.人物类.季节类.自然类.数字类.语言类.其他类)来进行学习. 2.乐猜成语:学习之余玩玩猜成语游戏,寓教于乐. 3.成语收藏:当用户遇到自己想要保存的成语,点击保存按钮,即保存到收藏页面以方便用户再次查看,对已经掌握