XV-Display: refine the formulation of the image-generator

- since we now use 32bit int arithmetic (which is faster),
   we can also use the exact value of the MPEG / Rec.601 coefficients

 - and also the generation of the NTSC colour bar pattern
   can be written much simpler and cleare with C++
This commit is contained in:
Fischlurch 2025-05-11 16:06:20 +02:00
parent 8fe50e37a4
commit b42143f425
3 changed files with 70 additions and 49 deletions

View file

@ -44,8 +44,8 @@ namespace node {
Trip yuv;
auto& [y,u,v] = yuv;
y = byte(clamp ( 0 + ( 299 * r + 587 * g + 114 * b) / 1000, 16,235)); // Luma clamped to MPEG scan range
u = byte(clamp (128 + (-169 * r - 331 * g + 500 * b) / 1000, 0, 255)); // Chroma components mapped according to Rec.601
v = byte(clamp (128 + ( 500 * r - 419 * g - 81 * b) / 1000, 0, 255)); // (but with integer arithmetics and slightly rounded coefficients)
u = byte(clamp (128 + (-168736 * r - 331264 * g + 500000 * b) / 1000000, 0, 255)); // Chroma components mapped according to Rec.601
v = byte(clamp (128 + ( 500000 * r - 418688 * g - 81312 * b) / 1000000, 0, 255)); // (but with integer arithmetics and slightly rounded coefficients)
return yuv;
}
@ -93,8 +93,14 @@ namespace node {
frame_ = 0;
if(frame_ < 1 * fps_)
{
// create random snow...
generateNoise (buffer);
else
generateBars (buffer);
}
void
DummyImageGenerator::generateNoise (DummyFrame buffer)
{ // create random snow...
for (uint i = 0; i < W*H*3; i+=3)
{
auto value = byte(rand());
@ -103,37 +109,42 @@ namespace node {
buffer[i+2] = value;
}
}
else
{ // create a colour strip pattern
typedef byte Row[W * 3];
byte* row = buffer;
// create a colour strip pattern in the first row...
for (uint x = 0; x < W; ++x)
/** fill the RGB-Buffer with the well-known NTSC colour-bar pattern */
void
DummyImageGenerator::generateBars (DummyFrame buffer)
{
byte& r = row[x*3];
byte& g = row[x*3+1];
byte& b = row[x*3+2];
using Row = std::array<Trip, W>;
using Img = std::array<Row, H>;
Img& img = reinterpret_cast<Img&> (*buffer);
Row& row = img[0];
const byte ON = byte(0xC0);
const byte OFF{0};
if (x < 1*W/7) r = ON, g = ON, b = ON;
else if(x < 2*W/7) r = ON, g = ON, b = OFF;
else if(x < 3*W/7) r = OFF, g = ON, b = ON;
else if(x < 4*W/7) r = OFF, g = ON, b = OFF;
else if(x < 5*W/7) r = ON, g = OFF, b = ON;
else if(x < 6*W/7) r = ON, g = OFF, b = OFF;
else r = OFF, g = OFF, b = ON;
// classic NTSC colour bars --R---G---B--
std::array<Trip, 7> bars = {{{ ON, ON, ON}
,{ ON, ON,OFF}
,{OFF, ON, ON}
,{OFF, ON,OFF}
,{ ON,OFF, ON}
,{ ON,OFF,OFF}
,{OFF,OFF, ON}
}};
// create a colour strip pattern in the first row...
for (uint x = 0; x < W; ++x)
{ // quantise into 7 columns
uint col = x * 7/W;
row[x] = bars[col];
}
// fill remaining rows of the frame with the same pattern
for (uint y = 1; y < H; ++y)
memcpy(buffer + y*sizeof(Row), row, sizeof(Row));
img[y] = row;
}
}
}
DummyFrame
DummyImageGenerator::next()

View file

@ -72,6 +72,8 @@ namespace node {
std::array<std::byte,BUFF_SIZ> outFrame_B_;
void generateFrame (DummyFrame buffer);
void generateNoise (DummyFrame buffer);
void generateBars (DummyFrame buffer);
};

View file

@ -130179,21 +130179,25 @@ StM_bind(Builder&lt;R1&gt; b1, Extension&lt;R1,R2&gt; extension)
<icon BUILTIN="idea"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1746921512647" ID="ID_1654688911" MODIFIED="1746921530413" TEXT="erster Schritt: Code reorganisieren und klarer machen">
<icon BUILTIN="flag-yellow"/>
<node COLOR="#338800" CREATED="1746921512647" ID="ID_1654688911" MODIFIED="1746971761434" TEXT="erster Schritt: Code reorganisieren und klarer machen">
<icon BUILTIN="button_ok"/>
<node CREATED="1746921531585" ID="ID_156630022" MODIFIED="1746921551379" TEXT="den double-buffering-Mechanismus von der Bildgenerierung trennen"/>
<node CREATED="1746921552092" ID="ID_492214837" MODIFIED="1746921563913" TEXT="die Farbraumkonvertierung als extra Schritt formulieren">
<node COLOR="#338800" CREATED="1746921552092" ID="ID_492214837" MODIFIED="1746972188067" TEXT="die Farbraumkonvertierung als extra Schritt formulieren">
<icon BUILTIN="button_ok"/>
<node CREATED="1746921707185" ID="ID_1757569540" MODIFIED="1746921715007" TEXT="dabei auch die Theorie nochmal verifizieren">
<node CREATED="1746921716337" ID="ID_683787640" MODIFIED="1746921728880" TEXT="&quot;yuv&quot; ist selber ein ungenauer Begriff"/>
<node CREATED="1746921729694" ID="ID_1983082888" MODIFIED="1746921740370" TEXT="gemeint ist meist YCrCb"/>
<node CREATED="1746929700320" ID="ID_878404124" MODIFIED="1746929714669" TEXT="die Koeffizienten sind eindeutig von Rec.601 / MPEG"/>
<node CREATED="1746929715402" ID="ID_1228492062" MODIFIED="1746929744583" TEXT="sie sind nur vereinfacht, damit man es mit 16bit Integer-Arrithmetik machen kann"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1746929753402" ID="ID_1545724068" MODIFIED="1746929764957" TEXT="da ich nun die Rechnung auf Int umstelle, k&#xf6;nnte man genauer rechnen">
<icon BUILTIN="flag-yellow"/>
<node CREATED="1746929715402" ID="ID_1228492062" MODIFIED="1746972230168" TEXT="sie sind nur vereinfacht, damit man es mit 16bit Integer-Arrithmetik machen kann">
<arrowlink COLOR="#467bb9" DESTINATION="ID_1545724068" ENDARROW="Default" ENDINCLINATION="43;-21;" ID="Arrow_ID_198569523" STARTARROW="None" STARTINCLINATION="-96;5;"/>
</node>
</node>
<node CREATED="1746921564743" ID="ID_472874597" MODIFIED="1746921696992" TEXT="umstellen auf std::array und m&#xf6;glichst Pointer durch Referenzen ersetzen">
<node COLOR="#338800" CREATED="1746929753402" ID="ID_1545724068" MODIFIED="1746972230168" TEXT="da ich nun die Rechnung auf Int umstelle, k&#xf6;nnte man genauer rechnen">
<linktarget COLOR="#467bb9" DESTINATION="ID_1545724068" ENDARROW="Default" ENDINCLINATION="43;-21;" ID="Arrow_ID_198569523" SOURCE="ID_1228492062" STARTARROW="None" STARTINCLINATION="-96;5;"/>
<icon BUILTIN="button_ok"/>
</node>
</node>
<node COLOR="#338800" CREATED="1746921564743" ID="ID_472874597" MODIFIED="1746972240706" TEXT="umstellen auf std::array und m&#xf6;glichst Pointer durch Referenzen ersetzen">
<richcontent TYPE="NOTE"><html>
<head>
@ -130205,6 +130209,7 @@ StM_bind(Builder&lt;R1&gt; b1, Extension&lt;R1,R2&gt; extension)
</body>
</html>
</richcontent>
<icon BUILTIN="button_ok"/>
</node>
<node COLOR="#435e98" CREATED="1746929669548" ID="ID_485365336" MODIFIED="1746936730029" TEXT="tja... compiliert aber das Ausgabeformat stimmt nicht">
<icon BUILTIN="broken-line"/>
@ -130230,6 +130235,9 @@ StM_bind(Builder&lt;R1&gt; b1, Extension&lt;R1,R2&gt; extension)
</node>
<node CREATED="1746936671244" ID="ID_1148968519" MODIFIED="1746936695084" TEXT="&#x27f9; mu&#xdf; also doch direkt nach dem Zugriff auf die Input-Daten nach int casten"/>
</node>
<node COLOR="#338800" CREATED="1746971763801" ID="ID_505273316" MODIFIED="1746971792732" TEXT="Auch die Generierung der Colour-Bars kann man in C++ viel eleganter formulieren">
<icon BUILTIN="button_ok"/>
</node>
</node>
</node>
</node>