Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1428581
  • 博文数量: 430
  • 博客积分: 9995
  • 博客等级: 中将
  • 技术积分: 4388
  • 用 户 组: 普通用户
  • 注册时间: 2006-05-24 18:04
文章存档

2013年(1)

2008年(2)

2007年(14)

2006年(413)

分类:

2006-10-17 09:46:32

目前可以在一些专业级视频工作站/编辑卡专业级视频设备或高档影碟机等家电上看到有YUV、YcbCr、Y/B-Y/B-Y等标记的接口标识,虽然其标记方法和接头外形各异但都是指的同一种接口色差端口( 也称分量视频接口) 。它通常采用YPbPr 和YCbCr两种标识,前者表示逐行扫描色差输出,后者表示隔行扫描色差输出。由上述关系可知,我们只需知道Y Cr Cb的值就能够得到G 的值( 即第四个等式不是必要的),所以在视频输出和颜色处理过程中就统一忽略绿色差Cg ,而只保留Y Cr Cb ,这便是色差输出的基本定义。
作为S-Video的进阶产品    
色差输出将S-Video传输的色度信号C分解为色差Cr和Cb,这样就避免了两路色差混合解码并再次分离的过程,也保持了色度通道的最大带宽,只需要经过反矩阵解码电路就可以还原为RGB三原色信号而成像,这就最大限度地缩短了视频源到显示器成像之间的视频信号通道,避免了因繁琐的传输过程所带来的图像失真,所以色差输出的接口方式是以上各种视频输出接口中最好的一种,目前色差输出仍停留在专业级应用中广泛普及。

 

MPEG之压缩比那麽大是因为它采用了失真压缩 (Lossy Compression),画面由三种格式储存:

I-Frame: Intraframe,一张完全独立之完整画面。

P-Frame: (Unidirectional) Prediction Frame,只储存那一帧画面与之前已解压的画面之分别。由於不需要储存整幅画面,故所需空间减少了很多。

B-Frame: Bi-directional Prediction Frame,与 P-Frame原理一样,但除了叁考之前解压了的画面外,亦会叁考後面未解压的画面。 B Frame解压後出来的画面质素会比 P-Frame来得好 (当然论画质而言, I-Frame最好 )。一般 MPEG档案之画面排列次序为 IBBPBBPBBPBBPBBIBBPBBP....


MPEG 2名词解释:

YUV:颜色格式 (Colour Space)的一种, Y代表光暗度 (Luminance), U代表颜色 (Hue), V代表饱和度 (Saturation)。

RGB: Red/Green/Blue,很明显就是电脑荧光幕所用的红绿蓝三原色。

Inverse Discrete Cosine Transform(IDCT):此步骤利用数学函式来解压出 B Frame及 P Frame资料。

Motion Compensation(影像动作补偿 ):将 IDCT解压出来的 P/B Frame资料以向量方式计算出一个完全的画面。

Colour Space Conversion(色彩格式转换 ):电脑荧光幕采用的颜色制式是 RGB,有别於 DVD所用之颜色制式 (YUV),但由於 YUV压缩後会比较悭位以及在画面质素保存方面会比较好,所以 MPEG 1及 MPEG 2都是采用 YUV,基於这个关系, YUV是需要转为 RGB资料来显示於荧光幕上 (这个步骤有很多浮点运算的 )。之後由於 VCD流行,所以各大显示晶片都加添了 YUV→ RGB的线路。而有很多所谓支援 MPEG 2/DVD软件播放的显示卡 (如 nVidia RivaTNT 3Dfx Voodoo Banshee等 ),其实只是在硬件提供了 MPEG 2解压所需的有关色彩格式转换函式而已 (MPEG 2之 YUV→ RGB的计算方法是与 MPEG 1有点出入 )。

De-interlacing(反交错处理 ):由於 MPEG-2信号是为电视而设,而电视是交错式的 (Interlaced),所以在电脑荧光幕上播放 DVD便要将电视用的交错型式 (Interlaced-mode)转为电脑上用的非交错式 (Non-interlaced Mode),这个步骤称为 De-interlacing,而 De-interlacing有两种方式,各有其优点及缺点,一种名叫 Weave De-interlacing,另一种名叫 Bob De-interlacing。

Video Scaling, Filtering Overlay Surfaces:由於影像画面需要因应用者之喜好而放大或缩小,所以就会有相对之 Video Scaling技术来减低因放大或缩小後画质变差之情出现。 Filtering(过滤 )技术是用於避免画面因放大而出现一个个细小的格仔,从而把放大了的影像柔化,最常见的过滤技术名为双线性过滤 (Bilinear Filtering/Bilinear Interpolation)。而使用 Overlay(重 )最主要的目的是可以使显示出来的影片颜色数量不用与 Windows所用的颜色数量相同,举例说,假如你用的 Windows调校了色深是 256色,但你播 MPEG1/MPEG2时却可显示 24bit色深,那就是 Overlay。 Overlay的另一个优点是可以不需要耗用系统资源来将画面放大缩小,以及支援 Overlay技术的显示晶片每秒可显示格数,远比不支援 Overlay技术的显示晶片为多。

 

 

 

FillEllips 函数填充指定的椭圆。椭圆心为(sx, sy),X 轴半径为 rx,Y 轴半径为 ry。
  FillSector 函数填充由圆弧和两条半径形成的扇形。圆心为(x, y),半径为 r,起始弧度为 ang1,终止弧度为 ang2。
  FillPolygon 函数填充多边形。pts 表示多边形各个顶点,vertices 表示多边形顶点个数。
  FloodFill 从指定点(x, y)开始填注。
  需要注意的是,所有填充函数使用当前画刷属性(颜色),并且受当前光栅操作的影响。
  
  下面的例子说明了如何使用 FillCircle 和 FillEllipse 函数填充圆或者椭圆。假定给定了两个点,pts[0] 和 pts[1],其中 pts[0] 是圆心或者椭圆心,而 pts[1] 是圆或者椭圆外切矩形的一个顶点。
  
        int rx = ABS (pts[1].x - pts[0].x);
        int ry = ABS (pts[1].y - pts[0].y);
  
        if (rx == ry)
          FillCircle (hdc, pts[0].x, pts[0].y, rx);
        else
          FillEllipse (hdc, pts[0].x, pts[0].y, rx, ry);
  
  5 建立复杂区域
  
  除了利用填充生成器进行填充绘制以外,我们还可以使用填充生成器建立由封闭曲线包围的复杂区域。我们知道,MiniGUI 当中的区域是由互不相交的矩形组成的,并且满足 x-y-banned 的分布规则。利用上述的多边形或者封闭曲线生成器,可以将每条扫描线看成是组成区域的高度为 1 的一个矩形,这样,我们可以利用这些生成器建立复杂区域。MiniGUI 利用现有的封闭曲线生成器,实现了如下的复杂区域生成函数:
  
  BOOL GUIAPI InitCircleRegion (PCLIPRGN dst, int x, int y, int r);
  BOOL GUIAPI InitEllipseRegion (PCLIPRGN dst, int x, int y, int rx, int ry);
  BOOL GUIAPI InitPolygonRegion (PCLIPRGN dst, const POINT* pts, int vertices);
  BOOL GUIAPI InitSectorRegion (PCLIPRGN dst, const POINT* pts, int vertices);
  
  利用这些函数,我们可以将某个区域分别初始化为圆、椭圆、多边形和扇形区域。然后,可以利用这些区域进行点击测试(PtInRegion 和 RectInRegion),或者选择到 DC 当中作为剪切域,从而获得特殊显示效果。
  
  6 直接访问显示缓冲区
  
  在新的 GDI 接口中,我们添加了用来直接访问显示缓冲区的函数,原型如下:
  
  Uint8* GUIAPI LockDC (HDC hdc, const RECT* rw_rc, int* width, int* height, int* pitch);
  void GUIAPI UnlockDC (HDC hdc);
  
  LockDC 函数锁定给定 HDC 的指定矩形区域(由矩形 rw_rc指定,设备坐标),然后返回缓冲区头指针。当 width、height、pitch 三个指针不为空时,该函数将返回锁定之后的矩形有效宽度、有效高度和每扫描线所占的字节数。
  UnlockDC 函数解开已锁定的 HDC。
  锁定一个 HDC 意味着 MiniGUI 进入以互斥方式访问显示缓冲区的状态。如果被锁定的 HDC 是一个屏幕 DC(即非内存 DC),则该函数将在必要时隐藏鼠标光标,并锁定 HDC 对应的全局剪切域。在锁定一个 HDC 之后,程序可通过该函数返回的指针对锁定区域进行访问。需要注意的是,不能长时间锁定一个 HDC,也不应该在锁定一个 HDC 时进行其他额外的系统调用。
  
  假定以锁定矩形左上角为原点建立坐标系,X 轴水平向右,Y 轴垂直向下,则可以通过如下的公式计算该坐标系中(x, y)点对应的缓冲区地址(假定该函数返回的指针值为 frame_buffer):
  
    Uint8* pixel_add = frame_buffer + y * (*pitch) + x * GetGDCapability (hdc, GDCAP_BPP);
  
  根据该 HDC 的颜色深度,就可以对该象素进行读写操作。作为示例,下面的程序段随机填充锁定区域:
  
    int i, width, height, pitch;
    RECT rc = {0, 0, 200, 200};
    int bpp = GetGDCapability (hdc, GDCAP_BPP);
    Uint8* frame_buffer = LockDC (hdc, &rc, &width, &height, &pitch);
    Uint8* row = frame_buffer;
  
    for (i = 0; i < *height; i++) {
      memset (row, rand ()%0x100, *width * bpp);
      row += *pitch;
    }
  
    UnlockDC (hdc);
  
  
  7 YUV 覆盖和 Gamma 校正
  
  为了增强 MiniGUI 对多媒体的支持,我们增加了对 YUV 覆盖(Overlay)和 Gamma 校正的支持。
  
  7.1 YUV 覆盖(Overlay)
  
  多媒体领域中,尤其在涉及到 MPEG 播放时,通常使用 YUV 颜色空间来表示颜色,如果要在屏幕上显示一副 MPEG 解压之后的图片,则需要进行 YUV 颜色空间到 RGB 颜色空间的转换。YUV 覆盖最初来自一些显示芯片的加速功能。这种显示芯片能够在硬件基础上完成 YUV 到 RGB 的转换,免去软件转换带来的性能损失。在这种显示芯片上建立了 YUV 覆盖之后,可以直接将 YUV 信息写入缓冲区,硬件能够自动完成 YUV 到 RGB 的转换,从而在 RGB 显示器上显示出来。在不支持 YUV 覆盖的显示芯片上,MiniGUI 也能够通过软件实现 YUV 覆盖,这时,需要调用 DisplayYUVOverlay 函数将 YUV 信息转换并缩放显示在建立 YUV 覆盖的 DC 设备上。
  
  MiniGUI 提供的 YUV 覆盖操作函数原型如下:
  
  /***************************** YUV overlay support ***************************/
  /* 最常见的视频覆盖格式.
  */
  #define GAL_YV12_OVERLAY 0x32315659  /* Planar mode: Y + V + U (3 planes) */
  #define GAL_IYUV_OVERLAY 0x56555949  /* Planar mode: Y + U + V (3 planes) */
  #define GAL_YUY2_OVERLAY 0x32595559  /* Packed mode: Y0+U0+Y1+V0 (1 plane) */
  #define GAL_UYVY_OVERLAY 0x59565955  /* Packed mode: U0+Y0+V0+Y1 (1 plane) */
  #define GAL_YVYU_OVERLAY 0x55595659  /* Packed mode: Y0+V0+Y1+U0 (1 plane) */
  
  /* 该函数创建一个视频输出覆盖
  */
  GAL_Overlay* GUIAPI CreateYUVOverlay (int width, int height,
          Uint32 format, HDC hdc);
  
  /* 锁定覆盖进行直接的缓冲区读写,结束后解锁 */
  int GAL_LockYUVOverlay (GAL_Overlay *overlay);
  void GAL_UnlockYUVOverlay (GAL_Overlay *overlay);
  
  #define LockYUVOverlay GAL_LockYUVOverlay
  #define UnlockYUVOverlay GAL_UnlockYUVOverlay
  
  /* 释放视频覆盖 */
  void GAL_FreeYUVOverlay (GAL_Overlay *overlay);
  #define FreeYUVOverlay GAL_FreeYUVOverlay
  
  /* 将视频覆盖传送到指定 DC 设备上。该函数能够进行 2 维缩放
  */
  void GUIAPI DisplayYUVOverlay (GAL_Overlay* overlay, const RECT* dstrect);
  
  有关视频格式的信息,可参见:
  
  
  
  有关颜色空间的相互关系的息,可参见:
  
  ~aly/polygon/info/color-space-faq.html
  
  7.2 Gamma 校正
  
  Gamma 校正通过为 RGB 颜色空间的每个颜色通道设置 Gamma 因子,来动态调整 RGB 显示器上的实际 RGB 效果。需要注意的是,Gamma 校正需要显示芯片的硬件支持。
  
  应用程序可以通过 SetGamma 函数设置 RGB 三个颜色通道的 Gamma 校正值。该函数原型如下:
  
  int GAL_SetGamma (float red, float green, float blue);
  #define SetGamma GAL_SetGamma
  
  线性 Gamma 校正值的范围在 0.1 到 10.0 之间。如果硬件不支持 Gamma 校正,该函数将返回 -1。
  
  应用程序也可以通过 SetGammaRamp 函数设置 RGB 三个颜色通道的非线性 Gamma 校正值。该函数原型如下:
  
  int GAL_SetGammaRamp (Uint16 *red, Uint16 *green, Uint16 *blue);
  #define SetGammaRamp GAL_SetGammaRamp
  
  int GAL_GetGammaRamp (Uint16 *red, Uint16 *green, Uint16 *blue);
  #define GetGammaRamp GAL_GetGammaRamp
  
  函数 SetGammaRamp 实际设置的是每个颜色通道的 Gamma 转换表,每个表由 256 个值组成,表示设置值和实际值之间的对应关系。当设置屏幕上某个象素的 RGB 分别为 R、G、B 时,实际在显示器上获得的象素 RGB 值分别为:red[R]、green[G]、blue[B]。如果硬件不支持 Gamma 校正,该函数将返回 -1。
  
  函数 GetGammaRamp 获得当前的 Gamma 转换表。
  
  Gamma 校正的最初目的,是为了能够在显示器上精确还原一副图片。Gamma 值在某种程度上表示的是某个颜色通道的对比度变化。但 Gamma 在多媒体和游戏程序中有一些特殊用途――通过 Gamma 校正,可以方便地获得对比度渐进效果。
  
  8 小结
  
  本文描述了自 MiniGUI 1.1.0Pre4 版本发布以来新增的 GDI 接口。这些接口涉及到曲线和填充生成器、复杂曲线的绘制、封闭曲线填充、复杂区域的创建、直接访问 FrameBuffer、YUV 覆盖和 Gamma 校正等等。通过本文的介绍,相信读者能够对 MiniGUI 的新 GDI 接口有一个更加全面的认识。
  

阅读(1661) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~