Enthusiasten, die sich ihre Computer-Grafiken an die Wand hängen wollen, können jetzt mit dem PosterMaker in neue Dimensionen vorstoßen: Jedes Bild kann bis zu 1,62 mal 1,12 Meter ausgedruckt werden.
Nach dem Programmstart u nd der Anzeige einer kleinen Info-Box kann mit einer File-Select-Box ein Bild ausgesucht werden.*
Das Programm ist in der vorliegenden Form auf Monochrom-Bildschirm eingestellt und kann keine Farbbilder konvertieren. Sie können also normale Bilder im Doodle-Format benutzen.
In zwei weiteren Alertboxen (Bild 1) werden Sie dann nach den Vergrößerungsfaktoren gefragt. PosterMaker kann in jede Richtung 2,4 oder 8 mal vergrößern, so daß die größte Stufe eine 64-fache Größe bedeutet. Nach einer kleinen Rückfrage (der Ausdruck dauert schon sehr lange) beginnt die Vergrößerung.
Dazu wird das Bild in Abhängigkeit von der gewünschten Vergrößerung in Blöcke unterteilt, die bis auf Bildschirmgröße gebracht werden. PosterMaker schickt dann den Schirm als Hardcopy an den Drucker. Ihnen bleibt nach Ausdruck aller Blöcke noch das Zusammenkleben der Teile und schon haben Sie Ihr Lieblingsbild riesengroß.
PosterMaker druckt jeweils zwei untereinanderliegende Blöcke auf eine Seite und schickt dann ein FormFeed. Somit sparen Sie sich die Hälfte der Klebestellen in vertikaler Richtung. Der Druckvorgang kann übrigens jederzeit durch Drücken einer beliebigen Taste unterbrochen werden. Vor der Ausgabe der gerade bearbeiteten Seite werden Sie gefragt, ob der Ausdruck wirklich abgebrochen werden soll. Ist ein komplettes Bild bearbeitet können Sie durch Auswahl in einer weiteren Alertbox andere Grafiken ausdrucken.
Als kleine Hilfe beim Zusammenkleben ist in Bild 2 noch die Ausdruckreihenfol-ge für einige Vergrößerungsstufen angegeben. Nach dem gleichen Prinzip müssen Sie auch bei den anderen Vorgehen.
Das Programm in Modula-2 (Listing 1) macht ausgiebig Gebrauch von Rastercopies. Die Einzelheiten zu dieser Funktion wurden in der ST-Ecke in ST-Computer 11/87, Seite 76 erläutert. Hier wird sie auf zweierlei Weise verwendet.
Die Prozedur “SetUpPicScreen” reserviert 32000 Bytes im Speicher. Dieser Bereich kann vom VDI wie ein realer Bildschirm verwendet werden, wenn ein entsprechender Memory-Form-Defini-tion-Block definiert wurde. Das auszudruckende Bild wird nun in diesen “Speicherbildschirm” geladen und jeweils mit einer Rastercopy blockweise auf den realen kopiert, was in der Prozedur “Blow ItUp” geschieht.
Aber auch zum Vergrößern selbst läßt sich die Rasterco-py-Funktion einsetzen und sichert dabei eine schnelle Verarbeitung. Die Vorgehensweise dabei ist einfach. Bei der Vergrößerung in vertikaler Richtung auf das Doppelte geht die untere Bildschirmhälfte sowieso verloren. Wir nehmen also die letzte Bildschirmzeile der ersten Hälfte und kopieren sie einfach in die unterste Bildschirmzeile. Wird ihr Inhalt auch noch in die vorletzte Zeile kopiert, ist eine Pixelreihe vergrößert. Auf diese Art arbeitet sich die Prozedur “BlowUpV” bis zur ersten Bildschirmzeile hoch.
Bei der horizontalen Vergrößerung mit “BlowUpH” werden einfach alle Bildschirm spalten ab der Mitte bis an den linken Rand je zweimal kopiert.Eine kleineErläuterung verdient noch die Funktion “Power Of2”, die mit dem Parameter “a” zwei hoch a liefert. Der Trick dabei ist, daß die Standardroutine “INCL” benutzt wird. Sie setzt das Bit Nummer a in dem Bitvektor b. Wer sich im binären Zahlensystem auskennt, weiß sofort, daß dieser Bitvektor nun dem Wert zwei hoch a entspricht, und genau das liefert die Funktion als CARDINAL ab.
Bleibt nur noch zu hoffen, daß Sie für den PosterMaker genügend Farbbänder auf Vorrat haben und das Sägen Ihres Druckers auch auf längere Zeit ertragen können!
MODULE PosterMaker;
(* Robert Tolksdorf, 9.12.87 *)
(* $ A+ *) (* Code optimieren *)
FROM SYSTEM IMPORT ADR, ADDRESS ;
FROM ASCII IMPORT FF ;
FROM Strings IMPORT String, Length, Concat, InitStringModule ;
FROM GEMDOS IMPORT Open, Read, Close, ConIS, NecIn, PrnOut, Alloc, Free ;
FROM GEMAESbase IMPORT Arrow, MouseOff, MouseOn;
FROM AESApplications IMPORT Appllnitialise, ApplExit;
FROM AESForms IMPORT FormAlert, FileSelectorlnput ;
FROM AESGraphics IMPORT GrafMouse ;
FROM GEMVDIbase IMPORT VDIWorkInType, VDIWorkOutType, BigPxyArrayType ;
FROM VDIControls IMPORT OpenVirtualWorkstation, CloseVirtualWorkstation;
FROM VDIRasters IMPORT MFDBType, CopyRasterOpaque ;
FROM XBIOS IMPORT ScreenPhysicalBase, ScreenDump ;
CONST
InfoAlert = '[0][ The Poster Maker| from ST-Computer|written Dez. 1987 by| Robert Tolksdorf| ][ OK ]';
HorizScale = ' [2] [Horizontal scaling][ 2x | 4x | 8x ]';
VertScale = ' [2] [Vertical scaling] [ 2x | 4x | 8x ]';
ReallyPrint = ' [3] [Really Start printing ?][ OK | Cancel ]';
AbortPrint = ' [2] [Really abort printing ?][ OK | Cancel ]';
Another = ' [2] [Another printout ?] [ Yes | No ]' ;
DEBUG — FALSE; (* TRUE, wenn kein Pr int out *)
VAR PicScreen, RealScreen : MFDBType; (* Screen Informationen *)
PicScreenA, RealScreenA : ADDRESS; (* deren Adressen *)
ApplID, ScreenHandle : INTEGER; (* AES/VDI ID's *)
ScreenSize ; LONGCARD; (* Bildschirmgröße *)
Scaling ; RECORD (* Vergrößerung *)
Horiz, Vert : CARDINAL;
END;
(* Screen-Init, MFDB's setzen, Speicherbildschirm einrichten *)
PROCEDURE SetUpPicScreen;
VAR workin : VDIWorkInType;
workout : VDIWorkOutType;
i : INTEGER;
BEGIN
InitStringModule;
i:=FormAlert(1,InfoAlert);
FOR i: =0 TO 9 DO workin[i]:=0 END;
workin[10]:=2;
OpenVirtualWorkstation(workin,ScreenHandle,workout);
WITH RealScreen DO
pointer:=ScreenPhysicalBase();
width:=639;
height:=399;
widthW:=40;
format:=1;
planes:=1;
END;
RealScreenA:=ADR(RealScreen);
PicScreen:=RealScreen;
Alloc(ScreenSize,PicScreen.pointer);
PicScreenA:=ADR(PicScreen);
END SetUpPicScreen;
(* File auswählen und eventuell in Speicherbildschirm laden *)
PROCEDURE LoadPic(): BOOLEAN ;
VAR inpath, insel, filename : String ;
dummy : BOOLEAN ;
exbutton, handle : INTEGER;
status : (StillSelecting, Aborted, ReadIn);
BEGIN
GrafMouse(Arrow, NIL);
status:=StillSelecting;
REPEAT
inpath:= '\*.*';
insel[0]:=0C;
FileSelectorInput(ADR(inpath),ADR(insei),exbutton);
IF (exbutton#0) AND (insel[0]#0C) THEN
WHILE inpath[Length(inpath)-1]#'\' DO
inpath[Length(inpath)-1]:=0C
END;
Concat(inpath,insel,filename);
Open(filename,0,handle);
IF handle>0 THEN
Read(handle,ScreenSize,PicScreen.pointer);
dummy:=Close(handle);
status:=ReadIn;
END;
ELSE
status:=Aborted;
END;
UNTIL (status#StillSelecting);
RETURN (status=ReadIn);
END LoadPic;
(* Bild anzeigen u.mit Alerts VergröPerung auswählen *)
PROCEDURE SelectScaling() :BOOLEAN;
VAR pxy : BigPxyArrayType;
BEGIN
pxy[0]:=0;
pxy[2]:=PicScreen.width;
pxy[4]:=0;
pxy[6]:=RealScreen.width;
pxy[1]:=0;
pxy[3]:=PicScreen.height;
pxy[5]:=0;
pxy[7]:=RealScreen.height;
GrafMouse(MouseOff,NIL);
(* Auf den realen Bildschirm kopieren *)
CopyRasterOpaque(ScreenHandle,3,pxy,PicScreenA, RealScreenA);
GrafMouse(MouseOn,NIL);
Scaling.Horiz:=CARDINAL(FormAlert(1,HorizScale));
Scaling.Vert :=CARDINAL(FormAlert(1,VertScale));
RETURN (FormAlert(1,ReallyPrint)=1);
END SelectScaling;
(* Blockweise in den realen Bildschirm kopieren, vergrößern und ausdrucken.
Bei Tastendruck eventuell abbrechen *)
PROCEDURE BlowItUp;
VAR i, hblock, vblock, hblocksize, vblocksize : INTEGER;
pxy : BigPxyArrayType ;
ch : CHAR;
(* 2 hoch a ausrechnen *)
PROCEDURE PowerOf 2 (a:CARDINAL) : CARDINAL;
VAR b:BITSET;
BEGIN
b:={}; (* Trick mit BITSET: Das Bit # a *)
INCL(b,a); (* wird gesetzt = 2 hoch a *)
RETURN CARDINAL (b) ; (* und als CARDINAL zurückgegeben *)
END PowerOf2;
BEGIN
hblocksize:=(PicScreen.width+1) DIV PowerOf2(Scaling.Horiz);
vblocksize:=(PicScreen.height+1) DIV PowerOf2(Scaling.Vert);
pxy[4]:=0; (* Destination-x und *)
pxy[5]:=0; (* Destination-y sind immer 0 *)
GrafMouse(MouseOff,NIL);
(* blockweise ... *)
FOR hblock:=1 TO PowerOf2(Scaling.Horiz) DO
FOR vblock : =1 TO PowerOf 2 (Scaling.Vert) DO
(* ... realen Bildschirm löschen ... *)
pxy(0]:=0;
pxy[2]:=RealScreen.width;
pxy[6]:=RealScreen.width;
pxy[1]:=0;
pxy[3]:=RealScreen.height;
pxy[7]:=RealScreen.height;
CopyRasterOpaque(ScreenHandle,0,pxy,RealScreenA,RealScreenA);
(* ... Block aus Speicher kopieren ... *)
pxy[0]:=(hblock-1)*hblocksize;
pxy[2]:=hblock*hblocksize-1;
pxy[6]:=hblocksize-1;
pxy[1]:=(vblock-1)*vblocksize;
pxy[3]:=vblock*vblocksize-1;
pxy[7]:=vblocksize-1;
CopyRasterOpaque(ScreenHandle,3,pxy,PicScreenA, RealScreenA);
(* ... vergrößern ... *)
FOR i:=1 TO Scaling.Horiz DO
BlowUpH;
END;
FOR i:=1 TO Scaling.Vert DO
BlowUpV;
END;
(* ... Taste gedrückt ?? *)
IF ConIS() THEN
NecIn(ch);
GrafMouse(MouseOn,NIL);
IF (FormAlert(2,AbortPrint)=1) THEN
RETURN (* Abbruch *)
ELSE
GrafMouse(MouseOff,NIL);
END
END;
IF ~DEBUG THEN
(* realen Bildschirm an Drucker schicken *)
ScreenDump ;
(* Seite voll -> FormFeed *)
IF ~ODD(vblock) THEN
PrnOut(FF);
END;
END;
END;
END;
GrafMouse(MouseOn,NIL);
END BlowItUp;
(* realen Bildschirm horiz . a . d. Doppelte vergröPern *)
PROCEDURE BlowUpH;
VAR x : INTEGER;
pxy : BigPxyArrayType;
BEGIN
pxy[1]:=0;
pxy[3]:=RealScreen.height;
pxy[5]:=0;
pxy[7]:=RealScreen.height;
FOR x:= ((RealScreen.width+1) DIV 2)-1 TO 0 BY -1 DO
pxy[0]:=x;
pxy[2]:=x;
pxy[4]:=x*2;
pxy[6]:=x*2;
CopyRasterOpaque(ScreenHandle,3,pxy,RealScreenA, RealScreenA);
INC(pxy[4]);
INC(pxy[6]);
CopyRasterOpaque(ScreenHandle,3,pxy,RealScreenA, RealScreenA);
END;
END BlowUpH;
(* realen Bildschirm vertikal a.d.Doppelte vergröPern *)
PROCEDURE BlowUpV;
VAR y : INTEGER;
pxy : BigPxyArrayType;
BEGIN
pxy[0]:=0;
pxy[2]:=RealScreen.width;
pxy[4]:=0;
pxy[6]:=RealScreen.width;
FOR y:=((RealScreen.height+1) DIV 2)-1 TO 0 BY -1 DO
pxy[1]:=y;
pxy[3]:=y;
pxy[5]:=y*2;
pxy[7]:=y*2;
CopyRasterOpaque(ScreenHandle,3,pxy,RealScreenA, RealScreenA);
INC(pxy[5]);
INC(pxy[7]);
CopyRasterOpaque(ScreenHandle,3,pxy,RealScreenA, RealScreenA);
END;
END BlowUpV;
(* Speicher freigeben und Screen schliePen *)
PROCEDURE CloseDown;
VAR dummy: BOOLEAN ;
BEGIN
dummy:=Free(PicScreen.pointer);
CloseVirtualWorkstation(ScreenHandle);
END CloseDown;
BEGIN
ApplID:=ApplInitialise();
ScreenSize:=32000;
SetupPicScreen;
REPEAT
IF (LoadPic()) AND (SelectScaling()) THEN
BlowItUp;
END;
UNTIL (FormAlert(1,Another)=2);
CloseDown;
ApplExit;
END PosterMaker.
Listing vom PosterMaker