|
JAI este un API care face parte din grupul Java Media API si este clasificat ca fiind o extensie standard a platformei Java. JAI furnizeaza functionalitati utile in procesarea de imagini dincolo de posibilitatile oferite de Java Foundation Classes (setul de clase de baza din Java), fiind totodata compatibil cu acesta.
JAI ofera mai multe avantaje pentru dezvoltatorii de aplicatii, in comparatie cu alte solutii de prelucrare a imaginilor. Cele mai importante dintre acestea vor fi expuse in cele ce urmeaza.
Prelucrare de imagini independenta de platforma. Majoritatea API-urilor specializate pe prelucrarea de imagini sunt destinate pentru un singur sistem de operare, insa JAI urmareste un model bazat pe biblioteci Java, ceea ce ii confera independenta de platforma. Implementari ale aplicatiilor JAI vor putea sa ruleze pe orice calculator cu Java VM. Acest lucru face ca JAI sa fie cu adevarat un API de prelucrari de imagini independent de platforma si care furnizeaza o interfata standard la posibilitatiile de prelucrari de imagini ale unei platforme. Asta inseamna ca se poate scrie o aplicatie o singura data si se va putea rula oriunde (conform sintagmei "Write once, run anywhere
Prelucrare de imagini distribuita. JAI este de asemenea foarte potrivit pentru prelucrari de imagini in aplicatii client-server prin mijloacele oferite de arhitectura de retea a platformei Java si prin tehnologiile de executie la distanta. Executia la distanta se bazeaza pe Java RMI (Remote Method Invocation). Java RMI permite ca codul Java de la client sa invoce metode din obiecte care se afla pe un alt calculator fara a muta aceste obiecte la client.
API orientat pe obiecte. Ca si Java, JAI este total orientat pe obiecte. In JAI, imaginile si operatiile de procesare de imagini sunt definite ca obiecte. JAI unifica notiunea de imagine si operator prin faptul ca amandoua sunt subclase ale aceluiasi parinte.
Un obiect operator este instantiat cu una sau mai multe imagini sursa si alti parametri. Acest obiect operator poate apoi deveni o imagine sursa pentru urmatorul obiect operator. Conexiunea dintre obiecte defineste un flux de date procesate. Graful editabil rezultat de operatii de procesare de imagini poate fi definit si instantiat dupa necesitati.
Flexibil si extensibil. Orice API pentru procesari de imagini trebuie sa suporte cel putin cateva tehnologii de baza, cum ar fi achizitia si afisarea imaginilor, manipulari de baza, imbunatatiri de imagini, manipulari geometrice si analiza de imagini. JAI furnizeaza un set de baza de operatori necesari pentru a sustine tehnologiile de procesari de imagini. Acesti operatori suporta multe dintre functiile necesare intr-o aplicatie de procesare de imagini. Deoarece anumite aplicatii necesita operatii speciale de procesari de imagini care sunt foarte rar folosite, pentru aceste aplicatii, JAI furnizeaza o infrastructura care permite ca solutii particulare sa poata fi adaugate la nucleul JAI API.
JAI detine de asemenea un set de standarde de metode de compresie si decopresie de imagini. Setul de baza se bazeaza pe standarde internationale pentru cele mai comune tipuri de fisiere comprimate. De asemenea JAI suporta adaugarea de codoare si decodoare mai speciale, care sunt folosite de aplicatii.
Independenta de dispozitivul de reprezentare. Procesarea de imagini poate fi specificata de coordonate independente de dispozitiv. Modul de reprezentare JAI trateaza toate imaginile sursa ca fiind independente de afisare. Se poate obtine astfel un graf (sau lant) de operatii de vizualizare fara a ne preocupa de rezolutia sau dimensiunile imaginii sursa, JAI ocupandu-se de toate aceste aspecte.
Puternic si performant. JAI suporta formate de imagine complexe, incluzand imagini cu pana la trei dimensiuni si un numar arbitrar de benzi, precum si multi algoritmi de procesare de imagini si operatori de procesare.
Pentru a spori performanta in procesarea imaginilor, pentru anumite platforme (actual pentru Solaris si Windows), JAI este implementat cu cod nativ, incluzand implementari ultra-optimizate care se bazeaza pe accelerare hardware si posibilitatile multimedia ale platformei, cum ar fi instructiuni MMX pentru procesoarele Intel si VIS pentru UltraSparc.
Interoperabilitate. JAI este integrat cu celelalte API-uri Java Media, fiind posibil astfel dezvoltarea de aplicatii multimedia foarte avansate pe platforma Java. JAI functioneaza bine cu celelalte API-uri, cum ar fi Java 3D sau tehnologiile bazate pe componente JavaBeans.
JAI API este construit pe fundatia Java 2D API pentru a permite aplicatii mai puternice si generale de procesari de imagini. JAI API adauga urmatoarele concepte:
Imagini multisegmentate
Executie amanata
Procesare de imagini in retea
Gestiunea proprietatilor imaginilor
Operatori imagine cu surse multiple
Date imagine tridimensionale
Combinatia dintre segmentare si executie amanata permite optimizari de rulare cu un model destul de simplu. Noi operatori pot fi adaugati si noi operatori pot participa ca obiecte de prima clasa in modelul de executie amanata.
JAI API de asemenea furnizeaza un grad destul de mare de compatibilitate cu modelele de procesare Java AWT si Java 2D. Operatorii JAI pot sa lucreze direct cu obiectele Java 2D BufferedImage sau cu orice alte obiecte imagine care implementeaza interfata RenderedImage. JAI suporta acelasi model independent de reprezentare ca si Java 2D API, folosind coordonate independente de dispozitiv. JAI suporta de asemenea stilul de desenare de la Java 2D pe amandoua tipurile de imagini, Rendered si Renderable folosind interfata Graphics.
JAI API nu utilizeaza interfetele de producator/consumator de imagine care au fost introduse in Java AWT si folosite mai apoi in Java 2D. In schimb, JAI API necesita ca imaginile sursa sa participe la modelul de procesare de tragere prin raspunsul la cereri pentru arii arbitrare, facand imposibil de instantiat un ImageProducer direct ca sursa. Este posibil, totusi, sa instantiem un ImageProducer ceea ce face ca datele imagine JAI API sa fie disponibile la aplicatii AWT mai vechi.
Similitudinile JAI cu Java 2D API sunt evidente, deoarece este dependent de abstractizarile definite in Java 2D API. In general, intregul mecanism pentru tratarea imaginilor de tip Renderable si Rendered, esantioanele pixelilor si stocarea datelor este sustinuta si de JAI. Principalele puncte comune ale celor doua API (JAI si Java 2D) sunt:
Interfetele RenderableImage si RenderedImage definite in Java 2D API sunt folosite ca baza pentru abstractizari de nivel inalt. JAI permite crearea si manipularea grafurilor directionale aciclice de obiecte implementand aceste interfete.
Obiectul principal de date, TiledImage, implementeaza interfata WritableRenderedImage si poate contine o grila regulata de segmente de obiecte Raster. Spre deosebire de BufferedImage din Java 2D API, TiledImage nu necesita sa fie prezent un obiect ColorModel pentru interpretare fotometrica a imaginii sale.
Obiectele operator din JAI sunt mult mai sofisticate decat in Java 2D API. Obiectul operator fundamental, OpImage, furnizeaza suport foarte bogat pentru extensibilitate spre noi operatori dincolo de posibilitatile Java 2D API. JAI are un mecanism bazat pe registri care automatizeaza selectia de operatii asupra unei RenderedImage.
Obiectele SampleModel, DataBuffer si Raster din Java 2D API sunt portate in JAI fara nici o modificare, cu exceptia ca se permite folosirea tipurilor double si float ca tipuri fundamentale de date a unui DataBuffer in adaos la tipurile existente, byte, short si int.
Clasele de date JAI. JAI introduce doua noi tipuri de clase de date care extind clasa de date DataBuffer din Java 2D. In Tabelul 6. sunt prezentate aceste clase.
Clasa
Descriere
DataBufferFloat
Stocheaza date intern sub forma de float.
DataBufferDouble
Stocheaza date intern sub forma de double.
Tabelul 6. Clasele utilizate pentru datele imagine din JAI
O operatie de procesare de imagini in JAI poate fi descrisa pe scurt in urmatorii patru pasi (JAI Programming, 1999):
1.Obtinerea unei s-au unor imagini sursa. Imaginile pot fi obtinute prin trei modalitati:
Incarcarea dintr-un fisier imagine cum ar fi GIF, TIFF, JPEG, etc.
Obtinerea unei imagini de la o alta sursa de date, cum ar fi un server distant.
Generarea unei imagini intern.
2.Definirea unui graf de prelucrari de imagini. Acest lucru este un proces in doua etape:
Definirea operatorilor imagine.
Definirea unei relatii parinte/copil intre surse si destinatii.
3.Evaluarea grafului folosind unul din urmatoarele trei modele de executie:
Modelul de executie Rendered (modul imediat).
Modelul de executie Renderable (modul amanat).
Modelul de executie la distenta (modul distant).
4.Procesarea rezultatului. Aici avem patru posibilitati:
Salvarea imaginii intr-un fisier
Afisarea imaginii pe ecran
Tiparirea imaginii la imprimanta sau la alt dispozitiv
Trimiterea imaginii la un alt API, de exemplu Swing.
In JAI orice operatie este definita ca obiect. Un obiect operator este instantiat cu nici una sau cu mai multe imagini sursa si alti parametri care definesc operatia. Doi sau mai multi operatori pot fi cuplati, astfel incat primul operator devine imaginea sursa pentru urmatorul operator. Prin legarea unui operator de un altul, se creeaza un graf de procesare de imagini sau lant.
In forma cea mai simpla, un graf de procesare de imagini este un lant de obiecte operator cu una sau mai multe imagini sursa la un capat si o imagine destinatie la celalalt. Graful astfel creat este cunoscut sub denumirea de graf aciclic directionat (DAG - directed acyclic graph), unde fiecare obiect este un nod in graf, iar referintele la obiecte formeaza ramuri. (Figura 5.)
Structura unui graf poate fi considerata ca fiind produsa de operatii, iar forma grafului este folositoare la vizualizarea acestor operatii. Un DAG este un graf care nu contine cicluri. Acest lucru inseamna ca pe o ruta de la un nod A spre un nod B nu mai exista o cale de intoarcere.
JAI extinde independenta de reprezentare, care a fost introdusa in Java 2D API. Cu ajutorul independentei de reprezentare se poate descrie o imagine asa cum dorim noi sa apara, independent de orice instanta specifica. JAI prezinta un mod Renderable prin felul in care trateaza toate sursele imagine ca si independente de reprezentare. Se poate construi un graf (sau lant) de operatii Renderable fara a ne interesa rezolutia sau dimensiunile imaginii sursa, JAI ocupandu-se de toate aceste detalii.
JAI a introdus doua tipuri de grafuri: Rendered si Renderable.
Grafuri Rendered. Grafurile Rendered sunt forma cea mai simpla de reprezentare in JAI. Grafurile Renderable au avantajul independentei de reprezentare, eliminand nevoia de a lucra direct cu pixeli, in schimb grafurile Rendered sunt utile atunci cand este necesar sa lucram direct cu pixeli. Un graf Rendered proceseaza imaginea in modul imediat. Pentru orice nod din graf, imaginea sursa este considerata ca o evaluare la momentul in care este instantiata si adaugata la graf, sau ca o noua operatie adaugata la lant.
Un graf Rendered este compus din noduri de obiecte Rendered. Aceste noduri sunt de obicei instante ale clasei RenderedOp, dar poate fi si o subclasa a clasei PlanarImage, care este versiunea JAI a clasei RenderedImage.
Imaginile sursa sunt obiecte care implementeaza interfata RenderedImage. Aceste surse sunt specificate ca parametri in constructia unor noi obiecte imagine. Fragmentul de cod urmator (Exemplul 10.) exemplifica construirea unui lant Rendered.
Exemplul 10. Exemplu de lant Rendered
import javax.jai.*;
import javax.jai.widget.*;
import java.awt.Frame;
public class AddExample extends Frame
Primele trei linii din exemplu specifica pachetele si clasele care se importa. Clasele care incep cu javax.jai sunt clasele JAI. Acest exemplu defineste un obiect de tip cadru (Frame) care contine un obiect pentru afisarea imaginilor (ScrollingImagePanel). Pentru simplicitatea prezentarii, toate actiunile executate de aceasta clasa sunt definite in constructor. Acest constructor primeste doua obiecte de tip ParameterBlock, utilizate in constructia a doua imagini de tip constant, care vor fi adunate impreuna pentru a crea imaginea destinatie. In cele din urma se afiseaza imaginea destinatie intr-o fereastra cu bare de defilare si apoi este atasata la cadrul principal.
Din momentul in care pixelii incep sa curga", graful acestei procesari v-a arata ca in Figura 6., intregul proces fiind condus de catre componenta de afisare. Imaginile sursa nu sunt incarcate si nici un pixel nu este produs pana cand componenta de afisare le cere.
Grafuri Renderable. Grafurile Renderable nu sunt evaluate la momentul in care se specifica. Evaluarea este amanata pana cand apare o cerere specifica pentru o reprezentare. Acest proces este cunoscut sub numele de executie amanata (deferred execution
Intr-un graf Renderable, daca o imagine sursa trebuie sa se schimbe inainte sa fie o cerere pentru reprezentare, schimbarea va fi reflectata la iesire. Acest proces este posibil datorita modelului de "tragere", unde procesul care cere imaginea, trage imaginea prin lant, lucru care este in opozitie cu modelul de impingere din procesarile AWT.
Un graf Renderable este alcatuit din obiecte noduri care implementeaza interfata RenderableImage, dar de obicei se foloseste obiecte de tipul RenderableOp. Pe masura ce se construieste graful Renderable, sursele din fiecare nod sunt specificate prin topologia grafului. Sursa unui graf Renderable este un obiect de tip RenderableImage.
Fragmentul de cod urmator (Exemplul 11.) reprezinta un exemplu de graf Renderable. Acest exemplu citeste un fisier in format TIFF, inverseaza valorile pixelilor si aduna o valoare constanta la pixeli.
Exemplul 11. Exemplu de graf Renderable
// Preia o sursa Rendered din sursa fisier TIFF
// obiectul ParameterBlock `pb0' contine numele
// sursei (fisier, URL, etc.). Obiectele `hints0',
// `hints1' si `hints2' contin indiciile de reprezentare si se
// presupune ca sunt create in afara acestui fragment de cod.
RenderedOp sourceImg = JAI.create('TIFF', pb0);
// Se obtine obiectul RenderableImage
// din sursa RenderedImage.
ParameterBlock pb = new ParameterBlock();
pb.addSource(sourceImg);
pb.add(null).add(null).add(null).add(null).add(null);
// creeaza o operatie Renderable.
RenderableImage ren = JAI.createRenderable('renderable', pb);
// creeaza blocul de parametrii pentru primul operand.
ParameterBlock pb1 = new ParameterBlock();
pb1.addSource(ren);
// Creeaza primul operand din lantul Renderable ca
// operatie de inversare.
RenderableOp Op1 = JAI.createRenderable('invert', pb1);
// creeaza blocul de parametrii pentru cel de-al doilea operand.
// constanta cu care se aduna este '2'.
ParameterBlock pb2 = new ParameterBlock();
pb2.addSource(Op1); // Op1 ca si sursa
pb2.add(2.0f); // 2.0f ca si constanta
// Creeaza al doilea operand ca si operatie de adunare
// cu o constanta.
RenderableOp Op2 = JAI.createRenderable('addconst', pb2);
// Creeaza contextul de reprezentare.
AffineTransform screenResolution = ;
RenderContext rc = new RenderContext(screenResolution);
// creeaza o reprezentare.
RenderedImage rndImg1 = Op2.createRendering(rc);
// Afiseaza reprezentarea folosind screenResolution.
imagePanel1 = new ScrollingImagePanel(rndImg1, 100, 100);Graful asociat lantului Renderable este prezentat in Figura
Graful Renderable poate fi gandit ca si un model care, atunci cand este reprezentat, provoaca instantierea unui graf Rendered paralel pentru indeplinirea procesarilor actuale. In graful din exemplul de mai sus se produc urmatoarele:
Atunci cand este apelata metoda Op2.createRendering, aceasta apeleaza recursiv metoda Op1.createRendering cu argumentul RenderContext rc.
Operatia Op1 apeleaza apoi metoda sourceImg.getImage, cu rc ca argument. Obiectul sourceImg creeaza un nou obiect RenderedImage pentru pastrarea pixelilor sursa la rezolutia necesara si ii introduce in lant. Acesta returneaza la Op1 o referinta spre acest obiect.
Op1 foloseste apoi OperationRegistry ca sa gaseasca un obiect de tipul ContextualRenderedImageFactory (CRIF) care poate sa execute o operatie "invert". Obiectul rezultat RenderedOp returnat de catre CRIF este introdus in lant cu referinta returnata de sourceImg ca si sursa.
Referinta catre obiectul "invert" de tip RenderedImage este returnat la Op2, care repeta procesul, creand un obiect "addconst" de tip RenderedOp, introducandu-l in lant si returnand o referinta catre rndImg1.
La sfarsit, obiectul rndImg1 este utilizat la apelul lui ScrollingImagePanel sa afiseze rezultatul pe ecran.
Dupa crearea obiectului ScrollingImagePanel, lanturile Renderable si Rendered vor arata ca si in Figura 8.
In acest moment in lant, nu se proceseaza nici un pixel. Doar atunci cand obiectul ScrollingImagePanel necesita sa afiseze pixeli pe ecran se creeaza obiectele OpImage si pixelii sunt trasi prin lantul Rendered, lucru executat in ultima linie de cod a exemplului
imagePanel1 = new ScrollingImagePanel(rndImg1, 100, 100);
Reutilizarea grafurilor. De cele mai multe ori, este mai potrivit sa modificam un graf existent si sa-l reutilizam, decat sa cream un graf aproape identic. Amandoua tipurile de grafuri, Rendered si Renderable, sunt editabile cu anumite restrictii.
Initial, un nod dintr-un graf Rendered este modificabil, in sensul ca pot fi atribuite noi surse, care sunt considerate ca vor fi evaluate in momentul cand sunt atribuite, iar valorile parametrilor lor pot fi modificati. Cu toate acestea, odata ce reprezentarea are loc, nodul va fi inghetat" iar sursele si parametrii lui nu pot fi schimbati.
Un lant de noduri Rendered poate fi clonat fara ca nodurile lui sa fie inghetate cu ajutorul metodei RenderedOp.createInstance. Folosind aceasta metoda, un graf Rendered poate fi configurat si reutilizat dupa dorinta si de asemenea serializat si transmis prin retea.
Clasa RenderedOp furnizeaza cateva metode pentru reconfigurarea unui nod Rendered. Metodele setParameter pot fi folosite pentru modificarea parametrilor din noduri. Metoda setOperationName poate fi utilizata la schimbarea numelui operatiei. Metoda setParameterBlock poate fi folosita la schimbarea obiectului de tip ParameterBlock din noduri.
Deoarece grafurile Renderable nu sunt evaluate pana cand exista o cerere specifica pentru reprezentare, nodurile pot fi editate in orice moment. Singura problema in editarea grafurilor Renderable este introducerea de cicluri, care trebuie evitata.
Clasa RenderableOp furnizeaza cateva metode pentru reconfigurarea unui nod Renderable. Metodele setParameter pot fi folosite pentru modificarea parametrilor nodurilor. Metoda setParameterBlock poate fi folosita la schimbarea obiectelor PrameterBlock din noduri. Metoda setProperty poate fi folosita la modificarea proprietatii locale a unui nod. Metoda setSource poate fi folosita la modificarea sursei pentru un nod.
JAI este compus din mai multe clase grupate in cinci pachete:
javax.media.jai - contine interfetele si clasele de baza.
jaxax.media.jai.iterator - contine clase si interfete iterator, care sunt utile pentru scrierea operatiilor extensie.
javax.media.jai.operator - contine clase care descriu toti operatorii de procesare a imaginilor.
javax.media.jai.widget - contine interfete si clase pentru crearea de suprafete si ferestre cu bare de derulare simple pentru afisarea imaginilor.
com.sun.media.jai.codec - contine clase si interfete utile in decodarea si codarea fisierelor imagine.
Clasa JAI. Clasa JAI nu poate fi instantiata, ea este formata dintr-o colectie de metode statice care asigura o sintaxa simpla pentru crearea de grafuri de tip Renderable si Rendered. Majoritatea metodelor din aceasta clasa sunt folosite pentru a crea un RenderedImage, luand ca argumente un ParameterBlock si un RenderingHints. Exista o singura metoda pentru a crea un RenderableImage, cu argumente de tip ParameterBlock si RenderingHints.
Aceasta clasa detine cateva variante de metode create, toate acestea preiau surse si parametrii in mod direct si construiesc un obiect ParameterBlock automat.
Clasa PlanarImage. Clasa PlanarImage este clasa principala pentru descrierea imaginilor bidimensionale in JAI. Aceasta clasa implementeaza interfata RenderedImage din Java 2D API, TiledImage si OpImage.
Interfata RenderedImage descrie o imagine segmentata, disponibila doar pentru citire cu un model al pixelului descris de tipurile SampledModel si DataBuffer. Fiecare segment este o suprafata dreptunghiulara de dimensiune identica, asezata pe o grila regulata. Toate segmentele se folosesc de un acelasi obiect SampleModel. In plus, fata de posibilitatile oferite RenderedImage, PlanarImage mentine conexiunile dintre sursa si destinatie, dintre nodurile grafurilor Rendered. Deoarece nodurile grafului sunt conectate bidirectional, garbage-collector-ul necesita un mic ajutor pentru a detecta atunci cand o portiune din graf nu mai este referentiata de codul utilizator si poate fi eliberata. Clasa PlanarImage se ocupa de acest lucru prin folosirea referintelor slabe (Weak References API) din Java 2.
Orice obiecte RenderedImage din exteriorul API sunt "acoperite" pentru a produce o instanta de PlanarImage. Acest lucru permite ca API sa utilizeze functionalitatile suplimentare din PlanarImage pentru toate imaginile.
Clasa CollectionImage. CollectionImage este o superclasa abstracta pentru patru clase si reprezinta colectii de obiecte PlanarImage:
ImageStack - reprezinta imagini bidimensionale care sunt asezate intr-un spatiu tridimensional. Imaginile necesita sa fie asezate paralel una cu cealalta.
ImageSequence - reprezinta o secventa de imagini cu marcajul de timp asociat si pozitiile camerei. Este folosita pentru a reprezenta imagini video sau fotografii dependente de timp.
ImagePyramid - reprezinta o serie de imagini de rezolutie progresiv mai mica, fiecare derivata din ultima prin mijloacele unui operator de procesare.
ImageMIPMap - reprezinta o stiva de imagini cu o relatie operationala fixa intre partile adiacente.
Clasa TiledImage. Clasa TiledImage reprezinta imagini continand mai multe segmente aranjate intr-o grila. Segmentele formeaza o grila regulata, care poate sa ocupe orice regiune dreptunghiulara din plan.
Clasa implementeaza interfata WritableRenderedImage din Java 2D API, de asemenea extinde clasa PlanarImage. Clasa permite ca segmentele sa poata fi validate pentru scriere, dupa ce datele pixelului vor fi accesate direct. De asemenea aceasta are o metoda createGraphics care permite ca continutul sa fie modificat utilizand apeluri de desenare din Java 2D API.
Aceasta clasa contine initial o grila care este goala, pe masura ce fiecare segment este solicitat, se initializeaza cu date dintr-o sursa PlanarImage. Dupa ce un segment este initializat, continutul sau poate fi modificat. O regiune de interes (ROI) arbitrara poate fi umpluta cu date copiate dintr-o sursa PlanarImage.
Clasa contine o metoda care permite desenarea unui obiect Graphics2D intr-un obiect TiledImage. Acest lucru este util la adaugarea de text, linii, sau a altor obiecte grafice simple la o imagine.
Clasa OpImage. OpImage este clasa parinte pentru toate operatiile de procesare a imaginilor, cum ar fi:
AreaOpImage - pentru operatori imagine care necesita doar o regiune dreptunghiulara fixa in jurul pixelului sursa pentru a calcula fiecare pixel destinatie.
PointOpImage - pentru operatori imagine care necesita doar un singur pixel sursa pentru a calcula fiecare pixel destinatie.
SourcelessOpImage - pentru operatori imagine care nu au imagine sursa.
StatisticsOpImage - pentru operatori imagine care calculeaza statistica pe o regiune data dintr-o imagine, cu o frecventa de esantionare data.
UntiledOpImage - pentru operatii uni-sursa in care valorile tuturor pixelilor din imaginea sursa contribuie la valoarea fiecarui pixel din imaginea destinatie.
WrapOpImage - pentru operatori imagine care executa o acoperire de imagine.
ScaleOpImage - pentru operatori extensie care executa scalare si necesita mapare regresiva rectilinie si adaugare prin dimensiunile filtrului de reesantionare.
Clasa OpImage este capabila sa determine care arii sursa sunt suficiente pentru calcularea unei arii date din destinatie prin mijloace furnizate de utilizator si anume metoda mapDestRect. Pentru majoritatea operatiilor, aceasta metoda este furnizata de o subclasa standard a clasei OpImage, cum ar fi PointOpImage sau AreaOpImage.
Clasa RenderableOp. Aceasta clasa aduce o reprezentare usoara (lightweight) a unei operatii in spatiul Renderable. Obiectele de tipul RenderableOp sunt create in mod normal folosind metoda createRenderable din clasa JAI si poate fi modificata dupa dorinta. De asemenea, clasa implementeaza interfata RenderableImage, asa ca poate fi interogata pentru dimensiunile sale independente de reprezentare.
Atunci cand un obiect RenderableOp trebuie sa fie reprezentat, acesta utilizeaza un obiect OperationRegistry pentru localizarea unui obiect de tipul ContextualRenderedImageFactory pentru a executa conversia din spatiul Renderable in RenderedImage.
Clasa RenderedOp. Este un obiect lightweight similar cu RebderableOp care stocheaza un nume de operatie, ParameterBlock si RenderingHints si poate fi adaugat intr-un graf Rendered. Exista doua metode pentru producerea si reprezentarea unui RenderedOp:
Implicita - orice apel la o metoda RenderedImage din RenderedOp provoaca crearea reprezentarii. Aceasta reprezentare este in mod obisnuit compusa dintr-un lant de obiecte OpImage cu o geometrie similara cu cea a lantului RenderedOp.
Explicita - un apel la metoda createInstance cloneaza obiectul RenderedOp si sursa lui, rezultand un nou lant Rendered cu aceleasi surse non-RenderedOp (de exemplu, obiecte TiledImage) ca si lantul original.
Obiectele RenderedOp care nu au fost reprezentate pot avea sursele si parametrii modificati. Sursele sunt considerate evaluate din momentul in care sunt conectate la un obiect RenderedOp.
JAI API specifica un set de baza de operatori de procesare de imagini. Categoriile generale de operatori de procesare de imagini suportati includ:
Operatori punctuali
Operatori de arie
Operatori geometrici
Operatori de cuantizare a culorii
Operatori de fisier
Operatori in frecventa
Operatori statistici
Operatori de extragere a muchiilor
Alti operatori
De asemenea JAI API suporta abstractizari pentru mai multe tipuri de colectii de imagini, cum ar fi imagini dependente de timp si piramide de imagini. Acestea au ca scop simplificarea operatiilor asupra colectiilor de imagini si permite dezvoltarea de operatori care lucreaza direct cu aceste abstractizari.
Operatori punctuali. Operatorii punctuali permit modificarea modului in care datele ocupa un domeniu disponibil de nivele de gri. Operatorii punctuali transforma imaginea de intrare intr-o imagine de iesire in asa fel incat fiecare pixel de iesire depinde doar de pixelul corespunzator de la intrare. Operatorii punctuali nu modifica relatia spatiala dintr-o imagine.
Cateva exemple de operatori punctuali sunt descrise in Tabelul
Operator
Descriere
Add
Preia doua imagini sursa Rendered sau Renderable si aduna fiecare pereche de pixeli, cate un pixel de la fiecare imagine sursa de la pozitia si banda corespunzatoare.
BandCombine
Preia o imagine sursa Rendered sau Renderable si calculeaza un set de combinatii liniare arbitrare asupra benzilor folosind o matrice specifica.
Composite
Preia doua imagini sursa Rendered sau Renderable si combina cele doua imagini bazandu-se pe valorile alfa a fiecarui pixel.
Invert
Preia o imagine sursa Rendered sau Renderable si inverseaza valorile pixelilor.
Tabelul Exemple de operatori punctuali din JAI
Operatori de arie. Operatorii de arie executa transformari geometrice care are ca rezultat repozitionarea pixelilor dintr-o imagine. Pixelii sunt repozitionati de la coordonatele spatiale initiale x si y din imaginea de intrare la noi coordonate in imaginea de iesire folosind transformari matematice.
Exista doua tipuri de operatii de arie de baza: liniare si neliniare. Operatiile liniare sunt translatia, rotatia si scalarea. Operatiile neliniare, cunoscute si sub numele de transformari de acoperire, sunt de curbare si de deformare. Cateva dintre aceste operatii sunt prezentate in Tabelul 8.
Operator
Descriere
Border
Preia o imagine sursa Rendered si ii adauga o bordura in jurul ei.
BoxFilter
Preia o imagine sursa Rendered si determina intensitatea unui pixel din imagine prin medierea pixelilor sursa din interiorul unei arii dreptunghiulare din jurul acelui pixel.
Convolve
Preia o imagine sursa Rendered si executa o operatie spatiala care calculeaza fiecare esantion de iesire prin inmultirea elementelor unui nucleu cu esantioanele inconjuratoare unui esantion particular.
Crop
Preia o imagine sursa Rendered sau Renderable si ajusteaza imaginea la o arie specificata.
MedianFilter
Preia o imagine sursa Rendered si o trece printr-un filtru neliniar care este util pentru eliminarea linilor sau pixelilor izolati, pastrand in mare infatisarea imaginii.
Tabelul 8. Operatori de arie
Operatori geometrici. Operatorii geometrici permit modificarea orientarii, marimii si formei unei imagini. Cateva exemple de astfel de operatori JAI se gasesc in Tabelul 9.
Operator
Descriere
Affine
Preia o sursa Rendered sau Renderable si executa o alocare affine
Rotate
Preia o imagine sursa Rendered sau Renderable si o roteste in jurul unui punct dat cu un unghi dat, specificat in radiani.
Scale
Preia o imagine sursa Rendered sau Renderable si translateaza si redimensioneaza imaginea.
Shear
Preia o imagine sursa Rendered sau Renderable si executa o intindere" (shearing) spatiala pe orizontala si verticala
Translate
Preia o imagine sursa Rendered sau Renderable si copiaza imaginea la o noua locatie din plan.
Transpose
Preia o imagine sursa Rendered sau Renderable si o intoarce sau o roteste.
Wrap
Preia o imagine sursa Rendered sau Renderable si executa o operatie de intindere generala a imaginii
Tabelul 9. Operatori geometrici
Operatori de cuantizare a culorii. Cuantizarea culorii este des folosita pentru a micsora conturarea amplitudinii pentru cadre bufer cu mai putin de 8 biti adancime sau pentru cadre bufer de culoare cu mai putin de 24 biti adancime. Operatori de cuantizare a culorii sunt prezentati in Tabelul 10.
Operator
Descriere
ErrorDiffusion
Preia o sursa Rendered sau Renderable si executa cuantizarea culorii prin cautarea celei mai apropiate culori pentru fiecare pixel dintr-o paleta de culori data si difuzarea erorii de cuantizare a culorii in partea de jos si dreapta a pixelului
OrderedDither
Preia o sursa Rendered sau Renderable si executa cuantizarea culorii prin cautarea celei mai apropiate culori pentru fiecare pixel dintr-un cub de culori dat si translatarea valorii indexului rezultat cu o cantitate pseudoaleatoare determinata de valorile date de masca dither
Tabelul 10. Operatorii de cuantizare a culorii
Operatori de fisier. Operatorii de fisier sunt utilizati pentru a citi si a scrie fisiere imagine. Cateva exemple de operatori de fisier sunt prezentati in Tabelul 11.
Operator
Descriere
AWTImage
Converteste un obiect standard java.awt.Image intr-o imagine Rendered
BMP
Citeste un flux de intrare standard BMP
Encode
Preia o imagine sursa Rendered si scrie imaginea la un obiect OutputStream in formatul specificat folosind parametrii de codare dati.
FileLoad
Citeste o imagine dintr-un fisier
FileStore
Preia o imagine sursa Rendered si scrie imaginea intr-un fisier dat in formatul specificat folosind parametrii de codare furnizati.
TIFF
Citeste date de tip TIFF 6.0 dintr-un SeekableStream
URL
Creeaza o imagine de iesire a carui sursa este specificata de un URL
Tabelul 11. Exemple de operatori de fisier
Operatori in frecventa. Operatorii in frecventa sunt folositi pentru a descompune o imagine din forma spatiala intr-o forma din domeniul frecventa. Operatorii sunt de asemenea disponibili pentru a executa operatia inversa a transformarii in frecventa, in care imaginea este convertita din domeniul frecventa inapoi in forma ei spatiala.
JAI suporta mai multe tipuri de transformari in frecventa. Cea mai utilizata transformare este transformta Fourier, dar JAI utilizeaza forma discreta a acestei transformate cunoscuta sub numele de transformata Fourier discreta, precum si transformata discreta cosinus impreuna cu variantele lor de transformari inverse. Cateva exemple de operatori in domeniul frecventa sunt prezentati in Tabelul 12.
Operator
Descriere
DCT
Preia o imagine sursa Rendered sau Renderable si calculeaza transformata discreta cosinus (DCT) para a imaginii. Fiecare banda a imaginii destinatie este derivata prin executarea unei transformari DCT bidimensionale asupra benzii corespunzatoare din imaginea sursa.
DFT
Preia o imagine sursa Rendered sau Renderable si calculeaza transformata discreta Fourier a imaginii.
Phase
Preia o imagine sursa Rendered sau Renderable continand date complexe si calculeaza unghiul fazei pentru fiecare pixel.
Tabelul 12. Exemple de operatori in domeniul frecventa
Operatori statistici. Operatorii statistici furnizeaza mijloace de analiza a continutului unei imagini. Operatorii statistici din JAI sunt prezentati in Tabelul 13.
Operator
Descriere
Extrema
Preia o sursa imagine Rendered, citeste o regiune specifica din imagine si gaseste valorile minime si maxime ale valorilor pixelilor pentru fiecare banda din acea regiune de imagine. Datele imagine trec prin acest operator nemodificate.
Histogram
Preia o imagine sursa Rendered, citeste o regiune specifica din imagine si genereaza o histograma bazandu-se pe valorile pixelilor din acea regiune de imagine. Datele histogramei sunt stocate intr-un obiect de tip javax.media.jai.Histogram obtinut de la utilizator, acesta putandu-se obtine printr-un apel la metoda getProperty asupra acestei operatii cu numele proprietatii "histogram". Valoarea de retur va fi de tipul javax.media.jai.Histogram. Datele imagine trec neschimbate prin aceasta operatie.
Mean
Preia o sursa imagine Rendered, citeste o regiune specifica si calculeaza valoarea medie pentru fiecare banda din interiorul unei regiuni dintr-o imagine. Datele imagine trec neschimbate prin aceasta operatie.
Tabelul 13. Operatori statistici
Operatori de extragere a muchiilor. Operatorii de extragere a muchiilor permit imbunatatirea muchiilor imaginii, reducand imaginea doar la detaliile muchiilor. Imbunatatirea muchiilor se face prin intermediul unor filtre spatiale care detecteaza o denivelare de stralucire a pixelilor specifica din interiorul unui grup de pixeli dintr-o imagine. O denivelare precipitata de stralucire indica prezenta unei muchii.
Operatorul GradientMagnitude preia o imagine sursa Rendered si calculeaza intensitatea vectorului gradient a imaginii pe doua directii ortogonale.
Alti operatori. Acestia sunt operatori care nu se incadreaza in categoriile de mai sus. Un astfel de operator din JAI este Renderable, care preia o imagine sursa Rendered si produce un obiect RenderableImage constituind o "piramida" de obiecte RenderedImage la valori ale rezolutiei progresiv mai mica.
Obiectele operatii sunt create in cele mai multe cazuri folosind metodele (metode create din clasa JAI) care vor fi expuse in cele ce urmeaza.
Pentru grafurile Renderable exista patru variatii pentru crearea de operatii in modul Renderable. De exemplu:
RenderableOp im = JAI.createRenderable('operationName',
paramBlock);
Metoda JAI.createRenderable creeaza un nod operatie Renderable care preia doi parametrii:
Un nume de operatie
O sursa si un set de parametrii pentru operatia continuta in blocul de parametrii
Pentru grafurile Rendered exista mult mai multe variatii ale metodelor de creare (metode JAI.create) a operatiilor in modul Rendered.
Exista doua versiuni ale metodei create care nu sunt statice, identificate ca createNS. Aceste metode pot fi utilizate cu o instanta specifica a clasei JAI si ar trebui utilizata doar atunci cand rezultatul final returnat este un singur obiect RenderedImage. Sursa sau sursele furnizate pot fi o colectie de imagini sau o colectie de colectii. In cele ce urmeaza se prezinta un exemplu de utilizare a acestei metode:
RenderedOp im = JAI.createNS('operationName',
source, param1, param2)
Indiciile de reprezentare asociate cu aceasta instanta a JAI sunt suprapuse cu indiciile furnizate la aceasta metoda, indiciile vor fi o uniune dintre indiciile instantei si indiciile date prin parametru.
Numele operatiei descrie operatorul care va fi creat si este un string.
Blocul de parametrii contine sursa operatiei si un set de parametrii utilizati de operatie. Continutul blocului de parametri depinde de operatia care se creeaza si poate fi doar numele imaginii sursa sau poate contine toti parametrii operatorului. Blocurile de parametrii incapsuleaza toate informatiile despre sursele si parametrii utilizati de operatie. Parametrii specificati de catre blocul de parametri sunt obiecte.
Aceste obiecte de control, parametri si surse, pot fi editate prin metoda setParameterBlock pentru a afecta operatii specifice sau chiar structura lantului de reprezetare. Modificarile afecteaza viitoarele obiecte RenderedImage derivate din punctele lantului din aval de unde s-a facut modificarea.
Exista doua clase separate pentru a specifica blocurile de parametrii:
java.awt.image.renderable.ParameterBlock - clasa principala pentru specificarea si schimbarea blocurilor de parametrii.
javax.media.jai.ParameterBlockJAI - extinde ParameterBlock prin permiterea utilizarii a valorilor implicite a parametrilor si utilizarii numelor de parametrii.
Blocul de parametrii trebuie sa contina acelasi numar de surse si parametri in functie de necesitatea operatiei, cu exceptia cand se foloseste ParameterBlockJAI care furnizeaza valori implicite. Pentru unele operatii, valorile implicite ale parametrilor nu sunt disponibile si de aceea ele trebuie furnizate.
Sursele sunt adaugate la blocul de parametrii cu metoda addSource. In exemplul urmator se creeaza un nou ParameterBlock numit pb si apoi metoda addSource este utilizata la adaugarea imaginii sursa im0 la blocul de parametrii.
ParameterBlock pb = new ParameterBlock();
pb.addSource(im0);
Pentru adaugarea a doua surse la un bloc de parametrii, se utilizeaza doua apeluri la metoda addSource.
ParameterBlock pb = new ParameterBlock();
pb.addSource(im0);
pb.addSource(im1);
In cazul folosirii clasei ParameterBlock, parametrii operatiei sunt adaugati la ParameterBlock cu metoda ParameterBlock.add. Exemplul urmator adauga doua valori la obiectul ParameterBlock numit pb, care a fost creat in exemplul anterior.
pb.add(150);
pb.add(200);
Metoda add poate fi utilizata cu toate tipurile de date suportate: byte, short, integer, long, float si double. Atunci cand se utilizeaza obiectul ParameterBlock, toti parametrii pe care o operatie are nevoie trebuie sa fie adaugati, altfel operatia va esua.
La utilizarea clasei ParameterBlockJAI, deoarece obiectul contine deja valori implicite pentru parametrii la momentul constructiei, parametrii trebuie schimbati cu metodele ParameterBlockJAI.set(value, index).
Exemplul urmator (Exemplul 12.) arata crearea unui Parameter-BlockJAI cu intentia de a fi furnizat unei operatii de rotire. Operatia de rotire preia patru parametrii: xOrigin, yOrigin, angle si interpolation. Valorile implicite pentru xOrigin si yOrigin sunt 0.0F pentru amandoua. In acest exemplu, aceste doua valori nu sunt modificate, deoarece valorile implicite sunt suficiente pentru operatie. Ceilalti doi parametri (angle si interpolation) au valoarea implicita null si astfel necesita modificarea valorilor. Imaginea sursa trebuie de asemenea specificata.
Exemplul 12. Utilizarea obiectelor ParameterBlockJAI pentru efectuarea operatiilor
// Specifica metoda de interpolatie utilizata
interp = Interpolation.create(Interpolation.INTERP_NEAREST);
// creeaza ParameterBlockJAI si adauga interpolatia la el
ParameterBlockJAI pb = new ParameterBlockJAI();
pb.addSource(im); // imaginea sursa
pb.set(1.2F, 'angle');// unghiul de rotatie in radiani
pb.set(interp, 'interpolation'); // metoda de interpolatieIndiciile de reprezentare reprezinta un set de indicii care descriu modul in care obiectele sunt reprezentate. Indiciile de reprezentare sunt intotdeauna optionale pentru orice operatie.
Indiciile de reprezentare specifica diferiti algoritmi de reprezentare cum ar fi antialiasing, interpolatie alfa si dithering. Multe dintre indicii permit alegerea dintre calitatea reprezentarii si viteza, alte indicii pot sa porneasca sau sa opreasca diferite optiuni de reprezentare, cum ar fi antialiasing si metrica fractionala. Exista doua clase separate pentru specificarea indiciilor de reprezentare:
java.awt.RenderingHints - contine indiciile de reprezentare care pot fi folosite de catre clasa Graphics2D si clasele care implementeaza Raster si BufferedImageOp.
javax.media.jai.JAI - furnizeaza metode pentru definirea cheilor pentru indicii de reprezentare specifice JAI.
Clasa RenderingHints creeaza indicii de reprezentare specifice Java AWT. Pentru a modifica indiciile de reprezentare, se creeaza un obiect RenderingHints si se transmite unei metode JAI.create asupra careia dorim sa actioneze. Modificand un indiciu de reprezentare nu se garanteaza ca un anume algoritm de reprezentare va fi folosit, deoarece nu toate platformele suporta modificarea codului de reprezentare.
In codul urmator, indiciile de reprezentare sunt setate pe calitate.
qualityHints = new
RenderingHints(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
Odata ce un obiect RenderingHints a fost creat, indiciile pot fi utilizate intr-o operatie folosind o metoda JAI.create.
Fiecare instanta a unui obiect JAI contine un set de indicii de reprezentare care va fi folosit pentru toate crearile de imagini sau colectii de imagini. Indiciile sunt combinate cu orice alte indicii furnizate metodei JAI.create. Indiciile furnizate direct au precedenta asupra indicilor obisnuite. Atunci cand o noua instanta JAI este construita, indiciile ei sunt initializate la o copie a indiciilor asociate cu instanta implicita. Indiciile asociate cu alte instante, incluzand instanta implicita, pot fi manipulate folosind metodele getRenderingHints, setRenderingHints si clearRenderingHints. Pentru manipularea individuala a indiciilor se folosesc metodele getRenderingHint, setRenderingHint si removeRenderingHint.
Codul urmator (Exemplul 13.) este un exemplu de reprezentare a unei imagini cu indicii de reprezentare pentru o operatie de scalare. Indiciul de reprezentare specifica originea imaginii destinatie modificata la 200x200.
Exemplul 13. Utilizarea indiciilor de reprezentare
// creeaza blocul de parametrii pentru operatia de scalare.
ParameterBlock pb = new ParameterBlock();
pb.addSource(im0);// imaginea sursa
pb.add(0F); // factorul de scalare x
pb.add(0F); // factorul de scalare y
pb.add(interp);// metoda de interpolatie
// Specificarea indiciilor de reprezentare
layout = new ImageLayout();
layout.setMinX(200);
layout.setMinY(200);
RenderingHints rh =
new RenderingHints(JAI.KEY_IMAGE_LAYOUT, layout);
// crearea operatiei de scalare.
PlanarImage im2 = (PlanarImage)JAI.create('scale', pb, layout)