C++ 如何创建颜色栏(电视测试图案)
我需要创建一个像这样的颜色条 我使用0到1之间的浮动的缩放数组 现在我想从这个浮点数计算RGB颜色。怎么做?想用C/C++编写它,所以我想我需要两个函数 第一个函数使用一个参数(如步长)构建colorbar,第二个函数需要该值,并且必须只返回colorbar的数组索引C++ 如何创建颜色栏(电视测试图案),c++,c,rgb,C++,C,Rgb,我需要创建一个像这样的颜色条 我使用0到1之间的浮动的缩放数组 现在我想从这个浮点数计算RGB颜色。怎么做?想用C/C++编写它,所以我想我需要两个函数 第一个函数使用一个参数(如步长)构建colorbar,第二个函数需要该值,并且必须只返回colorbar的数组索引 我在google上找不到它,所以请帮助我。RGB使用字节,所以假设您的浮点数组类似 float scaledColor[3]; // 0 = R, etc., all 0.0 < scaledColor[x] < 1.
我在google上找不到它,所以请帮助我。RGB使用字节,所以假设您的浮点数组类似
float scaledColor[3]; // 0 = R, etc., all 0.0 < scaledColor[x] < 1.0
当然,这只在浮点中的值确实在0.0到1.0之间时才起作用。RGB使用字节,因此假设浮点数组类似于
float scaledColor[3]; // 0 = R, etc., all 0.0 < scaledColor[x] < 1.0
当然,这只有在浮动中的值确实在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))];
}
然后,您可以使用它生成任意宽度的条形图。最简单的解决方案:
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颜色代码(如果您只需要它们)。这篇文章还提到了如何生成这些颜色,但这似乎要困难得多,不值得为七种颜色付出努力。我的google fu发现,您需要SMPTE颜色条图案的上三分之一。 维基百科说: 从左到右依次为灰色、黄色、青色、绿色、, 品红色、红色和蓝色
因此,最简单的方法是只需硬编码相应的RGB颜色代码(如果您只需要它们)。这篇文章还提到了如何生成这些颜色,但这似乎要困难得多,不值得为七种颜色付出努力。这里您指的是以标准机构欧洲广播联盟命名的100%EBU颜色条。这与完整的SMPTE RP 219-2002颜色条不同,后者具有其他功能,包括渐变和Plug图片线生成设备,如维基百科上的文章所述 EBU颜色条由8个宽度相等的垂直条组成。对于SD和HD格式,它们的定义方式相同。在RGB颜色空间中,它们以不同的速率交替每个红色、绿色和蓝色通道,就像从0到100%强度的二进制计数一样。以从左到右的标准化RGB形式从白色开始倒计时: 1,1,1:白色 1,1,0:黄色 0,1,1:青色 0,1,0:绿色 1,0,1:洋红色 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;
}
这应该很容易适应任何其他语言。可能不需要使用float,除非您在GPU上实现它,在这种情况下,算法会非常不同。这里有很大的优化空间;编写代码是为了清晰,而不是为了速度
请注意,虽然可以在计算机中生成颜色条的完美数字表示,但这对于广播来说并不安全。完美颜色条之间的过渡需要无限高的带宽才能准确表示。因此,如果测试图像是通过模拟广播设备传输的,它的带宽必须受到低通滤波器的限制,例如PAL为~4.3MHz。这就是为什么你会注意到每列之间的模糊边界;这些包含纯颜色之间的中间值
还请注意,不可能在RGB颜色空间中准确表示SMPTE颜色条。这是因为在YCb'Cr'颜色空间中指定了某些临界值,特别是在RGB色域SD或HD之外的PLUGE区域。您可以创建一些近似值的东西,例如深蓝色,但它们不正确。因此,除非您用YCb'Cr'表示测试帧,否则请仅使用上面2/3的EBU色条。这里您指的是以标准机构欧洲广播联盟命名的100%EBU色条。这与完整的SMPTE RP 219-2002颜色条不同,后者具有其他功能,包括渐变和Plug图片线生成设备,如维基百科上的文章所述 T EBU颜色条由8条宽度相等的垂直条组成。对于SD和HD格式,它们的定义方式相同。在RGB颜色空间中,它们以不同的速率交替每个红色、绿色和蓝色通道,就像从0到100%强度的二进制计数一样。以从左到右的标准化RGB形式从白色开始倒计时: 1,1,1:白色 1,1,0:黄色 0,1,1:青色 0,1,0:绿色 1,0,1:洋红色 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;
}
这应该很容易适应任何其他语言。可能不需要使用float,除非您在GPU上实现它,在这种情况下,算法会非常不同。这里有很大的优化空间;编写代码是为了清晰,而不是为了速度
请注意,虽然可以在计算机中生成颜色条的完美数字表示,但这对于广播来说并不安全。完美颜色条之间的过渡需要无限高的带宽才能准确表示。因此,如果测试图像是通过模拟广播设备传输的,它的带宽必须受到低通滤波器的限制,例如PAL为~4.3MHz。这就是为什么你会注意到每列之间的模糊边界;这些包含纯颜色之间的中间值
还请注意,不可能在RGB颜色空间中准确表示SMPTE颜色条。这是因为在YCb'Cr'颜色空间中指定了某些临界值,特别是在RGB色域SD或HD之外的PLUGE区域。您可以创建一些近似值的东西,例如深蓝色,但它们不正确。因此,除非您用YCb'Cr'表示测试帧,否则请仅使用EBU条的上2/3。到目前为止,您已经完成了哪些工作?考虑使用255 255 0,将我的浮点从0到255进行缩放,并将其用作RG,b每次为0。。但是这个suxxx你的阵列现在看起来怎么样?这些值究竟代表什么?你知道RGB颜色是如何工作的吗?你到底需要什么帮助?你需要知道如何画东西吗?或者仅仅是什么?浮点数和rgb通常是不相关的。你想用哪种算法从一个转换到另一个?@Raiv这是个问题,我只是有一个浮点数,必须把它转换成rgb。witch和how不重要,我只需要它:D我需要帮助将浮点转换为rgb颜色。到目前为止,您已经完成了哪些工作?考虑只使用255 255 0,将我的浮点从0到255进行缩放,并将其用作RG,b每次为0。。但是这个suxxx你的阵列现在看起来怎么样?这些值究竟代表什么?你知道RGB颜色是如何工作的吗?你到底需要什么帮助?你需要知道如何画东西吗?或者仅仅是什么?浮点数和rgb通常是不相关的。你想用哪种算法从一个转换到另一个?@Raiv这是个问题,我只是有一个浮点数,必须把它转换成rgb。witch和how不重要,我只需要它:D我需要帮助将浮点转换为rgb颜色作为一名20年的专业广播老手,这是一个关于什么是EBU颜色条,如何创建它们,以及为什么在rgb颜色空间中使用SMPTE颜色条不起作用的难以置信的完整而优秀的答案。非常好@这就是为什么谢谢你不久前我不得不自己解决这个问题,我发现网上有太多的资料不完整、不准确或误导。所以我希望能提供一个彻底的解释,让未来的开发者很容易找到。我甚至没有尝试覆盖不同的颜色空间。。。正如你所知道的,这东西很难做对!作为专业广播20年的老手,这是一个令人难以置信的完整和优秀的答案,关于什么是EBU颜色条,如何创建它们,以及为什么在RGB颜色空间中使用SMPTE颜色条不起作用。非常好@这就是为什么谢谢你不久前我不得不自己解决这个问题,我发现网上有太多的资料不完整、不准确或误导。所以我希望能提供一个彻底的解释,让未来的开发者很容易找到。我甚至没有尝试覆盖不同的颜色空间。。。正如你所知道的,这东西很难做对!