-- AISChangeHeaderImpl.mesa
Copyright Ó 1991, 1992 by Xerox Corporation. All rights reserved.
Bloomenthal, February 2, 1991 7:53 pm PST
DIRECTORY AISFileFormat, AISIO, Args, Basics, Commander, FS, IO, Rope;
AISChangeHeaderImpl: CEDAR PROGRAM
IMPORTS AISIO, Args, Basics, Commander, FS, IO
~ BEGIN
See AISIOImpl
wordsHeader: INT ¬ AISFileFormat.wordsPerAISPage;
Card: PROC [h: CARD16] RETURNS [b: Basics.HWORD] ~ {b ¬ Basics.HFromCard16[h]};
WriteBytes: UNSAFE PROC [out: IO.STREAM, base: LONG POINTER, bytes: INT] ~ UNCHECKED {
IO.UnsafePutBlock[out, [base: LOOPHOLE[base], count: bytes]];
};
WriteInfo: PROC [out: IO.STREAM, info: AISIO.Info] ~ {
WritePartHeader: PROC [type: AISFileFormat.PartType, nBytesInPart: INT] ~ {
nWordsTotal: INT ¬ (nBytesInPart+AISFileFormat.byteSizePartHeader)/2;
part: MACHINE DEPENDENT RECORD [
c: PartHeader, p: PACKED ARRAY [0..(BITS[WORD]-(BITS[PartHeader] MOD BITS[WORD])) MOD BITS[WORD]) OF [0..1]];
part.c ¬ [type, nWordsTotal/256, nWordsTotal MOD 256];
IF type = nil THEN part.c.lengthHi ¬ part.c.lengthLo ¬ 0;
TRUSTED {WriteBytes[out, @part, AISFileFormat.byteSizePartHeader]};
};
PartHeader: TYPE ~ AISFileFormat.PartHeader;
UCACoding: TYPE ~ AISFileFormat.UCACoding;
AttributeHeader: TYPE ~ AISFileFormat.AttributeHeader;
RasterPart: TYPE ~ AISFileFormat.RasterPart;
header: MACHINE DEPENDENT RECORD [
c: AttributeHeader, p: PACKED ARRAY [0..(BITS[WORD]-(BITS[AttributeHeader] MOD BITS[WORD])) MOD BITS[WORD]) OF [0..1]];
raster: MACHINE DEPENDENT RECORD [
c: RasterPart, p: PACKED ARRAY [0..(BITS[WORD]-(BITS[RasterPart] MOD BITS[WORD])) MOD BITS[WORD]) OF [0..1]];
uca: MACHINE DEPENDENT RECORD [
c: UCACoding, p: PACKED ARRAY [0..(BITS[WORD]-(BITS[UCACoding] MOD BITS[WORD])) MOD BITS[WORD]) OF [0..1]];
header.c ¬ [AISFileFormat.passwordValue, Card[wordsHeader]];
raster.c ¬ [info.raster.scanCount, info.raster.scanLength, Card[3], Card[1], 0, uca, AISFileFormat.nil];
uca.c ¬ [info.uca.bitsPerSample, info.uca.wordsPerScanLine, AISFileFormat.nil, AISFileFormat.nil];
TRUSTED {WriteBytes[out, @header, AISFileFormat.byteSizeAttributeHeader]};
WritePartHeader[raster, AISFileFormat.byteSizeRasterPart+AISFileFormat.byteSizeUCACoding];
TRUSTED {WriteBytes[out, @raster, AISFileFormat.byteSizeRasterPart]};
TRUSTED {WriteBytes[out, @uca, AISFileFormat.byteSizeUCACoding]};
IF info.placement # NIL THEN {
part: MACHINE DEPENDENT RECORD [
c: AISFileFormat.PlacementPart, p: PACKED ARRAY [0..(BITS[WORD]-(BITS[UCACoding] MOD BITS[WORD])) MOD BITS[WORD]) OF [0..1]];
part.c ¬ info.placement­;
WritePartHeader[placement, AISFileFormat.byteSizePlacementPart];
TRUSTED {WriteBytes[out, @part, AISFileFormat.byteSizePlacementPart]};
};
IF info.photometry # NIL THEN {
part: MACHINE DEPENDENT RECORD [
c: AISFileFormat.PhotometryPart, p: PACKED ARRAY [0..(BITS[WORD]-(BITS[UCACoding] MOD BITS[WORD])) MOD BITS[WORD]) OF [0..1]];
part.c ¬ info.photometry­;
WritePartHeader[photometry, AISFileFormat.byteSizePhotometryPart];
TRUSTED {WriteBytes[out, @part, AISFileFormat.byteSizePhotometryPart]};
};
IF info.comments # NIL THEN { -- ugh -- };
WritePartHeader[nil, 0]; -- end header
};
AISChangeHeaderCmd: Commander.CommandProc = {
inA, outA, xA, yA, bppA, numberScanlinesA, pixelsPerLineA, commentA: Args.Arg;
[inA, outA, xA, yA, bppA, numberScanlinesA, pixelsPerLineA, commentA] ¬
Args.ArgsGet[cmd, "%ss-placement%ii-bitsPerPixel%i-numberScanlines%i-pixelsPerLine%i-comment%s-wordsPerLine%i"
! Args.Error => {msg ¬ reason; CONTINUE}];
IF msg # NIL
THEN RETURN[$Failure, msg]
ELSE {
info: AISIO.Info ¬ AISIO.ReadInfo[inA.rope];
buffer: REF TEXT ¬ NEW[TEXT[1024]];
in: IO.STREAM ¬ FS.StreamOpen[inA.rope ! FS.Error => GOTO Bad];
out: IO.STREAM ¬ FS.StreamOpen[outA.rope, $create];
IF xA.ok OR yA.ok THEN {
IF info.placement = NIL THEN info.placement ¬ NEW[AISFileFormat.PlacementPart];
IF xA.ok THEN info.placement.xLeft ¬ Basics.HFromInt16[xA.int];
IF yA.ok THEN info.placement.yBottom ¬ Basics.HFromInt16[yA.int];
};
IF bppA.ok THEN info.uca.bitsPerSample ¬ Basics.HFromInt16[bppA.int];
IF numberScanlinesA.ok
THEN info.raster.scanCount ¬ Basics.HFromInt16[numberScanlinesA.int];
IF pixelsPerLineA.ok THEN {
info.raster.scanLength ¬ Basics.HFromInt16[pixelsPerLineA.int];
info.uca.wordsPerScanLine ¬ Basics.HFromInt16[pixelsPerLineA.int/2+(pixelsPerLineA.int MOD 2)];
};
IF commentA.ok THEN info.comments ¬ CONS[commentA.rope, info.comments];
WriteInfo[out, info];
IO.SetIndex[in, wordsHeader];
IO.SetIndex[out, wordsHeader];
DO
nBytes: INT ¬ IO.GetBlock[in, buffer];
IF nBytes = 0 THEN EXIT;
IO.PutBlock[out, buffer];
ENDLOOP;
IO.Close[in];
IO.Close[out];
EXITS Bad => RETURN[$Failure, "can't open file"];
};
};
usage: Rope.ROPE ¬
"\nAISChangeHeader <ais-in> <ais-out> [-option]
options include:
 -placement <x, y: INTEGER>
 -bitsPerPixel <INTEGER>
 -numberScanlines <INTEGER>
 -pixelsPerLine <INTEGER>
 -comment <ROPE>";
Commander.Register["AISChangeHeader", AISChangeHeaderCmd, usage];
END.