Color8Impl:
CEDAR PROGRAM
IMPORTS ColorMap, ColorMapImpl, ColorPackagePrivate, ConvertUnsafe, Graphics, GraphicsOps, JaMFnsDefs, Map, Real, TJaMGraphics
SHARES ColorMapImpl = BEGIN
table: Map.ColorTable;
palette: Map.PalTable;
Init:
PROCEDURE [] =
TRUSTED {
JaMFnsDefs.Register["LoadMap"L, JLoadMap];
JaMFnsDefs.Register["ShowRawImage"L, JShowRawImage];
JaMFnsDefs.Register["RestoreMap"L, JRestoreMap];
JaMFnsDefs.Register["RotateMap"L, JRotateMap];
};
JLoadMap:
PROCEDURE [] =
TRUSTED {
s:LONG STRING ← [50];
JaMFnsDefs.PopString[s];
LoadMap[ConvertUnsafe.ToRope[s]];
};
LoadMap:
PROCEDURE [file:Rope.
ROPE] =
TRUSTED {
[table, palette] ← Map.Restore[file];
ColorPackagePrivate.SetNewColorMapProc[PalMapper];
SetUpMap[palette];
};
RestoreMap:
PROCEDURE [] =
TRUSTED {
ColorPackagePrivate.SetNewColorMapProc[ColorMapImpl.MyGetIndex];
ColorMap.StandardMap[];
};
JRestoreMap:
PROCEDURE [] =
TRUSTED {
RestoreMap[];
};
JShowRawImage:
PROCEDURE [] =
TRUSTED {
s:LONG STRING ← [50];
paint: PROC [dc: Graphics.Context] = TRUSTED {
Graphics.DrawImage[self:dc, image:GraphicsOps.NewAisImage[ConvertUnsafe.ToRope[s]], raw:TRUE];
};
JaMFnsDefs.PopString[s];
TJaMGraphics.Painter[paint];
};
PalMapper: ColorPackagePrivate.ColorMapProc =
TRUSTED {
RETURN [Map.GetIndex[r,g,b, table]];
};
SetUpMap:
PROCEDURE [p:Map.PalTable] =
TRUSTED {
FOR palix:
CARDINAL
IN [0..p.size)
DO
ColorMap.SetRGBColor[palix, p[palix].r, p[palix].g, p[palix].b];
ENDLOOP;
};
ToRange: PROC[v: REAL] RETURNS[REAL] = INLINE { IF v IN[0..1] THEN RETURN[v]
ELSE ERROR };
-- ensures that v is in [0..1]; raises BoundsFault if not
HSVToRGB: PROC[h,s,v: REAL] RETURNS[r,g,b: REAL] = {
hue: REAL ← ToRange[h];
saturation: REAL ← ToRange[s];
value: REAL ← ToRange[v];
ihue: INTEGER;
fhue,m,n,k: REAL;
hue ← hue*6;
ihue ← Real.FixI[hue]; --integer hue
fhue ← hue-ihue; --fractional hue
IF ihue=6 THEN ihue ← 0;
m ← value*(1-saturation);
n ← value*(1-(saturation*fhue));
k ← value*(1-(saturation*(1-fhue)));
SELECT ihue FROM
0 => RETURN[value,k,m];
1 => RETURN[n,value,m];
2 => RETURN[m,value,k];
3 => RETURN[m,n,value];
4 => RETURN[k,m,value];
5 => RETURN[value,m,n];
ENDCASE => RETURN[0,0,0];
};
RGBToHSV: PROC[r,g,b: REAL] RETURNS[h,s,v: REAL] = {
max,min,rc,gc,bc: REAL;
r ← ToRange[r]; g ← ToRange[g]; b ← ToRange[b];
min ← MIN[MIN[r,g],b]; --amount of white
v ← max ← MAX[MAX[r,g],b]; --maximum "brightness"
IF max#0 THEN s ← (max-min)/max
ELSE s ← 0;
IF s=0 THEN RETURN[0,0,v]; --gray
rc ← (max - r)/(max - min);
gc ← (max - g)/(max - min);
bc ← (max - b)/(max - min);
IF r=max THEN h-gc
ELSE IF g=max THEN h𡤂+rc-bc
ELSE IF b=max THEN h𡤄+gc-rc;
h ← h / 6.0;
IF h<0 THEN h←h+1;
};
RotateMap:
PROCEDURE [n:
INTEGER] =
TRUSTED {
lr,lg,lb,h,s,v:REAL;
WHILE n>0
DO
FOR i:
CARDINAL IN [0..20]
DO
-- maximise saturations
FOR pix:
CARDINAL
IN [0..palette.size)
DO
OPEN palette[pix];
[h,s,v] ← RGBToHSV[r,g,b];
s ← MIN[s + i / 20.0, 1.0] ;
[lr,lg,lb] ← HSVToRGB[h,s,v];
ColorMap.SetRGBColor[pix, lr,lg,lb];
ENDLOOP;
ENDLOOP;
FOR i:
CARDINAL
DECREASING IN [0..20]
DO
-- reduce the saturations to 0
FOR pix:
CARDINAL
IN [0..palette.size)
DO
OPEN palette[pix];
[h,s,v] ← RGBToHSV[r,g,b];
s ← i/20.0 ;
[lr,lg,lb] ← HSVToRGB[h,s,v];
ColorMap.SetRGBColor[pix, lr,lg,lb];
ENDLOOP;
ENDLOOP;
FOR i:
CARDINAL
IN [0..10]
DO
-- threshold values around 0.5
FOR pix:
CARDINAL
IN [0..palette.size)
DO
OPEN palette[pix];
[h,s,v] ← RGBToHSV[r,g,b];
v ← IF v>0.5 THEN MIN[v+i*0.05, 1.0] ELSE MAX[v-i*0.05, 0.0] ;
s ← 0;
[lr,lg,lb] ← HSVToRGB[h,s,v];
ColorMap.SetRGBColor[pix, lr,lg,lb];
ENDLOOP;
ENDLOOP;
FOR i:
CARDINAL
DECREASING IN [0..10]
DO
-- restore values
FOR pix:
CARDINAL
IN [0..palette.size)
DO
OPEN palette[pix];
[h,s,v] ← RGBToHSV[r,g,b];
v ← IF v>0.5 THEN MIN[v+i*0.05, 1.0] ELSE MAX[v-i*0.05, 0.0] ;
s ← 0;
[lr,lg,lb] ← HSVToRGB[h,s,v];
ColorMap.SetRGBColor[pix, lr,lg,lb];
ENDLOOP;
ENDLOOP;
FOR pix:
CARDINAL
IN [0..palette.size)
DO
-- go red
OPEN palette[pix];
[h,s,v] ← RGBToHSV[r,g,b];
h ← 1.0 ;
s ← 0.0;
[lr,lg,lb] ← HSVToRGB[h,s,v];
ColorMap.SetRGBColor[pix, lr,lg,lb];
ENDLOOP;
FOR i:
CARDINAL IN [0..20]
DO
-- maximise saturations
FOR pix:
CARDINAL
IN [0..palette.size)
DO
OPEN palette[pix];
[h,s,v] ← RGBToHSV[r,g,b];
s ← i / 20.0 ;
h ← 1.0;
[lr,lg,lb] ← HSVToRGB[h,s,v];
ColorMap.SetRGBColor[pix, lr,lg,lb];
ENDLOOP;
ENDLOOP;
FOR i:
CARDINAL
DECREASING IN [0..40]
DO
-- rotate colors
FOR pix:
CARDINAL
IN [0..palette.size)
DO
OPEN palette[pix];
[h,s,v] ← RGBToHSV[r,g,b];
h ← i / 40.0 ;
s ← 1.0;
[lr,lg,lb] ← HSVToRGB[h,s,v];
ColorMap.SetRGBColor[pix, lr,lg,lb];
ENDLOOP;
ENDLOOP; -- NB hue is now 0
FOR i:
CARDINAL
DECREASING IN [0..20]
DO
-- reduce the value to 0
FOR pix:
CARDINAL
IN [0..palette.size)
DO
OPEN palette[pix];
[h,s,v] ← RGBToHSV[r,g,b];
h ← 0.0;
v ← v * i/20.0;
s ← 1.0 ;
[lr,lg,lb] ← HSVToRGB[h,s,v];
ColorMap.SetRGBColor[pix, lr,lg,lb];
ENDLOOP;
ENDLOOP;
FOR pix:
CARDINAL
IN [0..palette.size)
DO
-- restore the colors
OPEN palette[pix];
[h,s,v] ← RGBToHSV[r,g,b];
s ← 1.0; v ← 0.0;
[lr,lg,lb] ← HSVToRGB[h,s,v];
ColorMap.SetRGBColor[pix, lr,lg,lb];
ENDLOOP;
FOR i:
CARDINAL
IN [0..20]
DO
-- restore values
FOR pix:
CARDINAL
IN [0..palette.size)
DO
OPEN palette[pix];
[h,s,v] ← RGBToHSV[r,g,b];
v ← v * i/20.0;
[lr,lg,lb] ← HSVToRGB[h,s,v];
ColorMap.SetRGBColor[pix, lr,lg,lb];
ENDLOOP;
ENDLOOP;
n ← n - 1;
ENDLOOP;
};
JRotateMap:
PROCEDURE [] =
TRUSTED {
RotateMap[1];
};
Init[];
END.