如何创建彩条(电视测试图案)

时间:2011-08-04 09:59:18

标签: c++ c rgb

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

现在我想从这个浮点数计算RGB颜色。怎么做?想用C / c ++编写,所以我认为我需要2个函数。

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

我在Google上找不到它,所以请帮帮我。

4 个答案:

答案 0 :(得分:6)

您在这里指的是100%EBU彩条(以标准组织欧洲广播联盟命名)。这与完整的SMPTE RP 219-2002彩条不同,后者具有其他功能,包括渐变和PLUGE(画面阵容生成设备),在Color Bars上的维基百科文章中有描述。

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:蓝色
  • 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, "P6\n%u %u\n255\n", kWidth, kHeight);
    fwrite(frame, frameBytes, 1, fout);
    fclose(fout);

    free(frame);

    return 0;
}

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

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

另请注意,可以准确地表示RGB颜色空间中的SMPTE颜色条。这是因为在YCb'Cr'颜色空间(特别是在PLUGE区域)中指定了某些临界值,这些颜色空间在RGB色域(SD或HD)之外。您可以创建近似值的内容(例如,深蓝色),但它们正确。因此,除非您在YCb'Cr'中表示测试帧,否则仅限于EBU条(上部2/3)。

答案 1 :(得分:0)

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的范围内时才有效。

答案 2 :(得分: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))];
}

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

答案 3 :(得分:0)

我的google-fu出现了你想要SMPTE彩条模式的上三分之一。 维基百科说:

  

从左到右依次为灰色,黄色,青色,绿色,   洋红色,红色和蓝色。

因此,最简单的方法是只需硬编码相应的RGB颜色代码即可。文章还提到了如何生成这些颜色,但这看起来要困难得多,并不值得为七种颜色付出努力。