То, на что вы ссылаетесь, - это цветные полоски EBU 100% (названные в честь органа по стандартизации Европейского вещательного союза).Это не то же самое, что полные цветные полосы 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: пурпурный
- 1, 0, 0: красный
- 0, 0, 1: синий
- 0, 0, 0: черный
Таким образом, синий канал чередует каждый столбец, красный канал после двух столбцов и зеленыйпосле четырех столбцов.Это расположение имеет полезное свойство, заключающееся в том, что яркость (Y в цветовом пространстве YCb'Cr ') приводит к пошаговому графику.
Для визуализации с использованием 8-битного RGB (чаще всего встречается в настольных системах), просто умножьтевышеупомянутые значения на 255. Бары EBU бывают в 75% и 100% вариантах, в зависимости от интенсивности белого столбца.Цветные полосы SMPTE обычно используют уровни 75% в качестве эталона.
Вот простой код C для генерации цветных полос EBU 100% и сохранения результата в виде файла 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 (в этом случае алгоритм будет совсем другим).Здесь есть много возможностей для оптимизации;код написан для ясности, а не для скорости.
Обратите внимание, что, хотя в компьютере можно создать идеальное цифровое представление цветовых полос, это не будет безопасно для трансляции.Переходы между «идеальными» цветными полосами потребуют бесконечно высокой полосы пропускания для точного представления.Поэтому, если тестовое изображение должно передаваться через аналоговое вещательное оборудование, оно должно быть ограничено по полосе пропускания фильтром нижних частот (например, ~ 4,3 МГц для PAL).Вот почему вы замечаете «нечеткие» границы между каждым столбцом;они содержат промежуточные значения между чистыми цветами.
Также обратите внимание, что не позволяет точно представлять цветные полосы SMPTE в цветовом пространстве RGB.Это связано с тем, что определенные критические значения указаны в цветовом пространстве YCb'Cr '(особенно в области PLUGE), которые находятся за пределами гаммы RGB (SD или HD).Вы можете создать что-то, что приближает значения (например, очень темно-синий), но они не правильны.Поэтому, если вы не представляете тестовый фрейм в YCb'Cr ', придерживайтесь только столбцов EBU (верхние 2/3).