Hlavní navigace

PostScript a rastrové obrázky II

26. 7. 2007
Doba čtení: 12 minut

Sdílet

V dnešní části seriálu o grafických formátech a metaformátech dokončíme popis PostScriptu. Budeme se věnovat pokročilejší práci s rastrovými obrázky - ukážeme si jejich zrcadlení, otáčení, změnu velikosti a mimo jiné také ořezání libovolné části rastrového obrázku pomocí nadefinované cesty.

Obsah

1. Zrcadlení rastrových obrázků
2. První demonstrační příklad – zrcadlení obrázku Leny
3. Otočení rastrových obrázků a další lineární transformace
4. Druhý demonstrační příklad – otočení a změna velikosti obrázku Leny
5. Ořezání bitmap pomocí ořezové cesty
6. Třetí demonstrační příklad – použití ořezové cesty
7. Literatura
8. Odkazy na Internetu
9. Obsah dalšího pokračování tohoto seriálu

1. Zrcadlení rastrových obrázků

V předcházející části tohoto seriálu, ve které jsme se taktéž zabývali grafickým metaformátem PostScript, jsme si řekli, jakým způsobem je možné v PostScriptu vytvářet rastrové obrázky, od jednoduchých černobílých bitmap a víceúčelových náhledových obrázků až po plnobarevné fotografie s maximální bitovou hloubkou 12 bitů na pixel, tj. s možností použití až 68 719 476 736 barevných odstínů. Také jsme si ukázali, že při vykreslování rastrových obrázků je nutné vzít v úvahu dva typy lineárních transformací – transformaci podle CTM (Current Transformation Matrix) a dále transformaci specifikovanou přímo při vykreslování obrázku, tj. při volání příkazu image nebo colorimage. V dnešní části si podrobněji ukážeme souvislost mezi oběma transformacemi a způsob jejich vzájemné kombinace.

Začneme druhou nejpraktičtější lineární transformací. Jedná se o transformaci zrcadlení podle vertikální a/nebo horizontální osy (první nejpraktičtější transformace je představována pouhým posunem, ten však byl vysvětlen již v předchozí části). Důvod, proč se jedná o praktickou transformaci, spočívá v tom, že při práci s některými zařízeními (typicky skener) může dojít k zrcadlení obrázku a pomocí zpětné lineární transformace je možné dosáhnout opětného zrcadlení do správné polohy. V některých rastrových obrazových formátech, například TIFF či BMP, také dochází k otočení obrázku, který je uložen „hlavou dolů“. Lineární transformace zadaná v PostScriptovém souboru (nebo v souboru typu EPS) nám pomůže tyto nesrovnalosti opravit a vykreslit obrázek vždy ve správné poloze.

Transformaci zrcadlení je možné specifikovat jak v CTM, tak i v transformační matici obrázku. Pro názornost je vhodnější, když transformační matice obrázku zůstane nezměněna a dojde pouze k ovlivnění CTM. Důvod je jednoduchý – CTM se snáze modifikuje pomocí operátorů translate, rotate a scale, zatímco transformační matice obrázku musí být zadána pomocí šestice čísel, ze kterých nemusí být na první pohled patrné, o jakou transformaci se vlastně jedná. Praxe je taková, že v transformační matici obrázku je zapsána pouze transformace změny měřítka a popř. i verti­kálního zrcadlení – v tomto případě se však jedná o zrcadlení, které kompenzuje způsob nakládání s rastrovými daty v PostScriptu. Všechny další transformace se provádí pomocí modifikace CTM.

2. První demonstrační příklad – zrcadlení obrázku Leny

V dnešním prvním demonstračním příkladu je ukázáno horizontální zrcadlení známého obrázku Leny. Zrcadlení je provedeno pomocí změny CTM. Nejprve je obrázek posunut a je změněno jeho měřítko a posléze se pomocí příkazu -1.0 1.0 scale provede modifikace CTM tak, aby došlo ke kýženému zrcadlení. Korektní by bylo, aby se zrcadlení kompenzovalo dalším posunem (zrcadlí se okolo vertikální osy souřadného systému, ne okolo středové osy obrázku), to je možné provést dalším příkazem translate. Za povšimnutí stojí, že se daná transformace vztahuje pouze na vykreslovaný obrázek, protože jsou všechny příkazy „uzavřeny“ mezi operátory gsave a grestore (uložení a obnovení grafického stavu). Taktéž byly změněny rozměry bounding-boxu, čehož do větší míry využijeme až v následujícím demonstračním příkladu. Celý demonstrační příklad je možné získat pod tímto odkazem.

%!PS-Adobe-2.0 EPSF-2.0
%%Creator: pnmtops and vim
%%Title: lena2.ps
%%Pages: 1
%%BoundingBox: 100 200 500 800
%%EndComments
/readstring {
  currentfile exch readhexstring pop
} bind def
/picstr 80 string def
%%EndProlog
%%Page: 1 1

% ulozeni grafickeho stavu - pro EPS nutne
gsave

% posun obrazku
267.6 357.6 translate

% zmena meritka
76.8 76.8 scale

% zrcadleni rastroveho obrazku
-1.0 1.0 scale

% parametry pro prikaz "image"
80 80 8
[ 80 0 0 -80 0 80 ]
{ picstr readstring }
image
9f9e9b9a9a9da7aca17f5d626968696a6d757b7d81838181838585858484
858585838183838384838581818080807d7d766e6e89999d97989a999999
%
% zde jsou ulozeny informace o zbyvajicich pixelech rastroveho obrazku
%
5d6061636364666566676a6c70747981868b8f8a453e444f5854585a473a
353c384757482b202a3e
grestore
showpage % pro EPS je nutne tento prikaz odstranit
%%Trailer 

4801
Obrázek 1: Aplikace lineární transformace zrcadlení na rastrový obrázek

3. Otočení rastrových obrázků a další lineární transformace

Když umíme provádět zrcadlení, není již problém na rastrové obrázky aplikovat i další lineární transformace, například změnu měřítka a současně i otáčení. Transformace je možné libovolně kombinovat, pouze je zapotřebí mít na paměti, že skládaní jednotlivých transformací není, podobně jako násobení matic, komutativní operace, tj. záleží na pořadí zadání transformací. To je však logické, protože i při „ručním“ provádění transformací záleží na tom, zda se nejdříve obrázek otočí a teprve potom posune či naopak, zda se nejdříve posune a teprve poté otočí (rotace se totiž vždy provádí okolo středu souřadné soustavy, jiný typ rotace je zapotřebí simulovat složením translací/posuvů a rotace). Při provádění všech transformací je také vhodné změnit souřadnice bounding-boxu (pokud se jedná o soubory typu EPS), protože v opačném případě by se mohlo stát, že by byl obrázek ořezán (v tomto případě ovšem záleží na chování konkrétního RIPu).

4. Druhý demonstrační příklad – otočení a změna velikosti obrázku Leny

V dnešním druhém demonstračním příkladu, jehož plnou verzi je možné získat pod tímto odkazem, je ukázána kombinace několika lineárních transformací, které se po vynásobení transformačních matic každé transformace složí do CTM. Obrázek je pomocí operátoru rotate otočen o 45° a je také změněno jeho měřítko pomocí operátoru scale (obrázek je zvětšen na dvojnásobnou velikost). Původní rozměry obrázku jsou 76,8×76,8 bodů (1/72 palce). Aby byla tato hodnota v PostScriptovém souboru zachována, tj. aby se zde nenacházely další „magické konstanty“, použil jsem při specifikaci parametrů pro operátor scale dva aritmetické výrazy 2 76.8 mul, pomocí kterých se rozměry obrázku vynásobí dvěma (nesmíme zapomenout na to, že se všechny výrazy v PostScriptu zapisují obrácenou polskou notací). Zdrojový tvar druhého příkladu má zhruba tento tvar (opět jsou vynechány řádky s obrazovými daty):

%!PS-Adobe-2.0 EPSF-2.0
%%Creator: pnmtops and vim
%%Title: lena2.ps
%%Pages: 1
%%BoundingBox: 100 200 500 800
%%EndComments
/readstring {
  currentfile exch readhexstring pop
} bind def
/picstr 80 string def
%%EndProlog
%%Page: 1 1

% ulozeni grafickeho stavu - pro EPS nutne
gsave

% posun obrazku
267.6 357.6 translate

% zmena meritka - dvojnasobny obrazek
2 76.8 mul 2 76.8 mul scale

% otoceni rastroveho obrazku
45.0 rotate

% parametry pro prikaz "image"
80 80 8
[ 80 0 0 -80 0 80 ]
{ picstr readstring }
image
9f9e9b9a9a9da7aca17f5d626968696a6d757b7d81838181838585858484
858585838183838384838581818080807d7d766e6e89999d97989a999999
%
% zde jsou ulozeny informace o zbyvajicich pixelech rastroveho obrazku
%
5d6061636364666566676a6c70747981868b8f8a453e444f5854585a473a
353c384757482b202a3e
grestore
showpage % pro EPS je nutne tento prikaz odstranit
%%Trailer 

4802
Obrázek 2: Aplikace lineární transformace rotace a změny měřítka na rastrový obrázek

5. Ořezání bitmap pomocí ořezové cesty

Další operací, kterou je možné s rastrovými obrázky v PostScriptu provádět, je jejich ořezání pomocí ořezové cesty (clip path) či bitové masky (bit mask). Ukážeme se použití ořezové cesty, protože tato operace je používána častěji, než maskování obrázku pomocí bitové masky. Princip ořezání obrázku je poměrně jednoduchý: před vlastním vykreslením bitmapy, tj. před zadáním příkazu image či colorimage se vytvoří ořezová cesta, která se může, podobně jako vykreslovaná či vyplňovaná cesta, skládat z libovolné kombinace úseček, Bézierových křivek a kruhových oblouků. Pokud je ořezová cesta definována, provádí se při vykreslování obrázku s každým pixelem test, zda leží či neleží uvnitř této cesty. V případě, že pixel leží uvnitř cesty, je vykreslen, v opačném případě je takový pixel zahozen, takže neovlivní již nakreslenou část dokumentu.

Ořezání bitmap tedy produkuje jiný výsledek než pouhé přebarvení některých pixelů barvou pozadí. Kde můžeme tuto operaci použít? Samozřejmě při kompozici rastrového obrázku do složitějšího dokumentu, kdy je možné kombinovat ořez s obtékáním textu okolo grafiky. Existuje ovšem také mnohem zajímavější použití – vzhledem k tomu, že vykreslovaný text se rozkládá na cestu (ta se skládá z obecně více na sebe nenavazujících částí), je možné tuto cestu použít pro ořezání obrázku, který tak bude vykreslen pouze uvnitř jednotlivých písmen. Tímto způsobem můžeme dosáhnout mnoha zajímavých efektů, které by se v grafickém editoru mohly vytvářet složitým způsobem (samozřejmě také záleží na schopnostech daného editoru). Zbývá doplnit informaci, že ořezání rastrových obrázků se vlastně provádí v každém případě, i bez explicitního uvedení ořezové cesty. Implicitní ořezová cesta má totiž tvar shodný s výstupním médiem, tj. například s formátem papíru A4.

6. Třetí demonstrační příklad – použití ořezové cesty

Ve třetím demonstračním příkladu si ukážeme, jakým způsobem je možné použít ořezovou cestu při vykreslování rastrových obrázků. Nejprve si však uvedeme příklad (zde je jeho celý zdrojový kód), který pouze vykreslí cestu vyplněnou černou barvu a přes tuto cestu nakreslí zvolený rastrový obrázek, na který jsou pro jednoduchost aplikovány stejné lineární transformace, jako v předchozím demonstračním příkladu. Ze screenshotu můžeme vidět, že ořezová cesta má tvar obdélníku (přesněji řečeno čtverce, ten však není celý obsažen v bounding-boxu), který transformovaný rastrový obrázek protíná zhruba v jeho první třetině:

%!PS-Adobe-2.0 EPSF-2.0
%%Creator: pnmtops and vim
%%Title: lena2.ps
%%Pages: 1
%%BoundingBox: 100 200 500 800
%%EndComments
/readstring {
  currentfile exch readhexstring pop
} bind def
/picstr 80 string def
%%EndProlog
%%Page: 1 1

% ulozeni grafickeho stavu - pro EPS nutne
gsave

% vytvoreni a vykresleni cesty
newpath
100 100 moveto
100 500 lineto
500 500 lineto
500 100 lineto
closepath
fill

% posun obrazku
267.6 357.6 translate

% zmena meritka - dvojnasobny obrazek
2 76.8 mul 2 76.8 mul scale

% otoceni rastroveho obrazku
45.0 rotate

% parametry pro prikaz "image"
80 80 8
[ 80 0 0 -80 0 80 ]
{ picstr readstring }
image
9f9e9b9a9a9da7aca17f5d626968696a6d757b7d81838181838585858484
858585838183838384838581818080807d7d766e6e89999d97989a999999
%
% zde jsou ulozeny informace o zbyvajicich pixelech rastroveho obrazku
%
5d6061636364666566676a6c70747981868b8f8a453e444f5854585a473a
353c384757482b202a3e
grestore
showpage % pro EPS je nutne tento prikaz odstranit
%%Trailer 

48_03
Obrázek 3: Bitmapa a vyplněná cesta

Úprava výše uvedeného příkladu tak, aby se z vyplněné cesty stala cesta ořezová, je velmi jednoduché. Místo příkazu fill, kterým se vykreslí vyplněná cesta, postačuje použít příkaz clip, který zkombinuje stávající ořezovou cestu (ta, jak již víme, „obkresluje“ celé tiskové médium, tj. A4) s cestou novou. Výsledkem je dokument, na kterém je zobrazena pouze část transformovaného rastrového obrázku Leny.

%!PS-Adobe-2.0 EPSF-2.0
%%Creator: pnmtops and vim
%%Title: lena2.ps
%%Pages: 1
%%BoundingBox: 100 200 500 800
%%EndComments
/readstring {
  currentfile exch readhexstring pop
} bind def
/picstr 80 string def
%%EndProlog
%%Page: 1 1

% ulozeni grafickeho stavu - pro EPS nutne
gsave

% vytvoreni a kombinace orezove cesty
newpath
100 100 moveto
100 500 lineto
500 500 lineto
500 100 lineto
closepath
clip

% posun obrazku
267.6 357.6 translate

% zmena meritka - dvojnasobny obrazek
2 76.8 mul 2 76.8 mul scale

% otoceni rastroveho obrazku
45.0 rotate

% parametry pro prikaz "image"
80 80 8
[ 80 0 0 -80 0 80 ]
{ picstr readstring }
image
9f9e9b9a9a9da7aca17f5d626968696a6d757b7d81838181838585858484
858585838183838384838581818080807d7d766e6e89999d97989a999999
%
% zde jsou ulozeny informace o zbyvajicich pixelech rastroveho obrazku
%
5d6061636364666566676a6c70747981868b8f8a453e444f5854585a473a
353c384757482b202a3e
grestore
showpage % pro EPS je nutne tento prikaz odstranit
%%Trailer 

48_04
Obrázek 4: Bitmapa ořezaná pomocí ořezové cesty

Cestu je samozřejmě možné vytvořit i komplikovanějším způsobem, například pomocí Bézierových křivek. To je ukázáno na dnešním posledním demonstračním příkladu, ve kterém je vytvořena ořezová cesta ve zhruba eliptickém tvaru (neracionální Bézierovy křivky nelze použít pro přesné vyjádření kuželoseček), která je aplikována na trojnásobně zvětšený obrázek Leny:

%!PS-Adobe-2.0 EPSF-2.0
%%Creator: pnmtops and vim
%%Title: lena2.ps
%%Pages: 1
%%BoundingBox: 100 200 500 800
%%EndComments
/readstring {
  currentfile exch readhexstring pop
} bind def
/picstr 80 string def
%%EndProlog
%%Page: 1 1

% ulozeni grafickeho stavu - pro EPS nutne
gsave

% vytvoreni a kombinace orezove cesty
newpath
200 500 moveto
200 600
400 600
400 500 curveto
400 400
200 400
200 500 curveto
closepath
clip

% posun obrazku
300 340 translate

% zmena meritka - dvojnasobny obrazek
3 76.8 mul 3 76.8 mul scale

% otoceni rastroveho obrazku
45.0 rotate

% parametry pro prikaz "image"
80 80 8
[ 80 0 0 -80 0 80 ]
{ picstr readstring }
image
9f9e9b9a9a9da7aca17f5d626968696a6d757b7d81838181838585858484
%
% zde jsou ulozeny informace o zbyvajicich pixelech rastroveho obrazku
%
5d6061636364666566676a6c70747981868b8f8a453e444f5854585a473a
353c384757482b202a3e
grestore
showpage % pro EPS je nutne tento prikaz odstranit
%%Trailer 

48_05
Obrázek 5: Bitmapa ořezaná pomocí ořezové cesty elipsovitého tvaru

7. Literatura

Jelikož se jedná o poslední část tohoto seriálu, která je věnována grafickému metaformátu PostScript, uvedu zde soupis veškeré literatury, která byla většinou vypsána i v předchozích částech. Sice se jedná o určitou nadbytečnost, na druhou stranu je však dobré mít všechny odkazy uvedeny pohromadě. Kromě literatury a webových stránek, které se primárně zabývají PostScriptem, jsou uvedeny i dokumenty o programovacím jazyku Forth a zásobníkových procesorech, protože převrácená polská notace (RPN) a zásobníky tvoří nedílnou a velmi důležitou součást PostScriptu.

  1. Adobe Systems: PostScript Language Reference Manual, The Red Book,
    Adobe Systems Incorporated, 2nd edition, Addison Wesley 1990.
  2. Adobe Type 1 Font Format,
    Addison-Wesley
  3. Adobe Systems Incorporated, Glenn C. Reid:
    PostScript Language Program Design,
    Addison-Wesley 1990, ISBN 0–201–14396–8
  4. Adobe Systems Incorporated:
    PostScript Language Reference Manual,
    Addison-Wesley 1990, ISBN 0–201–18127–4
  5. Adobe Systems Incorporated:
    PostScript Language Tutorial and Cookbook,
    Addison-Wesley 1990, ISBN 0–201–10179–3
  6. Adobe Systems Incorporated:
    Programming the Display PostScript System With X
     1993
  7. Jean Callan King, Tony Esposito:
    The Designer's Guide to PostScript Text Type
     1997
  8. Ross Smith:
    Learning PostScript : A Visual Approach
    Published 1990
  9. Henry McGilton, Mary Campione:
    PostScript by Example
     1992
  10. Jonathan Grosvenor (Editor), et al:
    The PostScript Font Handbook : A Directory of Type 1 Fonts
     1992
  11. Pavel Herout:
    PostScriptové fonty pro ty, co o nich moc nevědí
  12. Petr Sojka: Grafika v TEXu (2),
    TeX Bulletin
  13. Rokicki, T.: DVIPS: A TEX Driver
  14. Thomas Merz:
    PostScript & Acrobat/PDF : Applications, Troubleshooting, and Cross-Platform Publishing,
     1996
  15. Timothy Van Zandt: PSTricks: PostScript macros for Generic TEX. User's Guide.

UX DAy - tip 2

8. Odkazy na Internetu

  1. Wikipedia: PostScript,
    http://en.wiki­pedia.org/wiki/Pos­tScript
  2. Paul Bourke: PostScript Tutorial,
    http://local.was­p.uwa.edu.au/~pbou­rke/dataformat­s/postscript/
  3. A First Guide to PostScript,
    http://www.ta­ilrecursive.or­g/postscript/pos­tscript.html
  4. PostScript fractals,
    http://www.pvv­.ntnu.no/~ander­sr/fractal/Pos­tScript.html
  5. Fractal generation,
    http://www.chez­.com/emarsden/dow­nloads/
  6. Pierre Bézier,
    http://en.wiki­pedia.org/wiki/Pi­erre_B%C3%A9z­ier
  7. Dmitry Kirsanov's monthly column: Nonlinear Design,
    http://www.we­breference.com/dlab/99­02/index.html
  8. Pavel Tišnovský:
    Programovací jazyk Forth,
    /clanky/progra­movaci-jazyk-forth-a-zasobnikove-procesory
  9. http://zforth­.com/ – takzvaný The Forth Programming Webring, počátek řetězce stránek věnovaných Forthu a příbuzným tématům. Zajímavé je, že tento server je vytvořen pomocí systému zHTTP, který je napsaný v dialektu programovacího jazyka Forth nazvaného zForth.
  10. http://www.for­th.com/ – úvodní stránka firmy Forth Inc., která vytváří komerční verze programovacího jazyka Forth spolu s propracovaným vývojovým prostředím, na stránce lze nalézt i odkaz na známý SwiftForth. Spoluzakladatelem této firmy je Chuck Moore.
  11. http://en.wiki­pedia.org/wiki/For­th_programmin­g_language – stránka Wikipedie o programovacím jazyku Forth.
  12. http://en.wiki­pedia.org/wiki/Chuc­k_Moore – stránka Wikipedie o Chucku Moorovi, vynálezci Forthu.
  13. http://home.e­arthlink.net/~mrob/p­ub/lang_srom.html – porovnání programovacích jazyků podle názoru programátorů.
  14. http://www.jwdt­.com/~paysan/gfor­th.html – GForth (GNU Forth)
  15. http://www.for­th.com/resources/e­volution/index­.html – The Evolution of Forth – velmi dobře zpracovaná historie Forthu.

9. Obsah dalšího pokračování tohoto seriálu

V následující části seriálu o grafických formátech se začneme zabývat dalším známým a k tomu velmi dobře navrženým vektorovým formátem. Jedná se o souborový formát nazvaný Scalable Vector Graphics, neboli SVG, který je založený na značkovacím jazyku Extensible Markup Language – XML. Uvidíme, že díky dobře navržené struktuře tohoto formátu mohou být soubory založené na XML (které jsou jinak známé svým velkým objemem a pomalým zpracováním) překvapivě malé.

Byl pro vás článek přínosný?

Autor článku

Vystudoval VUT FIT a v současné době pracuje na projektech vytvářených v jazycích Python a Go.