我如何创建一个颜色条(电视测试模式)

How do I create a color bar (TV test pattern)

本文关键字:模式 颜色 电视 一个 测试 何创建 创建      更新时间:2023-10-16

我需要创建一个像这样的颜色栏我使用的是0到1之间的浮点数的缩放数组。

现在我想计算这个浮点数的RGB颜色。怎么做呢?我想用C/c++写,所以我想我需要两个函数。

第一个函数用一个参数(如STEPSIZE)构建colorbar,第二个函数需要这个值,并且必须只返回colorbar的数组索引。

我在google上找不到,请帮帮我。

您这里所指的是100% EBU彩色条(以标准机构欧洲广播联盟命名)。这与完整的SMPTE RP 219-2002色条不同,后者具有其他功能,包括渐变和PLUGE(图片排列生成设备),这些功能在维基百科关于色条的文章中有描述。

EBU颜色条由8个宽度相等的垂直条组成。它们以相同的方式定义SD和HD格式。在RGB色彩空间中,它们以不同的速率交替红色、绿色和蓝色通道(很像二进制计数)从0到100%的强度。从白色开始倒数,正规化RGB格式(从左到右):

  • 1,1,1:白色
  • 1,1,0:黄色
  • 0、1、1:青色
  • 0、1、0:绿色
  • 1,0,1: Magenta
  • 1,0,0:红色
  • 0,0,1: Blue
  • 0,0,0:黑色

所以蓝色通道每一列交替,红色通道每两列交替,绿色通道每四列交替。这种排列有一个有用的特性,即亮度(YCb' cr '色彩空间中的Y)会导致向下的步进图。

要使用8位RGB(最常见于桌面系统)进行渲染,只需将上述值乘以255。EBU条有75%和100%的变体,基于白色柱的强度。SMPTE色条通常使用75%的色阶作为参考。

下面是一些简单的C代码,用于生成100% EBU颜色条并将结果保存为PGM文件:

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
// PAL dimensions
static const unsigned kWidth = 720;
static const unsigned kHeight = 576;
typedef struct
{
    uint8_t     r;
    uint8_t     g;
    uint8_t     b;
} RGB;
int main(int argc, char* argv[])
{
    const RGB BAR_COLOUR[8] =
    {
        { 255, 255, 255 },  // 100% White
        { 255, 255,   0 },  // Yellow
        {   0, 255, 255 },  // Cyan
        {   0, 255,   0 },  // Green
        { 255,   0, 255 },  // Magenta
        { 255,   0,   0 },  // Red
        {   0,   0, 255 },  // Blue
        {   0,   0,   0 },  // Black
    };
    // Allocate frame buffer
    size_t      frameBytes = kWidth*kHeight*sizeof(RGB);
    RGB*        frame = malloc(frameBytes);
    unsigned    columnWidth = kWidth / 8;
    // Generate complete frame
    for (unsigned y = 0; y < kHeight; y++)
    {
        for (unsigned x = 0; x < kWidth; x++)
        {
            unsigned col_idx = x / columnWidth;
            frame[y*kWidth+x] = BAR_COLOUR[col_idx];
        }
    }
    // Save as PPM
    FILE* fout = fopen("ebu_bars.ppm", "wb");
    fprintf(fout, "P6n%u %un255n", kWidth, kHeight);
    fwrite(frame, frameBytes, 1, fout);
    fclose(fout);
    free(frame);
    return 0;
}

这应该很容易适应于任何其他语言。可能没有必要使用float,除非你在GPU上实现它(在这种情况下,算法将完全不同)。这里有很大的优化空间;代码是为了清晰而编写的,而不是为了速度。

请注意,虽然在计算机中生成彩色条的完美数字表示是可能的,但这对于广播来说并不安全。"完美"色条之间的过渡需要无限高的带宽才能准确地表示。因此,如果测试图像要通过模拟广播设备传输,则必须通过低通滤波器(例如:~4.3MHz用于PAL)。这就是为什么你会注意到每一列之间的"模糊"边界;这些包含纯色之间的中间值。

还要注意,不可能准确地表示RGB色彩空间中的SMPTE色条。这是因为在YCb' cr '色彩空间(特别是在PLUGE区域)中指定了某些临界值,这些临界值超出了RGB (SD或HD)的色域。您可以创建一些近似的值(例如。深蓝色),但它们正确。因此,除非您用YCb' cr '表示测试框架,否则只坚持使用EBU条(上面的2/3)。

RGB使用字节,因此假设您的浮点数组类似于

float scaledColor[3]; // 0 = R, etc., all 0.0 < scaledColor[x] < 1.0

那么你可以这样做:

unsigned char r = (unsigned char)(255 * scaledColor[0]);
unsigned char g = (unsigned char)(255 * scaledColor[1]);
unsigned char b = (unsigned char)(255 * scaledColor[2]);

当然,只有当浮点数的值确实在0.01.0的范围内时,这才会起作用。

最简单的解决方案:

const unsigned char* getColour(float x) /* 0 <= x < 1 */
{
    static const unsigned char bar[][3] = {
        {255,255,255},
        {255,255,0},
        // ... fill in all the colours ...
        {0,0,0}
    };
    return bar[(int)(x*sizeof(bar))];
}

然后你可以使用它来生成任意宽度的条。

我的google-fu显示您想要SMPTE颜色条模式的上三分之一。维基百科说:

从左到右依次为灰色、黄色、青色、绿色、品红、红、蓝

所以最简单的方法是简单地硬编码各自的RGB颜色代码,如果你只需要那些。本文还提到了如何生成这些颜色,但这似乎要困难得多,并且不值得为七种颜色付出努力。