<> <> <> <> <<>> DIRECTORY AIS, Basics, Commander, CountedVM, Convert, FS, IO, PressReader, Rope, PressPrinter; PressImageExtractImpl: CEDAR PROGRAM IMPORTS AIS, Commander, CountedVM, Convert, FS, IO, PressReader, Rope, PressPrinter ~ BEGIN ROPE: TYPE ~ Rope.ROPE; bytesPerPage: NAT ~ 512; -- as per press file format. ExtractImages: PROC [inputName, outputNameRoot: ROPE, msg: IO.STREAM] ~ { pressFile: PressReader.Handle _ PressReader.OpenPressFile[inputName]; aisNum: INT _ 0; DoPage: PROC [pageNumber: INT] RETURNS [ok: BOOLEAN _ TRUE] = { PageProc: PressReader.PageProc = { EntityProc: PressReader.EntityProc = { -- Xe, Ye, fontSet xe: INT _ entityTrailer.Xe; ye: INT _ entityTrailer.Ye; x: INT _ xe; y: INT _ ye; lastShowX, lastShowY: INT _ -1; hue: REAL _ 0.0; saturation: REAL _ 1.0; brightness: REAL _ 0.0; skipAlternative, inAlternative: BOOL _ FALSE; reposition: BOOLEAN _ FALSE; showCharactersProc: PressReader.ShowCharactersProc = { NULL; }; -- showCharactersProc fontProc: PressReader.FontProc = { NULL; }; positionProc: PressReader.PositionProc = { IF skipAlternative THEN RETURN; IF opCode = setX THEN x _ xe + value ELSE y _ ye + value; reposition _ TRUE; }; spacingProc: PressReader.SpacingProc = { NULL; }; spaceProc: PressReader.SpaceProc = { NULL; }; colorProc: PressReader.ColorProc = { IF skipAlternative THEN RETURN; SELECT opCode FROM setHue => NULL; setSaturation => NULL; setBrightness => NULL; ENDCASE => ERROR; }; showRectangleProc: PressReader.ShowRectangleProc = { NULL; }; alternativeProc: PressReader.AlternativeProc = { IF (types = 0) AND (elBytes = 0) AND (dlBytes = 0) THEN inAlternative _ skipAlternative _ FALSE ELSE IF inAlternative THEN skipAlternative _ TRUE ELSE inAlternative _ TRUE; }; showObjectProc: PressReader.ShowObjectProc = { NULL; }; -- showObjectProc outputName: ROPE; showDotsOpCode: ROPE; thecode, thedots, thelines: INT _ INT.FIRST; SetCoding: PressReader.SetCodingProc ~ { thecode _ code; thedots _ dots; thelines _ lines; }; themode: NAT _ NAT.LAST; SetMode: PressReader.SetModeProc ~ { themode _ mode; }; passdots, displaydots, passlines, displaylines: INT _ INT.FIRST; SetWindow: PressReader.SetWindowProc ~ { passdots _ pd; displaydots _ dd; passlines _ pl; displaylines _ dl; }; thewidth, theheight: INT _ INT.FIRST; SetSize: PressReader.SetSizeProc ~ { thewidth _ width; theheight _ height; }; DotsFollow: PressReader.DotsFollowProc ~ { scanMode: AIS.ScanMode _ SELECT themode FROM 2 => ru, 3 => rd, 6 => lu, 7 => ld, 9 => ul, 8 => ur, 13 => dl, 12 => dr, ENDCASE => rd; raster: AIS.Raster _ NEW[AIS.RasterPart _ [ scanCount: thelines, scanLength: thedots, scanMode: scanMode, bitsPerPixel: thecode, linesPerBlock: -1, paddingPerBlock: 65535 ]]; ais: AIS.FRef _ AIS.CreateFile[name: outputName, raster: raster]; window: AIS.WRef _ AIS.OpenWindow[ais]; words: INT _ (thedots*MAX[thecode, 1]+Basics.bitsPerWord-1)/Basics.bitsPerWord; vm: CountedVM.Handle _ CountedVM.Allocate[words]; buffer: AIS.Buffer _ [length: words, addr: vm.pointer]; msg.PutF[" _ Page %g ", IO.int[pageNumber]]; msg.PutF[" %g[x: %g, y: %g, w: %g, h: %g]", IO.rope[showDotsOpCode], IO.int[x], IO.int[y], IO.int[thewidth], IO.int[theheight]]; IF brightness # 0.0 THEN msg.PutF[", hue: %g, sat: %g, brt: %g", IO.real[hue], IO.real[saturation], IO.real[brightness]]; FOR lineno: INT IN [0..thelines) DO TRUSTED { [] _ dots.file.UnsafeGetBlock[[base: LOOPHOLE[buffer.addr], startIndex: 0, count: words*2]]; window.UnsafeWriteLine[buffer, lineno]; }; ENDLOOP; AIS.CloseFile[ais]; }; showDotsProc: PressReader.ShowDotsProc = { IF NOT skipAlternative THEN { showDotsOpCode _ IF opCode = showDots THEN "showDots" ELSE "showDotsOpaque"; aisNum _ aisNum + 1; outputName _ Rope.Cat[outputNameRoot, "-", Convert.RopeFromInt[aisNum], ".ais"]; msg.PutRope[FS.ExpandName[outputName].fullFName]; pressFile.GetDots[ setCoding: SetCoding, setMode: SetMode, setWindow: SetWindow, setSize: SetSize, dotsFollow: DotsFollow ]; msg.PutChar['\n]; }; }; -- showDotsProc pressFile.GetCommands[ showCharactersProc: showCharactersProc, fontProc: fontProc, positionProc: positionProc, spacingProc: spacingProc, spaceProc: spaceProc, colorProc: colorProc, showRectangleProc: showRectangleProc, alternativeProc: alternativeProc, showObjectProc: showObjectProc, showDotsProc: showDotsProc ]; }; -- EntityProc pressFile.GetPage[EntityProc]; }; -- PageProc SkipFonts: PressReader.FontDirectoryProc = { ok _ FALSE; }; pressFile.GetParts[pageNumber, PageProc, SkipFonts]; }; -- DoPage pageNumber: INT _ 1; WHILE DoPage[pageNumber] DO pageNumber _ pageNumber + 1; ENDLOOP; pressFile.ClosePressFile[]; }; -- ExtractImages Break: PROC [char: CHAR] RETURNS [IO.CharClass] = { IF char = '_ THEN RETURN [break]; IF char = ' OR char = ' OR char = ', OR char = '; OR char = '\n THEN RETURN [sepr]; RETURN [other]; }; FindFullName: PROC [inputName: ROPE] RETURNS [ROPE] ~ { fullFName: ROPE _ NIL; fullFName _ FS.FileInfo[inputName ! FS.Error => CONTINUE].fullFName; IF fullFName = NIL OR NOT PressPrinter.IsAPressFile[fullFName] THEN { IF inputName.Find[".press", 0, FALSE] = -1 THEN { inputName _ inputName.Concat[".press"]; }; fullFName _ FS.FileInfo[inputName].fullFName; }; RETURN [fullFName] }; FileNameRoot: PROC [inputName: ROPE] RETURNS [ROPE] ~ { fullFName: ROPE _ NIL; cp: FS.ComponentPositions; [fullFName, cp] _ FS.ExpandName[inputName]; RETURN [fullFName.Substr[cp.base.start, cp.base.length]]; }; PressImageExtractCommand: Commander.CommandProc ~ { stream: IO.STREAM _ IO.RIS[cmd.commandLine]; GetToken: PROC RETURNS [rope: ROPE] = { rope _ NIL; rope _ stream.GetTokenRope[Break ! IO.EndOfStream => CONTINUE].token; }; inputName: ROPE _ GetToken[]; inputName _ FindFullName[inputName ! FS.Error => { IF error.group = user THEN {cmd.out.PutRope[error.explanation]; cmd.out.PutChar['\n]; GOTO Quit} ELSE REJECT }]; ExtractImages[inputName, FileNameRoot[inputName], cmd.out]; cmd.out.PutRope["Done.\n"]; IF GetToken[].Length # 0 THEN {cmd.out.PutRope["(Ignored: "]; cmd.out.PutRope[cmd.commandLine.Substr[stream.GetIndex]]; cmd.out.PutRope[")\n"]}; EXITS Quit => NULL }; Commander.Register["PressImageExtract", PressImageExtractCommand, "Recover the sampled image portions of a press file"]; END.