我需要创建一个像THIS这样的颜色栏 我使用0到1之间的缩放浮点数组。
现在我想从这个浮点数计算RGB颜色。怎么做?想用C / c ++编写,所以我认为我需要2个函数。
使用一个参数(如STEPSIZE)构建颜色条的第一个函数,第二个函数需要该值,并且必须只返回颜色条的数组索引。
我在Google上找不到它,所以请帮帮我。
答案 0 :(得分:6)
您在这里指的是100%EBU彩条(以标准组织欧洲广播联盟命名)。这与完整的SMPTE RP 219-2002彩条不同,后者具有其他功能,包括渐变和PLUGE(画面阵容生成设备),在Color Bars上的维基百科文章中有描述。
EBU彩条由8个相等宽度的垂直条组成。对于SD和HD格式,它们的定义方式相同。在RGB颜色空间中,它们以0到100%的强度以不同的速率(非常类似于二进制计数)交替每个红色,绿色和蓝色通道。从白色开始向下计数,采用标准化RGB格式(从左到右显示):
因此蓝色通道交替显示每列,红色通道在两列之后,绿色在四列之后。这种排列具有有用的特性,即亮度(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.0
到1.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颜色代码即可。文章还提到了如何生成这些颜色,但这看起来要困难得多,并不值得为七种颜色付出努力。