--VideoColor.mesa
--last edited by Maureen Stone September 13, 1982 2:02 pm

DIRECTORY
GraphicsColor,
Graphics,
LinearSystem,
JaMFnsDefs,
RealFns;

VideoColor: PROGRAM
IMPORTS RealFns, LinearSystem, JaMFnsDefs = {

--this procedure clips the current r,g,b to be within the NTSC bandwidth for chroma
--algorithm from Siggraph tutorial on animation (C. R. Odgers)

matrix: LinearSystem.Matrix3 ← [[.299, .587, .11], [.599, -.2773, -.3217], [.213, -.525, .3121]];

ClipColor: PROC [r,g,b: REAL] RETURNS [nr,ng,nb: REAL] = {
 i,y,q,cr,cg,cb: REAL;
 gamma: REAL ← 2.2;
 igamma: REAL ← 1.0/2.2;
 videoAmplitude: REAL;
--gamma correct r,g,b and convert to i, y, q
 cr ← RealFns.Power[r,igamma];
 cg ← RealFns.Power[g,igamma];
 cb ← RealFns.Power[b,igamma];
 y ← matrix[1][1]*cr+matrix[1][2]*cg+matrix[1][3]*cb;
 i ← matrix[2][1]*cr+matrix[2][2]*cg+matrix[2][3]*cb;
 q ← matrix[3][1]*cr+matrix[3][2]*cg+matrix[3][3]*cb;
 videoAmplitude ← y+RealFns.SqRt[(i*i)+(q*q)];
 IF videoAmplitude>1 THEN {
  f: REAL ← 1.0/videoAmplitude;
  rgb,yiq: LinearSystem.Column3;
  yiq[1] ← y/videoAmplitude;
  yiq[2] ← i/videoAmplitude;
  yiq[3] ← q/videoAmplitude;
  rgb ← LinearSystem.Solve3[matrix,yiq];
  nr ← RealFns.Power[MAX[0,rgb[1]],gamma];
  ng ← RealFns.Power[MAX[0,rgb[2]],gamma];
  nb ← RealFns.Power[MAX[0,rgb[3]],gamma];
  RETURN[nr,ng,nb];
  }
 ELSE RETURN[nr: r, ng: g, nb: b];
 };

SetColor
: PROC = {
 r,g,b: REAL;
 b ← JaMFnsDefs.PopReal[];
 g ← JaMFnsDefs.PopReal[];
 r ← JaMFnsDefs.PopReal[];
 [r,g,b] ← ClipColor[r,g,b];
 JaMFnsDefs.PushReal[r];
 JaMFnsDefs.PushReal[g];
 JaMFnsDefs.PushReal[b];
 };

JaMFnsDefs.Register[".ntsccolor", SetColor];
}.