PosterMaker druckt riesig

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.

Bild 1: Alertboxen um die Vergrößerungsfaktoren zu bestimmen

Cut & Paste

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!

Bild 2: So müssen die Ausdrucke zusammengeklebt werden

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


Robert Tolksdorf
Aus: ST-Computer 08 / 1988, Seite 88

Links

Copyright-Bestimmungen: siehe Über diese Seite