我如何创建一个颜色条(电视测试模式)
How do I create a color bar (TV test pattern)
我需要创建一个像这样的颜色栏我使用的是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.0
到1.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颜色代码,如果你只需要那些。本文还提到了如何生成这些颜色,但这似乎要困难得多,并且不值得为七种颜色付出努力。
- 具有奇怪重复模板模式的派生类中的成员变量已损坏
- 将"打开的CV图像"中的"颜色"转换为整数格式
- 为什么在保护模式下继承升级不起作用
- 如何在全屏模式下(在OpenGL中)使背景透明
- 为什么使用__LINE_的代码在发布模式下在MSVC下编译,而不是在调试模式下
- 派生类是否可以在抽象工厂设计模式中具有数据成员
- 如何在内核C++中使用1920x1080x16M图形或类似的16M颜色?(VGA)
- 如何在24位SDL_Surface上设置像素的颜色
- 此模式的C++RegEx
- avrogencpp能为模式中的每种类型生成单独的头文件吗
- 使用可变模板的Broadcaster/Listener模式
- c++方法参数只能在linux的发布模式下自行更改
- 资源管理设计模式
- 如何从SDL_Surface获取特定像素的颜色
- 使用 mod_gsoap 部署服务时,如何在 Gsoap 中更改 soap 上下文的模式?
- C++ 无法在字符数组中使用 for 循环打印字母模式
- 全屏模式下的快板颜色更改
- QOpenGL:颜色索引模式
- 在DirectX9中设置纹理寻址模式为边框颜色
- 我如何创建一个颜色条(电视测试模式)