Formatul grafic POSTSCRIPT

Cristian Nagy

PostScript este, de fapt, un limbaj de programare pentru descrierea paginii similar - în multe privinte - limbajului de programare Forth. Elaborat de firma Adobe Systems, limbajul PostScript a fost proiectat pentru imprimante si alte echipamente de iesire; în prezent, acest limbaj este folosit destul de mult si pentru stocarea si schimbul de imagini - în special în format EPS (encapsulated PostScript).

Există un mare număr de aplicatii care oferă suport pentru acest limbaj: majoritatea aplicatiilor pentru Macintosh, multe procesoare de texte si programe DTP pentru PC, unele aplicatii puternice pentru grafică sau CAD pentru PC, aplicatii UNIX. Limbajul are calităti foarte bune pentru asigurarea uniformitătii pe diferite platforme si medii - atât pentru imagini monocrome, cât si pentru imagini color.

Principalele avantaje ale formatului PostScript constau în faptul că dispune de posibilităti grafice mari cum ar fi: standardizarea si corectia monocromă, color si RGB pe 36 biti; memorarea imaginilor vectorial sau bitmap; lucrul cu vectori; fonturi; transformări liniare ale imaginilor. Datorită acestor caracteristici, PostScript a devenit un fel de standard în activitatea de tehnoredactare computerizată a publicatiilor.

Printre dezavantajele sale se numără dificultatea implementării unui cititor de uz general pentru fisiere PostScript (datorată complexitătii limbajului) si dimensiunea relativ mare a unui fisier PostScript care contine imagini bitmap (deoarece înregistrarea se face, în mod uzual, în format ASCII).

PostScript are patru variante: Level 1, Level 2, Encapsulated si Display PostScript. Level 1 este limbajul initial, folosit mai ales pentru imagini si desene monocrome, dar având posibilitatea de a reproduce culori RGB sau CMYK. Level 2 aduce o sumă de îmbunătătiri printre care utilizarea codului binar în loc de ASCII, diverse filtre pentru compresie, utilizarea colorimetriei si a mai multor spatii de culoare. Fisierele PostScript încapsulate (EPS = Encapsulated PostScript) reprezintă descrierea PostScript pentru o pagină ce poate fi inclusă, fără modificări, într-un document PostScript mai mare. Interpretoarele Display PostScript functionează ca interfete în timp real, independente de dispozitiv, pentru monitoarele calculatoarelor. Aceste interpretoare asigură suport pentru executarea multitasking a programelor PostScript, codificarea binară a numelor, utilizarea sistemelor de ferestre si a fonturilor bitmap.

Structura fisierului

PostScript este un limbaj de programare, deci nu are nevoie de o anumită structură a fisierului - cu exceptia respectării sintaxei si a semanticii. Totusi, pentru transmiterea eficientă a informatiilor, este necesară o anumită succesiune logică. Adobe a formalizat o astfel de succesiune într-o specificatie numită DSC (Document Structuring Conventions = conventii pentru structurarea documentelor). Structurarea impusă de DSC asigură tratarea corectă a fisierelor PostScript de către diferite tipuri de resurse pentru gestiunea documentelor. Pentru a obtine un control mai bun al acestor resurse, Adobe a creat, ca parte a DSC-ului, un fel de al doilea limbaj numit comentarii DSC. Termenii acestui limbaj apar în fisierul PostScript sub formă de comentarii care sunt ignorate de către procesor, dar sunt citite de către resursa care gestionează documentele.

Structura generală a unui fisier PostScript, sub versiunea 3.0 a DSC, este următoarea:

Prolog 
Antet 
Valori implicite (optional) 
Proceduri 
Script 
Parametrii documentului 
Pagină (pagini) de cod PostScript 
. 
. 
Încheierea documentului 

Această structură se implementează utilizând comentarii DSC (care încep cu %%, contin cel mult 255 caractere si se termină la primul caracter CR sau la prima pereche CR/LF).

Prologul

Sectiunea antet a prologului - Nu contine cod PostScript, ci numai comentarii. În anumite situatii, informatii de antet cum ar fi „bounding box" pot fi amânate pentru încheiere; acest fapt este indicat de utilizarea cuvântului cheie atend ca argument.

Fisierul începe cu un identificator PostScript (singurul comentariu care începe cu %!):

%!PS-Adobe-3.0 cuvânt-cheie 

Cuvântul cheie desemnează variatii: EPSF-3.0 se foloseste pentru PostScript încapsulat.

%%BoundingBox: Xstângajos Ystângajos Xdreaptasus Ydreaptasus Desemnează o regiune dreptunghiulară din spatiul utilizator (definit mai târziu) în care codul PostScript ce urmează îsi va pune marcajele.

%%EndComments Încheie sectiunea antet a prologului; linia este optională.

Sectiunea de proceduri a prologului - Contine procedurile definite de utilizator. Această sectiune este delimitată de următoarele comentarii DSC:

%%BeginProlog începe sectiunea de definire a procedurilor; optională.

%%EndProlog încheie sectiunea de definire a procedurilor si întregul prolog. După acest comentariu începe corpul principal al programului PostScript.

Codul PostScript

Aceasta este corpul principal de cod. Codul poate să contină si el comentarii DSC.

Încheierea

Această sectiune, dacă există, contine un amestec de comentarii DSC si cod PostScript având misiunea de a efectua diferite operatiuni de „curătire". De asemenea, ea poate să contină informatii importante ale antetului DSC care au fost amânate către încheiere prin cuvântul cheie atend. Începutul încheierii este indicat de comentariul DSC %%Trailer.

Executia PostScript

Obiecte - Pe măsură ce un fisier este parcurs de către interpretorul PostScript, codul ASCII este mai întâi separat în obiecte care pot să fie executabile sau neexecutabile. Obiectele executabile sunt comenzi PostScript; cele neexecutabile (numite literali) constituie datele. Obiectele executabile pot fi operatori PostScript sau nume de proceduri create de utilizator. Comentariile încep cu caracterul %.

Executie bazată pe stivă - Interpretorul PostScript execută programele folosind stive. În functie de natura lor, obiectele sunt fie depuse în stivă, fie executate imediat. Există patru stive: pentru operanzi, pentru dictionar, pentru executie si pentru stările părtii grafice.

Atunci când se întâlneste un obiect neexecutabil, cum ar fi numere, siruri de caractere sau matrici (indicate de paranteze drepte [ ]), obiectul este depus pe stiva de operanzi.

Atunci când se întâlneste un operand sau un alt obiect executabil, el este executat si executia lui începe cu extragerea datelor de intrare (dacă există) de pe stivă. De aceea, datele pentru un obiect executabil apar înaintea obiectului însusi. Asemănător, un obiect executabil va depune rezultatele sale pe stivă. În acest mod, obiectele executabile pot să apară sub formă de secvente, transmiterea datelor de la unul la altul făcându-se prin intermediul stivei.

De exemplu, operatorul PostScript pentru umplerea unui dreptunghi al cărui colt din stânga jos are coordonatele x, y si ale cărui dimensiuni sunt înăltime si lătime se va scrie astfel:

x y lătime înăltime rectfill 

Operanzii x, y, lătime si înăltime vor fi depusi pe stiva de operanzi. Apoi se va executa comanda rectfill care va extrage operanzii de pe stivă.

Nume - Atunci când interpretorul întâlneste o serie de simboluri obisnuite - cum ar fi litere si numere (delimitate de caractere spatiu sau de punctuatie) - si acea serie nu poate fi interpretată ca un număr, ea este considerată un obiect nume. Numele sunt identificatori unici folositi pentru operatori, siruri de caractere, variabile sau proceduri.

Dacă numele reprezintă un operator sau o procedură definită de utilizator, operatorul este executat imediat ce a fost identificat. Dacă numele reprezintă date, aceste date sunt depuse pe stiva de operanzi. Totusi, dacă numele începe cu un caracter slash (/), numele este tratat ca o dată (un literal) si este depus pe stiva de operanzi. Prefixul / se foloseste pentru a transmite nume ca argumente operatorilor si procedurilor. Obiectele denumite de utilizator sunt create cu operatorul def:

cheie valoare def 

unde cheie este un nume prefixat cu /, iar valoare este un număr, un sir de caractere, o procedură, sau un alt obiect.

Obiecte executabile (operatori) - Comenzile PostScript sunt fie operatori inclusi - cum ar fi rectfill, fie proceduri definite de utilizator - cum ar fi subrutinele. Operatorii sunt cuvinte scrise în ASCII pe care PostScript-ul îi „stie" deoarece numele lor sunt introduse în partea de dictionar de sistem a stivei de dictionar. Similar, numele procedurilor definite de utilizator sunt introduse în zona utilizator a stivei de dictionar.

Procedurile definite de utilizator se pot crea închizând operatorii doriti si datele între acolade { }, precedându-i cu /nume - unde nume este numele pe care îl dăm procedurii, si încheind cu operatorul def. Initial, interpretorul tratează operatorii drept date, într-un proces numit executie amânată. Simbolul / indică faptul că urmează un obiect literal (dată), astfel încât numele este depus pe stiva de operanzi. Astfel, închiderea operatorilor între acolade, { }, determină tratarea lor ca matrice de date atunci când sunt cititi prima oară; adică ei sunt depusi pe stiva de operanzi. Apoi operatorul def extrage toate acele obiecte de pe stiva de operanzi si crează o intrare în dictionarul utilizatorului.

De exemplu linia

/square {50 50 rectfill} def 

crează, în stiva de dictionar, o procedură numită „square" care generează un dreptunghi cu dimensiunile 50x50, umplut.

Tipuri de date

Numerele întregi si reale au formă conventională cu semn. Numerele reale pot să aibă oricâte zecimale (ca 2.0 sau 1.5999) sau pot să folosească notatia exponentială (ca 235.667e10 sau 1.56E-15).

Sirurile de caractere se înregistrează mai ales ca text închis între paranteze ( ). Caracterele netipăribile, cum ar fi line-feed sau carriage return, se pot include fie în formă ASCII, fie - mai uzual - într-o formă specială de codificare. Această ultimă formă foloseste un caracter \ urmat de următoarele caractere: b = backspace, f = formfeed, n = line-feed (LF), r = carriage return (CR), t = tab, nnn = cod octal al unui caracter.

Sirurile de caractere se mai pot folosi si ca bufferi în stiva de operanzi. Ele se pot aloca utilizând operatorul string:

lungimesir string 

unde lungimesir este un întreg. Acest operator depune pe stivă de operanzi un număr de lungimesir de octeti cu valoarea zero.

Mai multe numere sau siruri de caractere pot alcătui un singur obiect compus, numit matrice, prin închiderea lor între paranteze drepte [ ].

Starea grafică

Atunci când interpretorul PostScript execută un grafic, el se bazează pe valori „curente". Acestea determină starea grafică curentă. Se pot salva sau reface mai multe stări grafice, folosind stiva de stări grafice, cu ajutorul operatorilor gsave si grestore.

Sisteme de coordonate - În esentă, PostScript plasează „cerneală" opacă pe o pagină virtuală albă, numită pagină curentă. Sistemul de coordonate PostScript, numit spatiu utilizator, se referă la această pagină. Un al doilea sistem de coordonate, numit spatiu dispozitiv, este mapat în spatiul utilizator prin intermediul unei matrici de transformare a coordonatelor (CTM = coordinate transformation matrix).

Cu ajutorul CTM, asupra imaginii de iesire se pot aplica deplasări, rotiri, scalări sau alte transformări liniare. Matricea CTM implicită foloseste axe ortogonale X si Y orientate conventional, scalate cu o unitate egală cu 1/72 toli (1 punct) si plasate astfel încât originea spatiului utilizator coincide cu cea a spatiului dispozitiv. CTM poate fi stabilită direct, folosind algebra matricială si operatorii setmatrix sau concat, dar de obicei modificările se fac cu operatorii translate, rotate sau scale:

Cei trei operatori au si o formă în care acceptă matrici ca intrare si ca iesire.

Grafică vectorială

Iată un exemplu simplu de grafică vectorială în cod PostScript:

3.0 3.5 moveto 
4.0 3.5 lineto 
4.0 4.5 lineto 
3.0 4.5 lineto 
stroke 

Această secventă de cod defineste un pătrat al cărui colt din stânga-jos se află la coordonatele utilizator (3.0, 3.5).

PostScript generează asemenea grafice în doi pasi. Mai întâi se creează o „cale curentă" folosind coordonatele din spatiul utilizator si operatori ca lineto; apoi asupra căii curente actionează operatori de „pictare" (cum ar fi stroke) folosind culoarea curentă. Cei mai importanti operatori pentru cale sunt:

Imagini bitmap în tonuri de gri

Iată un exemplu simplu de cod pentru o imagine bitmap alb-negru de 16x16 pixeli:

/pixbuf 2 string def 
gsave 
198.32 373.32 translate 
15.36 15.36 scale 
16 16 1 % lătime, înăltime, biti/esantion 
[16 0 0 - 16 0 16] % matricea imagine arată ordinea de scanare 
{currentfile pixbuf readhexstring pop} % procedura pentru datele sursă 
image 
fffffefffeffeeeff6dffabffd7f8383 % date hexazecimale ASCII 
fdffabff6dfeeeffefffefffffffffff 
grestore 

Acest segment de cod defineste mai întâi un buffer de date pentru pixeli, cu lungimea de doi octeti, numit „pixbuf", după care protejează starea grafică curentă depunând-o pe stiva grafică cu gsave. Apoi specifică pozitia si scara pentru imagine. În continuare, încep datele pentru operatorul image. Datele bitmap urmează operatorului image si, în final, se restaurează starea grafică.

Operatorul image este generatorul de imagini bitmap. Forma sa de bază, pentru tonuri de gri, este:

lătime înăltime biti/esantion matrice sursădate image 
lătime si înăltime dau numărul de coloane si de rânduri din planul original de pixeli. 
biti/esantion dă adâncimea imaginii (1, 2, 4, 8, sau 12). 
matrice este o matrice specială, cu sase elemente. 

Ea poate fi utilizată pentru transformări liniare, dar se foloseste mai ales pentru specificarea ordinii de scanare a imaginii bitmap. Pentru imagini scanate de la stânga la dreapta si de jos în sus, matricea este [lătime 0 0 - înăltime 0 înăltime].

sursădate este sursa pentru datele binare ale bitmap-ului; în mod conventional, este o procedură care umple cu date un sir de caractere de lungime arbitrară.

Datele bitmap - În exemplul de mai sus, ca în majoritatea cazurilor, datele folosite de operatorul image se găsesc chiar în programul PostScript, ceea ce este arătat de numele currentfile. Dar operatorul image poate să accepte date provenind din alte fisiere decât cel curent.

Ca si în exemplu, sursa de date pentru operatorul image este, de obicei, o procedură; adică o procedură care citeste date de la o adresă, le converteste în binar dacă este cazul si le depune pe stivă pentru operatorul image.

Citirea datelor hexazecimale ASCII - Uzual, datele pentru bitmap sunt codificate folosind caractere ASCII pentru reprezentarea valorilor hexazecimale. În acest caz, nucleul procedurii folosite ca sursă de date pentru imagine este operatorul readhexstring:

fisier sir readhexstring 

în care fisier reprezintă locul unde se află datele, iar sir este un buffer în care se vor citi datele. Operatorul citeste perechi de numere hexazecimale si le converteste în valori binare pe un octet; datele vor fi citite până la umplerea bufferului sir sau până la întâlnirea sfârsitului fisierului. Acest operator depune pe stiva de operanzi două rezultate: sirul de date binare si o valoare logică. Valoarea logică este „adevărat" cu exceptia situatiei în care se ajunge la sfârsitul fisierului.

În exemplul nostru, acest operator este folosit astfel: parametrul fisier pentru readhexstring este currentfile, iar parametrul sir este pixbuf. Deoarece operatorul readhexstring lasă în vârful stivei o valoare logică pe care imaginea nu o foloseste, aceasta este îndepărtată cu operatorul pop. Odată ce s-a executat operatorul image, pointerul în fisierul curent este la începutul datelor pentru bitmap, astfel încât readhexstring începe să citească date din acel punct. Aceasta este abordarea uzuală pentru citirea datelor bitmap.

Imprimarea paginii

Pe măsură ce se execută codul PostScript, imaginii construite în memorie i se adaugă liniile, bitmap-urile si alte elemente. Comanda showpage îi spune interpretorului PostScript că pagina este gata. Acesta va imprima sau va afisa pagina, apoi va sterge imaginea paginii.

Caseta Limbajelor imprimantelor HP:PCL


(C) Copyright Computer Press Agora