DIRECTORY
ColorEditOps,
FS USING [StreamOpen],
IO USING [Close, GetChar, EndOf, PutChar, RIS, ROS, RopeFromROS, STREAM],
SampleMapOps USING [Clear, DoWithScratch, Fill, GetSample],
SelectRegions USING [ApplyTRC, nullRectangle, TRCSequence, TRCSequenceRep];
OPEN ColorEditOps;
LogApply:
PUBLIC
PROC [trc:
REF
TRC, sm: SampleMap, extent: Rectangle]
RETURNS [rope:
ROPE] ~ {
Converts the parameters for an Apply into a rope
stream: IO.STREAM ~ IO.ROS[];
FOR i:
NAT
IN [0..256)
DO
IO.PutChar[self: stream, char: VAL[trc[i]]];
ENDLOOP;
SaveExtentOfMaskToStream[stream: stream, mask: sm, extent: extent];
rope ← IO.RopeFromROS[self: stream];
};
ApplyLog:
PUBLIC
PROC [changeLog:
ROPE, sa: SampleArray] ~ {
Apply the logged information currently in data.changeLog
ApplyLogAction:
PROC [sm: SampleMap] ~ {
stream: IO.STREAM ~ IO.RIS[rope: changeLog];
trcs: SelectRegions.TRCSequence ~ NEW[SelectRegions.TRCSequenceRep[sa.n]];
trc: REF TRC ~ NEW[TRC];
extent: Rectangle;
FOR i:
NAT
IN [0..trcs.n)
DO
trcs[i] ← trc;
ENDLOOP;
UNTIL
IO.EndOf[self: stream]
DO
FOR i:
NAT
IN [0..256)
DO
trc[i] ← LOOPHOLE[IO.GetChar[self: stream]];
ENDLOOP;
extent ← ReadExtentOfMaskFromStream[stream: stream, mask: sm];
SelectRegions.ApplyTRC[sm, sa, trcs, extent];
ENDLOOP;
};
SampleMapOps.DoWithScratch[sSize: sa.sSize, fSize: sa.fSize, bitsPerSample: 1, action: ApplyLogAction];
};
extentFilePassword: CARDINAL ~ 30346;
SaveExtentOfMask:
PUBLIC
PROC [mask: SampleMap, extent: Rectangle, fileName:
ROPE] ~ {
file: IO.STREAM ~ FS.StreamOpen[fileName: fileName, accessOptions: create];
SaveExtentOfMaskToStream[file, mask, extent];
IO.Close[self: file];
};
ReadExtentOfMask:
PUBLIC
PROC [mask: SampleMap, fileName:
ROPE]
RETURNS [extent: Rectangle] ~ {
file: IO.STREAM ~ FS.StreamOpen[fileName: fileName];
extent ← ReadExtentOfMaskFromStream[file, mask];
};
SaveExtentOfMaskToStream:
PUBLIC
PROC [stream:
IO.
STREAM, mask: SampleMap, extent: Rectangle] ~ {
PutCardinal:
PROC [cardinal:
CARDINAL] ~ {
IO.PutChar[self: stream, char: VAL[cardinal/256]];
IO.PutChar[self: stream, char: VAL[cardinal MOD 256]];
};
bitsPerSample: [1..1] ~ mask.bitsPerSample;
currentValue: CARDINAL ← 0;
currentCount: CARDINAL ← 0;
PutCardinal[extentFilePassword];
PutCardinal[mask.sSize];
PutCardinal[mask.fSize];
PutCardinal[extent.sMin];
PutCardinal[extent.sMax];
PutCardinal[extent.fMin];
PutCardinal[extent.fMax];
IF extent#SelectRegions.nullRectangle
THEN {
FOR s:
CARDINAL
IN [extent.sMin .. extent.sMax]
DO
FOR f:
CARDINAL
IN [extent.fMin .. extent.fMax]
DO
sample: CARDINAL ~ SampleMapOps.GetSample[sampleMap: mask, index: [s: s, f: f]];
SELECT
TRUE
FROM
sample#currentValue => {
PutCardinal[currentCount];
currentCount ← 1;
currentValue ← 1 - currentValue;
};
currentCount =
CARDINAL.
LAST-1 => {
PutCardinal[CARDINAL.LAST];
currentCount ← 0;
currentValue ← 1 - currentValue;
};
ENDCASE => currentCount ← currentCount+1;
ENDLOOP;
ENDLOOP;
};
IF currentCount#0 THEN PutCardinal[currentCount];
PutCardinal[extentFilePassword]; --Pad with the password
};
ReadExtentOfMaskFromStream:
PUBLIC
PROC [stream:
IO.
STREAM, mask: SampleMap]
RETURNS [extent: Rectangle] ~ {
GetCardinal:
PROC
RETURNS [
CARDINAL] ~ {
hi: CARDINAL ~ LOOPHOLE[IO.GetChar[self: stream]];
lo: CARDINAL ~ LOOPHOLE[IO.GetChar[self: stream]];
RETURN [hi*256 + lo];
};
bitsPerSample: [1..1] ~ mask.bitsPerSample;
currentValue: CARDINAL ← 0;
currentCount: CARDINAL ← 0;
IF GetCardinal[] # extentFilePassword THEN ERROR;
IF GetCardinal[] # mask.sSize THEN ERROR;
IF GetCardinal[] # mask.fSize THEN ERROR;
extent.sMin ← GetCardinal[];
extent.sMax ← GetCardinal[];
extent.fMin ← GetCardinal[];
extent.fMax ← GetCardinal[];
SampleMapOps.Clear[mask];
IF extent=SelectRegions.nullRectangle THEN RETURN;
currentCount ← GetCardinal[];
FOR s:
CARDINAL
IN [extent.sMin .. extent.sMax]
DO
f: CARDINAL ← extent.fMin;
WHILE f ~> extent.fMax
DO
count: CARDINAL ← MIN[currentCount, extent.fMax+1-f];
IF currentValue=1 THEN SampleMapOps.Fill[dest: [sampleMap: mask, start: [s: s, f: f], size: [s: 1, f: count]], value: 1];
f ← f+count;
currentCount ← currentCount - count;
IF currentCount=0
THEN {
currentValue ← 1-currentValue;
currentCount ← GetCardinal[];
};
ENDLOOP;
ENDLOOP;
IF currentCount # extentFilePassword THEN ERROR;
};