RGB,YUV,420SP,NV21,420P,nv21TOargb,nv21TOyuv等,BMP/RGB和YUV/RGB和HSL的转换与区别(视频编码)

  RGBA、RGB、BGRA、BGR、YUV420P、YUV420SP、YUV,420SP,NV21、420P、nv21TOargb,nv21TOyuv、BMP、HSL、HSV等。
1.视频什么时候转为RGB格式 什么时候转为YUV格式?
2.YUV为什么要转为RGB格式?
3.视频输出的数据流是YUV,照相机输出的数据流是RGB ?

-- 比如yuv420格式图像相比RGB来说,要节省一半的字节大小,抛弃相邻的色差对于人眼来说,差别不大。
 一张yuv格式的图像,占用字节数为 (width * height + (width * height) / 4 + (width * height) / 4) = (width * height) * 3 / 2
;一张RGB格式的图像,占用字节数为(width * height) * 3;
 在传输上,yuv格式的视频也更灵活(yuv3种数据可分别传输)。
 很多视频编码器最初是不支持rgb格式的。但是所有的视频编码器都支持yuv格式。综合来讲,我们选择使用yuv格式,所以我们编码之前,首先将视频数据转成yuv格式。
 I420格式:y,u,v 3个部分分别存储:Y0,Y1...Yn,U0,U1...Un/2,V0,V1...Vn/2
 NV12格式:y和uv 2个部分分别存储:Y0,Y1...Yn,U0,V0,U1,V1...Un/2,Vn/2
 NV21格式:同NV12,只是U和V的顺序相反。
 所有的音频编码器,都支持pcm编码,而且录制的声音,默认也是PCM格式。

-- 采用GLSurfaceView,要得到摄像头的YUV数据会非常的困难,因为通过GLSurfaceView得到的是ARGB数据,要手动的转一遍YUV数据,会有巨大的性能问题;  

  Parameters.setPreviewFormat(ImageFormat.NV21); // 设置NV21预览格式。SurfaceVie初始化摄像头的时候,必须要指定摄像头的数据预览格式为NV21(YUV数据的一种),摄像头初始化完成后绑定SurfaceView,在onPreviewFrame()回调中得到预览的NV21数据,将此数据提供给编码器。编码过程为:将NV21帧数据转换为NV12数据,再将NV12数据输入到编码器,此时编码器会自动编码该数据,然后输出编码后的数据(output())到混合器。 编码器的颜色模式在我的代码中使用的是COLOR_FormatYUV420SemiPlanar,这个颜色模式就是NV12的格式,但有些手机可能不支持这个格式,所以小伙伴们需要先检查手机的编码器是否支持该格式,如果不支持该格式就得使用其他的颜色模式。通过MediaCodecInfo.getCapabilitiesForType()可以拿到当前编码器的MediaCodecInfo.CodecCapabilities,它有一个数组变量colorFormats包含的是该编码器支持的颜色模式,需要在这些模式中选择适用的颜色模式(在这篇文章中以COLOR_FormatYUV420SemiPlanar为例,建议小伙伴们如果编码器支持的颜色模式种包含这个模式,优先使用这个模式),因为摄像头拿到的是NV21的数据,所以就需要把NV21数据转为你当前编码器配置的颜色模式。

-- 通常视频依照24帧每秒的频率存储图像、甚至以30帧每秒的频率存储图像,如果以rgba的格式存储,占用的存储空间是非常庞大的,而且不利于网络传输。而YUV格式,如果一帧RGBA的图像数据占用16份,那么RGB占用12份,而YUV420只占用6份。虽然RGB的图像变为YUV格式质量通常会有损失,但是这个损失通常是可以接受的。

-- 两大类:yuv xxx p和yuv xxx sp。xxx可以是444,422,420替换过来。
  Android调用本地的摄像头以及麦克风采集的原始数据,视频是YUV或者RGB格式的;音频经过麦克风采集后是PCM格式的,这是采集的最原始的数据;视频:NV21,音频:PCM。采集到原始的数据Android默认是NV21的,然后又出来一个I420格式的。H.264编码的输入数据必须是I420标准的格式。原始数据NV21(YUV420SP),首先将其转换成了I420(YUV420P),这样就可以继续利用MediaCodec API将原始数据进行编码了。此时数据格式:视频:I420,音频:PCM。

-- 做视频采集与处理,自然少不了要学会分析YUV数据。因为从采集的角度来说,一般的视频采集芯片输出的码流一般都是YUV数据流的形式,而从视频处理(例如H.264、MPEG视频编解码)的角度来说,也是在原始YUV码流进行编码和解析。  分析清楚YUV码流格式了,我们可以做什么?最常用的一点就是,提取出所有的Y分量,然后利用vc或者matlab把你采集的图像的灰度值(Y分量)显示处理,这样你就可以很快地知道你采集的图像是否有问题了。如何提取、转换、显示这些YUV原始码流?

计算机中的大多数图片,都是以RGB格式存储的。YUV图像视频主要应用于电视和游戏视频显示。

> HSV,图像检索:CEDD(Color and Edge Directivity Descriptor)算法- https://blog.csdn.net/leixiaohua1020/article/details/16883379

  HSV:色调,饱和度,亮度。
  RGB颜色模型的设计是根据色彩发光原理而来的,且与硬件相关,一般情况下,计算机都会釆用这种空间模型在屏幕上显示某种颜色的定义,即人们所熟悉的三色组合。所以,当从一幅图像中提取像素点时首先提取的一般也是像素点的RGB信息。
  HSV模型中,H (Hue)代表色调,指通过物体传播或从物体射出的颜色,一般在使用中是由颜色名称来标识的。S (Saturation)代表饱和度,表示色调中灰色成分的比例,指颜色的纯度或强度。V (Value)代表亮度,指颜色相对的明暗程度。HSV模型能够较好地反应人对颜色的感知和鉴别能力,所以非常适合于比较基于颜色的图像相似性,在图像分类中也得到了广泛应用。在提取颜色信息前就需要对图像像素进行RGB-HSV的模型转换。

  10-bins模糊过滤器是基于模糊理论的。10-bins模糊过滤器的工作过程是通过三个通道输入HSV信息,然后输出10个模糊的直方图信息值。10个直方图信息值的含义如下:(0)黒色(Black),(1)灰色(Gray),(2)白色(White),(3)红色(Red), (4)橙色(Orange),(5)黄色(Yellow),(6)绿色(Green),(7)青色(Cyan),(8)蓝色(Blue),(9)品红色(Magenta)。
  24-bins模糊过滤器就是将10-bins模糊过滤器输出的每种色区再分为3个H值区域,输入一个10维向量和S、V通道值,输出的是一个24维向量,其系统模型如图3-7所示。它输出的每一维所代表的信息分别是:(0)黑色(Black),(1)灰色(Grey),(2)白色(White),(3)暗红色(Dark Red),(4)红色(Red),(5)浅红(Light Red),(6)暗橙色(DarkOrange),(7)橙色(Orange),(8)浅橙色(Light Orange),(9)暗黄色(Dark Yellow),(10)黄色(Yellow), (11)浅黄色(LightYellow),(12)深绿色(Dark Green),(13)绿色(Green),(14)浅绿色(Light Green),(15)暗青色(Dark Cyan),(16)青色(Cyan),(17)浅青色(Light Cyan),(18)深蓝色(Dark Blue),(19)蓝色(Blue),(20)淡蓝色(LightBlue),(21)暗品红色(DarkMagenta),(22)品红色(Magenta),(23)浅品红色(Light Magenta)。

> YIQ色彩空间,灰度值 色调信息
 YIQ色彩空间属于NTSC (国际电视标准委员会)系统。Y(Luminace)代表了颜色的明视度,直观点说就是图像的灰度值。I和Q (Chrominace)代表了色调信息,它们分别描述图像色彩以及饱和度的属性。在YIQ色彩空间模型中,Y分量表示图像的亮度信息,I和Q分量表示颜色信息,I分量是指从橙色到青色,Q分量则是指从紫色到黄绿色。

> BMP转换为YUV
  位图文件(Bitmap-File,BMP)格式是Windows采用的图像文件存储格式,在Windows环境下运行的所有图像处理软件都支持这种格式。BMP位图文件默认的文件扩展名是bmp或者dib。
  BMP转换为YUV,RGB到色差信号的转换如下所示:
 Y=0.2990R+0.5870G+0.1140B
 R-Y=0.7010R-0.5870G-0.1140B
 B-Y=-0.2990R-0.5870G+0.8860B
  为了使色差信号的动态范围控制在0.5之间,需要进行归一化,对色差信号引入压缩系数。归一化后的色差信号为:
 U=-0.1684R-0.3316G+0.5B
 V=0.5R-0.4187G-0.0813B
 
> YV12和I420的区别:(YUV播放器)
   一般来说,直接采集到的视频数据是RGB24的格式,RGB24一帧的大小size=width×heigth×3 Byte,RGB32的size=width×heigth×4,如果是I420(即YUV标准格式4:2:0)的数据量是I420 size=width×heigth×1.5 Byte
    在采集到RGB24数据后,需要对这个格式的数据进行第一次压缩。即将图像的颜色空间由RGB2YUV。因为,X264在进行编码的时候需要标准的YUV(4:2:0)。但是这里需要注意的是,虽然YV12也是(4:2:0),但是YV12和I420的却是不同的,在存储空间上面有些区别。如下:YV12 : 亮度(行×列) + V(行×列/4) + U(行×列/4);I420 : 亮度(行×列) + U(行×列/4) + V(行×列/4)

-- 视频的yv12,I420
  一般来说,直接采集到的视频数据是RGB24的格式,RGB24一帧的大小size=width×heigth×3 Byte,RGB32的size=width×heigth×4,如果是I420(即YUV标准格式4:2:0)的数据量是 size=width×heigth×1.5 Byte。
  YV12 : 亮度(行×列) + V(行×列/4) + U(行×列/4)
  I420 : 亮度(行×列) + U(行×列/4) + V(行×列/4)
附一个YUV播放器的源代码:http://download.csdn.net/detail/leixiaohua1020/6374065

> RGB和HSL的转换
RGB和HSL色彩的相互转换- http://blog.csdn.net/yuntongsf/article/details/79289368

> RGB和YUV互相转换  
Android视频编码——RGBA、RGB、BGRA、BGR转YUV420P、YUV420SP- http://blog.csdn.net/junzia/article/details/54707322
YUV与RGB互转各种公式- http://www.cnblogs.com/luoyinjie/p/7219319.html
Android Opengl ES2.0 -实现RGB-YUV互转并显示到屏幕- https://blog.csdn.net/nommmmon/article/details/71025251
android CodecCapabilities 图像格式- https://blog.csdn.net/jumper511/article/details/21719313
视频存储格式YUV420 NV12 NV21 i420 YV12- https://www.jianshu.com/p/e67f79f10c65
YUV 格式与 RGB 格式的相互转换公式及C++ 代码- https://blog.csdn.net/liyuanbhu/article/details/68951683

https://img-blog.csdn.net/20180917171113493?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1NoYXJlVXM=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70

yuv是经过压缩的视频信号,要还原成可以处理的数字信号,得必须转换。
 视频是由一帧一帧的数据连接而成,而一帧视频数据其实就是一张图片。yuv是一种图片储存格式,跟RGB格式类似。
 一张24位BMP图像为例实现RGB与YUV相互转换。在记录计算机图像时,最常见的是采用RGB(红、绿,蓝)颜色分量来保存颜色信息.  由于不同国家的电视信号系统支持的图像格式不同,有YUV格式成像,也有RGB格式成像,因此为了保证兼容性,需要进行RGB与YUV格式的互转。在视频等相关的应用中,YUV是一个经常出现的格式。

1.RGB格式转为YUV格式转换公式:
  Y = 0.299 R + 0.587 G + 0.114 B
  U = - 0.1687 R - 0.3313 G + 0.5 B + 128
  V = 0.5 R - 0.4187 G - 0.0813 B + 128 

2.YUV格式转为RGB格式转换公式:
  R = Y + 1.402 (V-128)
  G = Y - 0.34414 (U-128) - 0.71414 (V-128)
  B = Y + 1.772 (U-128)

3.RGB格式转为YCbCr格式转换公式
  YCbCr格式是基于YUV格式的一个偏移,具体转换如下:
 Y’ = 0.257*R' + 0.504*G' + 0.098*B' + 16
 Cb' = -0.148*R' - 0.291*G' + 0.439*B' + 128
 Cr' = 0.439*R' - 0.368*G' - 0.071*B' + 128

4.RGB格式转为YCbCr格式转换公式:
 R' = 1.164*(Y’-16) + 1.596*(Cr'-128)
 G' = 1.164*(Y’-16) - 0.813*(Cr'-128) -0.392*(Cb'-128)
 B' = 1.164*(Y’-16) + 2.017*(Cb'-128)

5.YUV与RGB相互转换的公式如下(RGB取值范围均为0-255)︰
 Y = 0.299R + 0.587G + 0.114B ; U = -0.147R - 0.289G + 0.436B ; V = 0.615R - 0.515G - 0.100B
 R = Y + 1.14V ; G = Y - 0.39U - 0.58V ; B = Y + 2.03U

6.YCbCr[YUV(601)]转换RGB(范围0-255)时用的。
 B = 1.164 * (Y - 16) + 2.018 * (U - 128)
 G = 1.164 * (Y - 16) - 0.38 * (U - 128) - 0.813 * (V - 128)
 R = 1.164 * (Y - 16) + 1.159 * (V - 128)

> YUV:灰阶值,色度

-- 如何显示原始的YUV码流,根据我的经验,一般有三种方法:

(1) 利用 matlab ,写相关的程序进行显示。(本文我将提供相关显示程序)

(2) 使用 MFC + Direct Draw 来实现。(稍后整理好了再提供出来)

(3) 使用 第三方工具(YUVviewerPlus.exe),很好的软件。(在附件中提供)

开源的 Android YUV 格式查看工具- https://github.com/Jhuster/YUVDroidTools
-- YUV/RGB播放器,既支持YUV又支持RGB的播放器
原版项目地址:https://sourceforge.net/projects/raw-yuvplayer/
修改版源码地址:https://github.com/leixiaohua1020/YUVplayer
图文详解YUV420数据格式- http://www.cnblogs.com/azraelly/archive/2013/01/01/2841269.html

-- YUV取值范围有两种:
(1)以Rec.601为代表(还包括BT.709 / BT.2020)的广播电视标准中,Y的取值范围是16-235,U、V的取值范围是16-240。FFmpeg中称之为“mpeg”范围。
(2)以JPEG为代表的标准中,Y、U、V的取值范围都是0-255。FFmpeg中称之为“jpeg” 范围。
  YUV,分为三个分量,“Y”表示明亮度(Luminance或Luma),也就是灰度值;而“U”和“V” 表示的则是色度(Chrominance或Chroma),作用是描述影像色彩及饱和度,用于指定像素的颜色。
  YUV码流的存储格式其实与其采样的方式密切相关,主流的采样方式有三种,YUV4:4:4,YUV4:2:2,YUV4:2:0

  YUV是被欧洲电视系统所采用的一种颜色编码方法(属于PAL),是PAL和SECAM模拟彩色电视制式采用的颜色空间。在现代彩色电视系统中,通常采用三管彩色摄影机或彩色CCD摄影机进行取像,然后把取得的彩色图像信号经分色、分别放大校正后得到RGB,再经过矩阵变换电路得到亮度信号Y和两个色差信号B-Y(即U)、R-Y(即V),最后发送端将亮度和色差三个信号分别进行编码,用同一信道发送出去。这种色彩的表示方法就是所谓的YUV色彩空间表示。采用YUV色彩空间的重要性是它的亮度信号Y和色度信号U、V是分离的。用这个三个字母好象就是通道命令。

  YUV是一种亮度信号Y和色度信号U、V是分离的色彩空间,它主要用于优化彩色视频信号的传输,使其向后相容老式黑白电视,且与RGB要求三个独立的视频信号同时传输相比,YUV最大的优点在于只需占用极少的频宽,非常适用于流媒体传输。

  YUV主要用于优化彩色视频信号的传输,使其向后相容老式黑白电视。与RGB视频信号传输相比,它最大的优点在于只需占用极少的频宽(RGB要求三个独立的视频信号同时传输)。其中“Y”表示明亮度(Luminance或Luma),也就是灰阶值;而“U”和“V” 表示的则是色度(Chrominance或Chroma),作用是描述影像色彩及饱和度,用于指定像素的颜色。“亮度”是透过RGB输入信号来建立的,方法是将RGB信号的特定部分叠加到一起。“色度”则定义了颜色的两个方面─色调与饱和度,分别用Cr和Cb来表示。其中,Cr反映了RGB输入信号红色部分与RGB信号亮度值之间的差异。而Cb反映的是RGB输入信号蓝色部分与RGB信号亮度值之间的差异。
  采用YUV色彩空间的重要性是它的亮度信号Y和色度信号U、V是分离的。如果只有Y信号分量而没有U、V分量,那么这样表示的图像就是黑白灰度图像。彩色电视采用YUV空间正是为了用亮度信号Y解决彩色电视机与黑白电视机的兼容问题,使黑白电视机也能接收彩色电视信号。主要的采样格式有YCbCr 4:2:0、YCbCr 4:2:2、YCbCr 4:1:1和 YCbCr 4:4:4。其中YCbCr 4:1:1 比较常用,其含义为:每个点保存一个 8bit 的亮度值(也就是Y值),每 2x2 个点保存一个 Cr 和Cb 值,图像在肉眼中的感觉不会起太大的变化。所以,原来用 RGB(R,G,B 都是 8bit unsigned) 模型,1个点需要 8x3=24 bits(如下图第一个图),(全采样后,YUV仍各占8bit)。按4:1:1采样后,而现在平均仅需要 8+(8/4)+(8/4)=12bits(4个点,8*4(Y)+8(U)+8(V)=48bits), 平均每个点占12bits(如下图第二个图)。这样就把图像的数据压缩了一半。
  YUV420平面格式(Planar),即Y、U、V是分开存储的,每个分量占一块地方,其中Y为 width*height,而U、V合占Y的一半,该种格式每个像素占12比特。根据U、V的顺序,分出2种格式,U前V后即YUV420P,也叫 I420,V前U后,叫YV12(YV表示Y后面跟着V,12表示12bit)。另外,还有一种半平面格式(Semi-planar),即Y单独占一块地 方,但其后U、V又紧挨着排在一起,根据U、V的顺序,又有2种,U前V后叫NV12,在国内好像很多人叫它为YUV420SP格式;V前U后叫 NV21。 对手机摄像头采集的原始帧做Rotate或者Scale.

  YUV的存储中与RGB格式最大不同在于:RGB格式每个点的数据是连继保存在一起的。即R,G,B是前后不间隔的保存在2-4byte空间中。而YUV的数据中为了节约空间,U,V分量空间会减小。每一个点的Y分量独立保存,但连续几个点的U,V分量是保存在一起的,(反正人眼一般也看不出区别).这几个点合起来称为macro-pixel, 这种存储格式称为Packed格式。
  另外一种存储格式是把一幅图像中Y,U,V分别用三个独立的数组表示。这种模式称为planar模式。

  YUV格式分为两种类型,即Packet(包)和Plannar(平面)。Packet类型是将Y、U、V分量存储在同一个数组中,每个像素点的Y、U、V是连续交错存储的,常见的采样格式有NV21、NV12;Plannar类型是将Y、U、V分量分别存储在三个独立的数组中,且先连续存储所有像素点的Y分量,紧接着存储所有像素点的U分量,最后存储所有像素点的V分量,常见的采样格式有YV12、I420。

-- YCbCr不是一种绝对色彩空间,是YUV压缩和偏移的版本。
  Y(Luma,Luminance)视讯,也就是灰阶值。UV 视作表示彩度的 C(Chrominance或Chroma)。主要的采样(subsample)格式有YCbCr 4:2:0、YCbCr 4:2:2。如果只有Y信号分量而没有U、V分量,那么这样表示的图像就是黑白灰度图像。因此用YUV格式由彩色转
黑白信号相当简单. 
   在技术文档里,YUV经常有另外的名字, YCbCr ,其中Y与YUV 中的Y含义一致,Cb , Cr 同样都指色彩,,只是在表示方法上不同而已,Cb Cr 就是本来理论上的“分量/色差”的标识。C代表分量(是component的缩写)Cr、Cb分别对应r(红)、b(蓝)分量信号,Y除了g(绿)分量信号,还叠加了亮度信号。
  Y'CbCr 在模拟分量视频(analog component video)中也常被称为YPbPr,YPbPr是将模拟的Y、PB、PR信号分开,使用三条线缆来独立传输,保障了色彩还原的准确性,YPbPr表示逐行扫描色差输出.YPbPr接口可以看做是S端子的扩展,与S端子相比,要多传输PB、PR两种信号,避免了两路色差混合解码并再次分离的过程,也保持了色度通道的最大带宽,只需要经过反矩阵解码电路就可以还原为RGB三原色信号而成像,这就最大限度地缩短了视频源到显示器成像之间的视频信号通道,避免了因繁琐的传输过程所带来的图像失真,保障了色彩还原的准确,目前几乎所有大屏幕电视都支持色差输入。
  RGB格式中,一个24bpp像素要占用4字节空间。在YUV格式中,可以对于UV分量的数据压缩,但是对图像整体质量影响不大,这样YUV所占的空间就比RGB要小一些,不过RGB中 16bpp的 565格式每一个点只占2个字节,从这一点看也没有省多少。不过视频应用都是清一色的YUV应用。因此YUV的处理还是一个比较重要课题。

  YUV 4:4:4 表示色度值(UV)没有减少采样。即Y,U,V各占一个字节,加上Alpha通道一个字节,总共占4字节.这个格式其实就是24bpp的RGB格式了。
  YUV 4:2:2 表示UV分量采样减半,比如第一个像素采样Y、U,第二个像素采样Y、V,依次类推,这样每个点占用2个字节.二个像素组成一个宏像素.
  YUV 4:2:0 这种采样并不意味着只有Y、Cb而没有Cr分量,这里的0说的U、V分量隔行才采样一次。比如第一行采样 4:2:0 ,第二行采样 4:0:2 ,依次类推...在这种采样方式下,每一个像素占用16bits或10bits空间.
  YUV 4:1:1 可以参考4:2:2分量,是进一步压缩,每隔四个点才采一次U和V分量。一般是第0点采Y,U,第1点采Y,第3点采YV,第四点采Y,依次类推。
 除了4:4:4采样,其余采样后信号重新还原显示后,会丢失部分UV数据,只能用相临的数据补齐,但人眼对UV不敏感,因此总体感觉损失不大。

-- YCbCr 4:1:1和 YCbCr 4:4:4。YUV的表示法称为 A:B:C 表示法:
* 4:4:4 表示完全取样。
* 4:2:2 表示 2:1 的水平取样,没有垂直下采样。
* 4:2:0 表示 2:1 的水平取样,2:1 的垂直下采样。
* 4:1:1 表示 4:1 的水平取样,没有垂直下采样。

-- 主流的采样方式有三种,YUV4:4:4,YUV4:2:2,YUV4:2:0
YUV 4:4:4采样,每一个Y对应一组UV分量。 
YUV 4:2:2采样,每两个Y共用一组UV分量。 
YUV 4:2:0采样,每四个Y共用一组UV分量。

(1) YUVY 格式 (属于YUV422)
(2) UYVY 格式 (属于YUV422)
(3) YUV422P(属于YUV422)
(4) YV12,YU12格式(属于YUV420)
(5) NV12、NV21(属于YUV420)

> RGB
  RGB色彩模式是工业界的一种颜色标准,是通过对红(R)、绿(G)、蓝(B)三个颜色通道的变化以及它们相互之间的叠加来得到各式各样的颜色的,RGB即是代表红、绿、蓝三个通道的颜色,这个标准几乎包括了人类视力所能感知的所有颜色,是目前运用最广的颜色系统之一。

  一般来说,直接采集到的视频数据是RGB24的格式,RGB24一帧的大小size=width×heigth×3 Bit,RGB32的size=width×heigth×4,如果是I420(即YUV标准格式4:2:0)的数据量是 size=width×heigth×1.5 Bit。在采集到RGB24数据后,需要对这个格式的数据进行第一次压缩。即将图像的颜色空间由RGB2YUV。

  RGB每个像素点的每个分量取值范围为0-255不同(每个分量占8bit)。

  按照计算,256级的RGB色彩总共能组合出约1678万种色彩,即256×256×256=16777216。通常也被简称为1600万色或千万色。也称为24位色(2的24次方)。
 手机1600万象素(4618×3464),800万象素(3264×2448),500万 (2592×1944),300万象素(2048×1536)。

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++ ;  
                }  
            }  
        }  
    }  
}  

> 将YUV转成ARGB_8888的jni代码:
jintArray Java_com_spore_jni_ImageUtilEngine_decodeYUV420SP(JNIEnv * env,
jobject thiz, jbyteArray buf, jint width, jint height) {
  jbyte * yuv420sp = (*env)->GetByteArrayElements(env, buf, 0);
 
  int frameSize = width * height;
  jint rgb[frameSize]; // 新图像像素值
 
  int i = 0, j = 0,yp = 0;
  int uvp = 0, u = 0, v = 0;

  for (j = 0, yp = 0; j < height; j++){
    uvp = frameSize + (j >> 1) * width;
    u = 0;
    v = 0;
    for (i = 0; i < width; i++, yp++){
    int y = (0xff & ((int) yuv420sp[yp])) - 16;
    if (y < 0)
        y = 0;
    if ((i & 1) == 0){
        v = (0xff & yuv420sp[uvp++]) - 128;
        u = (0xff & yuv420sp[uvp++]) - 128;
    }
 
        int y1192 = 1192 * y;
    int r = (y1192 + 1634 * v);
    int g = (y1192 - 833 * v - 400 * u);
    int b = (y1192 + 2066 * u);
 
    if (r < 0) r = 0; else if (r > 262143) r = 262143;
    if (g < 0) g = 0; else if (g > 262143) g = 262143;
    if (b < 0) b = 0; else if (b > 262143) b = 262143;
 
        rgb[yp] = 0xff000000 | ((r << 6) & 0xff0000) | ((g >> 2) & 0xff00) | ((b >> 10) & 0xff);
    }
  }
 
  jintArray result = (*env)->NewIntArray(env, frameSize);
  (*env)->SetIntArrayRegion(env, result, 0, frameSize, rgb);
  (*env)->ReleaseByteArrayElements(env, buf, yuv420sp, 0);
   return result;
}

public native int[] decodeYUV420SP(byte[] buf, int width, int height);

展开阅读全文

没有更多推荐了,返回首页