Documente Academic
Documente Profesional
Documente Cultură
7.1. Evoluţia Procesării de Imagini În Java
7.1. Evoluţia Procesării de Imagini În Java
1
succes destul de remarcabil, dar nici unul dintre acestea nu au fost universal
acceptate deoarece au euat n a se adresa unui segment specific al domeniului
procesrilor de imagini sau nu aveau putere n a ndeplini anumite nevoi. Astfel
multe companii au trebuit s-i elaboreze propria implementare n ncercarea de
a ndeplinii aceste nevoi.
Experiena acumulat de ctre industrie i mediile universitare n
crearea unor biblioteci de procesare de imagini, utilitatea acestor biblioteci
peste o mare varietate de domenii de aplicabilitate i reacia utilizatorilor la
aceste biblioteci a condus la crearea JAI (Java Advanced Imaging) API.
JAI este conceput pentru a suporta procesri de imagini folosind
limbajul de programare Java ntr-un mod ct mai general posibil, adresndu-se
unui domeniu ct mai larg al aplicaiilor de procesare de imagini. n acelai
timp, JAI prezint un model de programare simplu care poate fi folosit cu
uurin n aplicaii fr a fi nevoie s se cunoasc toate fazele din construcia
API-ului.
JAI extinde mai departe platforma Java (incluznd Java 2D API)
permind astfel ca procesrile de imagini de mare performan s fie
ncorporate n applet-uri i aplicaii Java. JAI este un set de clase care
furnizeaz funcionaliti legate de procesarea de imagini dincolo de cele
obinute la Java 2D i Java Foundation Classes, dar fiind n acelai timp
compatibil cu aceste API-uri.
JAI implementeaz un set de resurse de baz n procesarea de imagini
care includ lucrul cu seciuni de imagine, regiuni de interes i execuie amnat.
JAI ofer de asemenea operatori de baz n procesarea de imagini care includ
muli operatori punctuali i spaiali obinuii, precum i operatori n domeniul
frecven. JAI ncapsuleaz formate de date imagine i invocare de metode
distant printr-un obiect imagine reutilizabil, permind unui fiier imagine,
unui obiect imagine de reea, sau unui flux de date n timp real s poat fi
procesate n mod identic.
JAI este proiectat s satisfac cerinele oricrei aplicaii de procesare
de imagini, acest API fiind foarte extensibil, permind ca noi operaii s fie
adugate.
JAI suport trei modele de procesare de imagini:
Modelul producer/consumer (productor/consumator) de mpingere,
care este modelul de baz AWT.
Modelul de mod imediat (Java 2D), care este un model AWT mai
avansat.
Model de tip pipeline de tragere, care este un model specific JAI.
Urmtorul tabel (Tabelul 7.1) contureaz cteva trsturi pentru
fiecare dintre aceste modele de procesare a imaginilor.
2
Modelul de Modelul de mod Modelul de tragere
mpingere imediat
Image BufferedImage RenderableImage
Interfee/clase
importante ImageProducer Raster RenderableImageO
ImageConsumer BufferedImageOp p
ImageObserver RasterOp (Java 2D API)
(JDK 1.0.X, (Java 2D API) RenderedOp
1.1.X) RenderableOp
TiledImage
(Java Advanced Imaging)
Procesare Interfa de Stocheaz/proceseaz
Avantaje
condus de programare mai doar datele necesare
disponibilitatea simpl Permite evaluarea
imaginii (de Modelul cel mai amnat
exemplu n reea) des utilizat
Imagini
procesate
incremental
Necesit Necesit alocare Interfa de programare
Dezavantaje
transferul (dar nu de memorie a ntregii mai complex
procesarea) imagini Implementare mai
imaginilor Necesit complex
complete procesarea de
Interfa de imagini ntregi
programare
complex
Tabelul 7.1. Modele de procesare a imaginilor n Java
3
Datele imagine au asociate un obiect ColorModel care descrie configuraia
pixelilor din imagine, precum i modul de interpretare a datelor.
Pentru a procesa imagini folosind modelul de mpingere, un obiect Image
este obinut dintr-o surs oarecare, de exemplu printr-un apel la metoda
Applet.getImage(). Metoda Image.getSource() poate apoi fi folosit pentru a
obine ImageProducer-ul pentru acel Image. O serie de obiecte de tip
FilteredImageSource pot fi ataate la ImageProducer, fiecare filtru fiind un
ImageConsumer a imaginii surs precedente.
Clasa FilteredImageSource este o implementare a interfeei
ImageProducer care preia o imagine i un obiect filtru i le folosete pentru a
produce date imagine coninnd imaginea filtrat. n fragmentul de cod urmtor
(Exemplul 7.1.) se prezint o filtrare a unei imagini folosind un filtru de
convoluie:
4
poate de asemenea instania un obiect de tip ImageObserver dac dorete s fie
ntiinat despre ncheierea unei operaii de procesare a imaginilor.
Procesrile de imagini din AWT nu au adoptat ideea unei imagini care
este susinut prin stocarea ei permanent. Att timp ct sunt furnizate metodele
pentru a converti o arie de memorie de intrare ntr-un ImageProducer, sau
pentru a captura o arie de memorie dintr-un ImageProducer, nu exist noiunea
de obiect imagine persistent care s poat fi reutilizat. Atunci cnd este nevoie
de date de la un Image, trebuie s obinem o referin spre ImageProducer-ul
imaginii.
Modelul AWT nu poate fi folosit pentru dezvoltarea de cod de
procesare a imaginilor foarte performant din cauza modelului de mpingere,
lipsei unui obiect imagine persistent, modelului restricionat al unui filtru
imagine i a unui numr mic de formate de date imagine. De asemenea lipsesc
cteva concepte de baz care sunt des folosite n procesarea de imagini, cum ar
fi operaiile executate pe o regiune de interes a unei imagini.
n Tabelul 7.2. sunt prezentate clasele i interfeele care sunt folosite
de modelul de mpingere AWT.
Clasa/Interfaa Descriere
Image Superclas pentru toate clasele care reprezint
imagini grafice
ColorModel Clas abstract care ncapsuleaz metodele pentru
translatarea valorii unui pixel spre componentele
culorii (ex. , rou, verde, albastru) i o
component alfa.
FilteredImageSource O implementare a interfeei ImageProducer care
preia imaginea existent i un obiect filtru i le
utilizeaz pentru a produce date imagine pentru o
nou versiune filtrat a imaginii originale
ImageProducer Interfa pentru obiectele care pot produce date
imagine pentru obiecte Image. Fiecare imagine
conine un ImageProducer care este folosit pentru
reconstrucia imaginii oricnd este nevoie, de
exemplu, atunci cnd imaginea este scalat i are
alte dimensiuni, sau cnd limea sau nlimea
imaginii este solicitat.
ImageConsumer Interfa pentru obiectele care i manifest
interesul asupra datelor imagine prin interfaa
ImageProducer. Cnd este adugat un
consumator la un productor de imagine,
productorul trimite toate datele despre imagine
folosind apeluri de metode definite n aceast
5
interfa.
ImageObserver Interfa asincron de actualizare pentru
recepionarea de notificri cu privire la
informaiile despre un obiect Image, n timp ce
imaginea se construiete.
Tabelul 7.2. Clasele i interfeele modelului de mpingere
BufferedImage
Raster ColorModel
SampleModel
ColorSpace
DataBuffer
Operaie de procesare a
imaginilor
filtru Imagine
Imagine surs destinaie
7
Operaiile suportate includ:
Transformare affine
Scalare de amplitudine
Modificare cu tabele de cutare (lookup table)
Combinare liniar a benzilor
Conversie de culori
Convoluie
Elemente dat sunt primitive tip utilizate ca uniti de stocare a datelor
imagine. Elementele dat sunt membrii individuali ai unei arii DataBuffer.
Configuraia elementelor n buferul de date este independent de interpretarea
datelor ca pixeli de ctre obiectul SampleModel al imaginii.
Eantioanele sunt membrii distinci de pixeli ai unei imagini. Un
obiect SampleModel asigur un mecanism pentru convertirea elementelor din
DataBuffer n pixeli i eantioanele sale. Eantioanele unui pixel pot s
reprezinte valori de baz ntr-un model de culoare particular, de exemplu, un
pixel dintr-un model de culoare RGB este compus din trei eantioane: red,
green i blue.
Componentele sunt valori ale pixelilor independente de interpretarea
culorilor. Distincia dintre component i eantion este folositoare pentru
IndexColorModel, unde componentele pixelului sunt indexate ntr-un
LookupTable.
O band este o component a spaiului de culoare a unei imagini. De
exemplu, componentele de rou, verde i albastru reprezint benzile dintr-o
imagine RGB. Datele pixelilor pot fi stocate n mai multe moduri, iar Java 2D
suport dou dintre acestea: organizare pe benzi i arie regulat de pixeli.
Stocarea pe benzi a pixelilor determin ca un pixel s fie format dintr-
o dat eantion de la aceeai poziie n fiecare band. Stocarea pixelilor ntr-o
arie organizeaz datele imagine n pixeli, astfel avem o singur arie coninnd
toi pixelii, iar benzile sunt constituite dintr-un set de eantioane la aceeai
poziie de index pentru fiecare pixel.
Un obiect ColorSpace ncapsuleaz regulile care guverneaz modul n
care un set de msurri corespund unei culori anume. Implementrile clasei
ColorSpace din pachetul java.awt.color reprezint cele mai utilizate spaii de
culoare, incluznd RGB sau scal de gri. Un spaiu de culoare reprezint nite
reguli pentru modul cum vor fi interpretate valorile culorilor.
Separaia spaiului de culoare de modelul de culoare asigur o
flexibilitate sporit la reprezentarea i conversia culorilor dintr-un anumit spaiu
al culorii n altul.
8
7.3.1. Clasa BufferedImage
BufferedImage offImg;
public Graphics2D
createMyG2D(Graphics g) {
Graphics2D g2 = null;
int width = getSize().width;
int height = getSize().height;
if (offImg == null || offImg.getWidth()
!= width || offImg.getHeight() != height) {
offImg = (BufferedImage)
createImage(width, height);
}
if (offImg != null) {
g2 = offImg.createGraphics();
g2.setBackground(getBackground());
}
// terge componenta
g2.clearRect(0, 0, width, height);
return g2;
}
9
cum ea ar fi afiat ntr-o fereastr. Toate facilitile de reprezentare Java 2D
pot fi aplicate atunci cnd se lucreaz cu imagini n afara ecranului.
Cea mai simpl metod de a crea o imagine, care poate fi folosit ca i
un bufer n afara ecranului, este prin apelul metodei Component.createImage.
Clasa BufferedImage suport cteva tipuri de imagine predefinite:
TYPE_3BYTE_BGR imagine cu componente de culoare RGB
pe 8 bii, corespunztoare modelului de culoare RGB din
Windows, cu culorile Blue, Green i Red stocate pe 3 bytes.
TYPE_4BYTE_ABGR imagine cu componente de culoare
RGBA pe 8 bii, cu culorile Blue, Green i Red stocate pe 3 bytes
i un byte pentru canalul alfa.
TYPE_4BYTE_ABGR_PRE imagine cu componente de
culoare RGBA pe 8 bii cu culorile Blue, Green i Red stocate pe
3 bytes i un byte pentru alfa
TYPE_BYTE_BINARY imagine opac pe 1, 2 sau 4 bii
TYPE_BYTE_GRAY imagine scal de gri pe un unsigned byte,
neindexat.
TYPE_BYTE_INDEXED imagine pe un byte indexat.
TYPE_CUSTOM imagine nerecunoscut, de tip utilizator.
TYPE_INT_ARGB_PRE imagine cu componente de culoare
RGBA pe 8 bii compus din pixeli integer.
TYPE_INT_ARGB imagine cu componente de culoare RGBA
pe 8 bii compus din pixeli integer.
TYPE_INT_BGR imagine cu componente de culoare RGBA pe
8 bii, corespunztor pentru modelele de culoare din Windows sau
Solaris, cu culorile Blue, Green i Red mpachetate n pixeli
integer.
TYPE_INT_RGB reprezint o imagine cu componente de
culoare RGB pe 8 bii mpachetate n pixeli integer.
TYPE_USHORT_555_RGB imagine cu componente de culoare
5-5-5 RGB (5-bii Red, 5-bii Green, 5-bii Blue) fr canal alfa.
TYPE_USHORT_565_RGB imagine cu componente de culoare
5-6-5 RGB (5-bii Red, 6-bii Green, 5-bii Blue) fr canal alfa.
TYPE_INT_GRAY imagine n scal de gri stocat pe tipul
unsignrd short, neindexat.
Pentru reprezentarea ntr-un obiect de tip BufferedImage, se apeleaz
metoda BufferedImage.createGraphics, care returneaz un obiect Graphics2D.
Cu acest obiect se pot apela toate metodele pentru reprezentarea primitivelor
grafice, sau reprezentarea altor imagini n imagine. n fragmentul de cod
urmtor (Exemplul 7.3.) se ilustreaz utilizarea buferrii n afara ecranului:
10
Exemplul 7.3. Exemplu de utilizare a buferrii n afara ecranului
public void update(Graphics g) {
Graphics2D g2 = (Graphics2D)g;
if(firstTime) {
Dimension dim = getSize();
int w = dim.width;
int h = dim.height;
area = new Rectangle(dim);
bi = (BufferedImage)createImage(w, h);
big = bi.createGraphics();
rect.setLocation(w/2-50, h/2-25);
big.setStroke(new BasicStroke(8.0f));
firstTime = false;
}
// terge suprafaa care a fost desenat anterior
big.setColor(Color.white);
big.clearRect(0, 0, area.width, area.height);
// Deseneaz i umple un nou dreptunghi n bufer.
big.setPaint(drept1);
big.draw(rect);
big.setPaint(drept2);
big.fill(rect);
// Deseneaz un buffered image pe ecran.
g2.drawImage(bi, 0, 0, this);
}
11
exemplu, atunci cnd se reprezint folosind metoda Component.paint, se
apeleaz drawImage asupra obiectului de afiare grafic transmis la metod
(vezi Exemplul 7.4).
12
care asigur filtrare la nivel de rastru i manipulare a datelor imagine sau atunci
cnd se implementeaz orice metod care are nevoie s execute manipulri de
pixeli de nivel inferior.
Metodele Raster.getPixel permit preluarea unui pixel individual care
este returnat ca eantion individual dintr-o arie. Metodele
Raster.getDataElements returneaz o poriune specificat a imaginii
neinterpretat din DataBuffer. Metoda Raster.getSample returneaz eantioane
cu un pixel individual. Metoda getSamples returneaz o band pentru o regiune
specificat dintr-o imagine. Buferul de date i modelul de eantioane poate fi de
asemenea accesat prin intermediul variabilelor instan a clasei Raster. Aceste
obiecte asigur mijloace suplimentare pentru accesarea i interpretarea datelor
pixel a unui obiect Raster.
Subclasa WritableRaster asigur metode pentru modificarea datelor
pixel i a eantioanelor. Obiectul Raster asociat cu un obiect BufferedImage
formeaz un obiect WritableRaster, asigurnd acces total la manipularea datelor
pixel.
13
Clasa Descrierea
DataBuffer Acoper unul sau mai multe arii de date.
Fiecare arie de date ne este refereniat ca i
un grup.
Raster Reprezint o arie dreptunghiular de pixeli i
furnizeaz metode pentru obinerea de date
imagine.
SampleModel Extrage eantioane de pixeli din imagini.
WriteableRaster Furnizeaz metode pentru stocarea datelor
imagine i motenete metode pentru
obinerea datelor imagine de la printele ei,
clasa Raster.
Tabelul 7.3. Clasele utilizate de Java 2D pentru
reprezentarea datelor imagine
14
Datele pixel oferite de SampleModel pot fi corelate direct cu un mod
de reprezentare a datelor culoare dintr-un model de culoare particular, n funcie
de datele surs. De exemplu, n datele imagine ale unei fotografii eantioanele
pot s reprezinte date RGB. n datele imagine de la un dispozitiv de prelucrare
a imaginilor medicale eantioanele pot s reprezinte tipuri diferite de date ca de
exemplu temperatura sau densitatea oaselor.
Exist trei categorii de metode pentru accesarea datelor imagine.
Metodele getPixel returneaz un pixel ntreg ca i o arie cu o singur valoare
pentru fiecare eantion. Metodele getDataElement asigur accesul la datele
brute, neinterpretate stocate n DataBuffer. Metodele getSample asigur accesul
la componentele pixelului pentru o band specific.
15
7.3.6. Procesare i mbuntire de imagini n Java 2D
16
Exemplul 7.7. Operaie de rescalare
RescaleOp rop = new RescaleOp(1.5f, 1.0f, null);
rop.filter(bi,bimg);
17
...
Kernel kernel = new Kernel(3,3,elements);
ConvolveOp cop = new ConvolveOp(kernel,
ConvolveOp.EDGE_NO_OP, null);
cop.filter(bi,bimg);
18
7.3.8. Straturi de reprezentare
ParameterBlock
20
7.3.10.1. Stratul Renderable
Clasa/Interfaa Descrierea
RenderableImage O interfa comun pentru imagini
independente de reprezentare
ContextualRenderedImage- Furnizeaz o interfa pentru funcionalitate
Factory care poate s difere ntre instane diferite de
RenderableImageOp.
ParameterBlock ncapsuleaz toate informaiile despre sursele
i parametrii necesari de ctre
RenderableImageOp i alte clase viitoare care
manipuleaz lanuri de operatori de procesare.
RenderableImageOp Se ocup de aspectele Renderable a unei
operaii cu ajutorul unei instane asociate de
ContextualRenderedImageFactory (CRIF).
RenderableImageProducer O clas adaptoare care implementeaz
ImageProducer i permite producerea
asincron a unui RenderableImage.
RenderContext ncapsuleaz informaia necesar pentru a
produce o reprezentare specific dintr-un
RenderableImage.
Tabelul 7.4. Clasele i interfeele utilizate de stratul Renderable
21
Un alt bloc implicat n construcia unui RenderableImageOp este
ParameterBlock. Clasa ParameterBlock gzduiete sursele pentru operaie i
parametrii sau alte obiecte pe care acel operator le poate cere. Parametrii sunt
versiuni independente de reprezentare ai parametrilor care controleaz
operatorul.
Lanul Renderable este construit prin instanierea fiecrui obiect
succesiv de tipul RenderableImageOp, fiind transmis n ultimul obiect
RenderableImage ca i surs n obiectul ParameterBlock. Acestui lan i se
poate cere s furnizeze un numr de reprezentri spre spaii dispozitiv specifice
prin intermediul metodei getImage.
Acest lan, odat construit rmne editabil. Parametrii pentru operaiile
specifice din lan i structura propriuzis a lanului se poate schimba. Acest
lucru se poate realiza prin apelul metodei setParameterBlock, modificnd
parametrii de control sau/i sursele. Aceste modificri afecteaz viitoarele
obiecte RenderedImage derivate din punctele din lan care se gsesc n zona
inferioar zonei unde sa fcut modificrile. Obiectele RenderedImage care sunt
obinute mai devreme din lanul Renderable sunt fixe i complet independente
de lanul din care au fost derivate.
RenderContext
22 ParameterBlock drawImage
Clasa/Interfaa Descriere
RenderedImage O interfa comun pentru obiecte
care conin sau pot produce date
imagine sub form de obiecte Raster.
BufferedImage O subclas care descrie un obiect
Image cu un bufer de date imagine
accesibil.
WritableRenderedImage O interfa comun pentru obiecte
care conin sau pot produce date
imagine care pot fi modificate sau/i
suprascrise.
Tabelul 7.5. Clasele i interfeele din stratul Rendered
JAI este un API care face parte din grupul Java Media API i este
clasificat ca fiind o extensie standard a platformei Java. JAI furnizeaz
funcionaliti utile n procesarea de imagini dincolo de posibilitile oferite de
Java Foundation Classes (setul de clase de baz din Java), fiind totodat
compatibil cu acesta.
JAI ofer mai multe avantaje pentru dezvoltatorii de aplicaii, n
comparaie cu alte soluii de prelucrare a imaginilor. Cele mai importante dintre
acestea vor fi expuse n cele ce urmeaz.
23
Prelucrare de imagini independent de platform. Majoritatea API-
urilor specializate pe prelucrarea de imagini sunt destinate pentru un singur
sistem de operare, ns JAI urmrete un model bazat pe biblioteci Java, ceea ce
i confer independen de platform. Implementri ale aplicaiilor JAI vor
putea s ruleze pe orice calculator cu Java VM. Acest lucru face ca JAI s fie cu
adevrat un API de prelucrri de imagini independent de platform i care
furnizeaz o interfa standard la posibilitiile de prelucrri de imagini ale unei
platforme. Asta nseamn c se poate scrie o aplicaie o singur dat i se va
putea rula oriunde (conform sintagmei Write once, run anywhere).
Prelucrare de imagini distribuit. JAI este de asemenea foarte
potrivit pentru prelucrri de imagini n aplicaii client-server prin mijloacele
oferite de arhitectura de reea a platformei Java i prin tehnologiile de execuie
la distan. Execuia la distan se bazeaz pe Java RMI (Remote Method
Invocation). Java RMI permite ca codul Java de la client s invoce metode din
obiecte care se afl pe un alt calculator fr a muta aceste obiecte la client.
API orientat pe obiecte. Ca i Java, JAI este total orientat pe obiecte.
n JAI, imaginile i operaiile de procesare de imagini sunt definite ca obiecte.
JAI unific noiunea de imagine i operator prin faptul c amndou sunt
subclase ale aceluiai printe.
Un obiect operator este instaniat cu una sau mai multe imagini surs
i ali parametri. Acest obiect operator poate apoi deveni o imagine surs pentru
urmtorul obiect operator. Conexiunea dintre obiecte definete un flux de date
procesate. Graful editabil rezultat de operaii de procesare de imagini poate fi
definit i instaniat dup necesiti.
Flexibil i extensibil. Orice API pentru procesri de imagini trebuie s
suporte cel puin cteva tehnologii de baz, cum ar fi achiziia i afiarea
imaginilor, manipulri de baz, mbuntiri de imagini, manipulri geometrice
i analiz de imagini. JAI furnizeaz un set de baz de operatori necesari pentru
a susine tehnologiile de procesri de imagini. Aceti operatori suport multe
dintre funciile necesare ntr-o aplicaie de procesare de imagini. Deoarece
anumite aplicaii necesit operaii speciale de procesri de imagini care sunt
foarte rar folosite, pentru aceste aplicaii, JAI furnizeaz o infrastructur care
permite ca soluii particulare s poat fi adugate la nucleul JAI API.
JAI deine de asemenea un set de standarde de metode de compresie i
decopresie de imagini. Setul de baz se bazeaz pe standarde internaionale
pentru cele mai comune tipuri de fiiere comprimate. De asemenea JAI suport
adugarea de codoare i decodoare mai speciale, care sunt folosite de aplicaii.
Independena de dispozitivul de reprezentare. Procesarea de
imagini poate fi specificat de coordonate independente de dispozitiv. Modul de
reprezentare JAI trateaz toate imaginile surs ca fiind independente de afiare.
Se poate obine astfel un graf (sau lan) de operaii de vizualizare fr a ne
24
preocupa de rezoluia sau dimensiunile imaginii surs, JAI ocupndu-se de
toate aceste aspecte.
Puternic i performant. JAI suport formate de imagine complexe,
incluznd imagini cu pn la trei dimensiuni i un numr arbitrar de benzi,
precum i muli algoritmi de procesare de imagini i operatori de procesare.
Pentru a spori performana n procesarea imaginilor, pentru anumite
platforme (actual pentru Solaris i Windows), JAI este implementat cu cod
nativ, incluznd implementri ultra-optimizate care se bazeaz pe accelerare
hardware i posibilitile multimedia ale platformei, cum ar fi instruciuni
MMX pentru procesoarele Intel i VIS pentru UltraSparc.
Interoperabilitate. JAI este integrat cu celelalte API-uri Java Media,
fiind posibil astfel dezvoltarea de aplicaii multimedia foarte avansate pe
platforma Java. JAI funcioneaz bine cu celelalte API-uri, cum ar fi Java 3D
sau tehnologiile bazate pe componente JavaBeans.
25
instaniat un ImageProducer direct ca surs. Este posibil, totui, s instaniem
un ImageProducer ceea ce face ca datele imagine JAI API s fie disponibile la
aplicaii AWT mai vechi.
Similitudinile JAI cu Java 2D API sunt evidente, deoarece este
dependent de abstractizrile definite n Java 2D API. n general, ntregul
mecanism pentru tratarea imaginilor de tip Renderable i Rendered,
eantioanele pixelilor i stocarea datelor este susinut i de JAI. Principalele
puncte comune ale celor dou API (JAI i Java 2D) sunt:
Interfeele RenderableImage i RenderedImage definite n Java 2D API sunt
folosite ca baz pentru abstractizri de nivel nalt. JAI permite crearea i
manipularea grafurilor direcionale aciclice de obiecte implementnd
aceste interfee.
Obiectul principal de date, TiledImage, implementeaz interfaa
WritableRenderedImage i poate conine o gril regulat de segmente de
obiecte Raster. Spre deosebire de BufferedImage din Java 2D API,
TiledImage nu necesit s fie prezent un obiect ColorModel pentru
interpretare fotometric a imaginii sale.
Obiectele operator din JAI sunt mult mai sofisticate dect n Java 2D API.
Obiectul operator fundamental, OpImage, furnizeaz suport foarte bogat
pentru extensibilitate spre noi operatori dincolo de posibilitile Java 2D
API. JAI are un mecanism bazat pe regitri care automatizeaz selecia de
operaii asupra unei RenderedImage.
Obiectele SampleModel, DataBuffer i Raster din Java 2D API sunt portate
n JAI fr nici o modificare, cu excepia c se permite folosirea tipurilor
double i float ca tipuri fundamentale de date a unui DataBuffer n adaos la
tipurile existente, byte, short i int.
Clasele de date JAI. JAI introduce dou noi tipuri de clase de date
care extind clasa de date DataBuffer din Java 2D. n Tabelul 7.6. sunt
prezentate aceste clase.
Clasa Descriere
DataBufferFloat Stocheaz date intern sub form de float.
DataBufferDouble Stocheaz date intern sub form de double.
Tabelul 7.6. Clasele utilizate pentru datele imagine din JAI
26
Generarea unei imagini intern.
2. Definirea unui graf de prelucrri de imagini. Acest lucru este un proces
n dou etape:
Definirea operatorilor imagine.
Definirea unei relaii printe/copil ntre surse i destinaii.
3. Evaluarea grafului folosind unul din urmtoarele trei modele de
execuie:
Modelul de execuie Rendered (modul imediat).
Modelul de execuie Renderable (modul amnat).
Modelul de execuie la disten (modul distant).
4. Procesarea rezultatului. Aici avem patru posibiliti:
Salvarea imaginii ntr-un fiier
Afiarea imaginii pe ecran
Tiprirea imaginii la imprimant sau la alt dispozitiv
Trimiterea imaginii la un alt API, de exemplu Swing.
im0 im1
constant constant
im1
Noduri add
Ramuri
Component de
afiare 27
28
ScrollingImagePanel imagePanel1;
// constructorul clasei
public AddExample(ParameterBlock param1,
ParameterBlock param2) {
// creaz o imagine constant
RenderedOp im0 = JAI.create("constant", param1);
// creaz o alt imagine constant
RenderedOp im1 = JAI.create("constant", param2);
// adun cele dou imagini mpreun
RenderedOp im2 = JAI.create("add", im0, im1);
// Afieaz imaginea ntr-o fereastr glisant
imagePanel1 = new ScrollingImagePanel(im2, 100,
100);
// ataeaz obiectul de afiare la cadrul principal
add(imagePanel1);
}
}
im0 im1
ConstantOpImage ConstantOpImage
im1
AddOpImage
Component
de afiare
29
Figura 7.6. Exemplu de lan Rendered
Grafuri Renderable. Grafurile Renderable nu sunt evaluate la
momentul n care se specific. Evaluarea este amnat pn cnd apare o cerere
specific pentru o reprezentare. Acest proces este cunoscut sub numele de
execuie amnat (deferred execution).
ntr-un graf Renderable, dac o imagine surs trebuie s se schimbe
nainte s fie o cerere pentru reprezentare, schimbarea va fi reflectat la ieire.
Acest proces este posibil datorit modelului de tragere, unde procesul care
cere imaginea, trage imaginea prin lan, lucru care este n opoziie cu modelul
de mpingere din procesrile AWT.
Un graf Renderable este alctuit din obiecte noduri care
implementeaz interfaa RenderableImage, dar de obicei se folosete obiecte de
tipul RenderableOp. Pe msur ce se construiete graful Renderable, sursele
din fiecare nod sunt specificate prin topologia grafului. Sursa unui graf
Renderable este un obiect de tip RenderableImage.
Fragmentul de cod urmtor (Exemplul 7.11.) reprezint un exemplu de
graf Renderable. Acest exemplu citete un fiier n format TIFF, inverseaz
valorile pixelilor i adun o valoare constant la pixeli.
30
// creeaz blocul de parametrii pentru cel de-al doilea operand.
// constanta cu care se adun este "2".
ParameterBlock pb2 = new ParameterBlock();
pb2.addSource(Op1); // Op1 ca i surs
pb2.add(2.0f); // 2.0f ca i constant
// Creeaz al doilea operand ca i operaie de adunare
// cu o constant.
RenderableOp Op2 = JAI.createRenderable("addconst", pb2);
// Creeaz contextul de reprezentare.
AffineTransform screenResolution = ...;
RenderContext rc = new RenderContext(screenResolution);
// creeaz o reprezentare.
RenderedImage rndImg1 = Op2.createRendering(rc);
// Afieaz reprezentarea folosind screenResolution.
imagePanel1 = new ScrollingImagePanel(rndImg1, 100, 100);
Imagine surs
RenderableOp
Op1
RenderableOp
Op2
RenderableOp
31
pentru pstrarea pixelilor surs la rezoluia necesar i i introduce n
lan. Acesta returneaz la Op1 o referin spre acest obiect.
Op1 folosete apoi OperationRegistry ca s gseasc un obiect de
tipul ContextualRenderedImageFactory (CRIF) care poate s execute
o operaie invert. Obiectul rezultat RenderedOp returnat de ctre
CRIF este introdus n lan cu referina returnat de sourceImg ca i
surs.
Referina ctre obiectul invert de tip RenderedImage este returnat
la Op2, care repet procesul, crend un obiect addconst de tip
RenderedOp, introducndu-l n lan i returnnd o referin ctre
rndImg1.
La sfrit, obiectul rndImg1 este utilizat la apelul lui
ScrollingImagePanel s afieze rezultatul pe ecran.
Dup crearea obiectului ScrollingImagePanel, lanurile Renderable i
Rendered vor arta ca i n Figura 7.8.
Imagine surs
RenderableOp
(NoName) addconst
RenderedOp
rndImg1
RenderedOp
ImagePanel1
(component de afiare)
JAI este compus din mai multe clase grupate n cinci pachete:
javax.media.jai conine interfeele i clasele de baz.
33
jaxax.media.jai.iterator conine clase i interfee iterator, care sunt utile
pentru scrierea operaiilor extensie.
javax.media.jai.operator conine clase care descriu toi operatorii de
procesare a imaginilor.
javax.media.jai.widget conine interfee i clase pentru crearea de
suprafee i ferestre cu bare de derulare simple pentru afiarea imaginilor.
com.sun.media.jai.codec conine clase i interfee utile n decodarea i
codarea fiierelor imagine.
Clasa JAI. Clasa JAI nu poate fi instaniat, ea este format dintr-o
colecie de metode statice care asigur o sintax simpl pentru crearea de
grafuri de tip Renderable i Rendered. Majoritatea metodelor din aceast clas
sunt folosite pentru a crea un RenderedImage, lund ca argumente un
ParameterBlock i un RenderingHints. Exist o singur metod pentru a crea
un RenderableImage, cu argumente de tip ParameterBlock i RenderingHints.
Aceast clas deine cteva variante de metode create, toate acestea
preiau surse i parametrii n mod direct i construiesc un obiect
ParameterBlock automat.
Clasa PlanarImage. Clasa PlanarImage este clasa principal pentru
descrierea imaginilor bidimensionale n JAI. Aceast clas implementeaz
interfaa RenderedImage din Java 2D API, TiledImage i OpImage.
Interfaa RenderedImage descrie o imagine segmentat, disponibil
doar pentru citire cu un model al pixelului descris de tipurile SampledModel i
DataBuffer. Fiecare segment este o suprafa dreptunghiular de dimensiune
identic, aezat pe o gril regulat. Toate segmentele se folosesc de un acelai
obiect SampleModel. n plus, fa de posibilitile oferite RenderedImage,
PlanarImage menine conexiunile dintre surs i destinaie, dintre nodurile
grafurilor Rendered. Deoarece nodurile grafului sunt conectate bidirecional,
garbage-collector-ul necesit un mic ajutor pentru a detecta atunci cnd o
poriune din graf nu mai este refereniat de codul utilizator i poate fi eliberat.
Clasa PlanarImage se ocup de acest lucru prin folosirea referinelor slabe
(Weak References API) din Java 2.
Orice obiecte RenderedImage din exteriorul API sunt acoperite
pentru a produce o instan de PlanarImage. Acest lucru permite ca API s
utilizeze funcionalitile suplimentare din PlanarImage pentru toate imaginile.
Clasa CollectionImage. CollectionImage este o superclas abstract
pentru patru clase i reprezint colecii de obiecte PlanarImage:
ImageStack reprezint imagini bidimensionale care sunt aezate ntr-un
spaiu tridimensional. Imaginile necesit s fie aezate paralel una cu
cealalt.
ImageSequence reprezint o secven de imagini cu marcajul de timp
asociat i poziiile camerei. Este folosit pentru a reprezenta imagini video
sau fotografii dependente de timp.
34
ImagePyramid reprezint o serie de imagini de rezoluie progresiv mai
mic, fiecare derivat din ultima prin mijloacele unui operator de
procesare.
ImageMIPMap reprezint o stiv de imagini cu o relaie operaional fix
ntre prile adiacente.
Clasa TiledImage. Clasa TiledImage reprezint imagini coninnd mai
multe segmente aranjate ntr-o gril. Segmentele formeaz o gril regulat, care
poate s ocupe orice regiune dreptunghiular din plan.
Clasa implementeaz interfaa WritableRenderedImage din Java 2D
API, de asemenea extinde clasa PlanarImage. Clasa permite ca segmentele s
poat fi validate pentru scriere, dup ce datele pixelului vor fi accesate direct.
De asemenea aceasta are o metod createGraphics care permite ca coninutul
s fie modificat utiliznd apeluri de desenare din Java 2D API.
Aceast clas conine iniial o gril care este goal, pe msur ce
fiecare segment este solicitat, se iniializeaz cu date dintr-o surs
PlanarImage. Dup ce un segment este iniializat, coninutul su poate fi
modificat. O regiune de interes (ROI) arbitrar poate fi umplut cu date copiate
dintr-o surs PlanarImage.
Clasa conine o metod care permite desenarea unui obiect
Graphics2D ntr-un obiect TiledImage. Acest lucru este util la adugarea de
text, linii, sau a altor obiecte grafice simple la o imagine.
Clasa OpImage. OpImage este clasa printe pentru toate operaiile de
procesare a imaginilor, cum ar fi:
AreaOpImage pentru operatori imagine care necesit doar o regiune
dreptunghiular fix n jurul pixelului surs pentru a calcula fiecare pixel
destinaie.
PointOpImage pentru operatori imagine care necesit doar un singur
pixel surs pentru a calcula fiecare pixel destinaie.
SourcelessOpImage pentru operatori imagine care nu au imagine surs.
StatisticsOpImage pentru operatori imagine care calculeaz statistica pe
o regiune dat dintr-o imagine, cu o frecven de eantionare dat.
UntiledOpImage pentru operaii uni-surs n care valorile tuturor
pixelilor din imaginea surs contribuie la valoarea fiecrui pixel din
imaginea destinaie.
WrapOpImage pentru operatori imagine care execut o acoperire de
imagine.
ScaleOpImage pentru operatori extensie care execut scalare i necesit
mapare regresiv rectilinie i adugare prin dimensiunile filtrului de
reeantionare.
Clasa OpImage este capabil s determine care arii surs sunt
suficiente pentru calcularea unei arii date din destinaie prin mijloace furnizate
de utilizator i anume metoda mapDestRect. Pentru majoritatea operaiilor,
35
aceast metod este furnizat de o subclas standard a clasei OpImage, cum ar
fi PointOpImage sau AreaOpImage.
Clasa RenderableOp. Aceast clas aduce o reprezentare uoar
(lightweight) a unei operaii in spaiul Renderable. Obiectele de tipul
RenderableOp sunt create n mod normal folosind metoda createRenderable
din clasa JAI i poate fi modificat dup dorin. De asemenea, clasa
implementeaz interfaa RenderableImage, aa c poate fi interogat pentru
dimensiunile sale independente de reprezentare.
Atunci cnd un obiect RenderableOp trebuie s fie reprezentat, acesta
utilizeaz un obiect OperationRegistry pentru localizarea unui obiect de tipul
ContextualRenderedImageFactory pentru a executa conversia din spaiul
Renderable n RenderedImage.
Clasa RenderedOp. Este un obiect lightweight similar cu
RebderableOp care stocheaz un nume de operaie, ParameterBlock i
RenderingHints i poate fi adugat ntr-un graf Rendered. Exist dou metode
pentru producerea i reprezentarea unui RenderedOp:
Implicit orice apel la o metod RenderedImage din RenderedOp
provoac crearea reprezentrii. Aceast reprezentare este n mod obinuit
compus dintr-un lan de obiecte OpImage cu o geometrie similar cu cea a
lanului RenderedOp.
Explicit un apel la metoda createInstance cloneaz obiectul
RenderedOp i sursa lui, rezultnd un nou lan Rendered cu aceleai surse
non-RenderedOp (de exemplu, obiecte TiledImage) ca i lanul original.
Obiectele RenderedOp care nu au fost reprezentate pot avea sursele i
parametrii modificai. Sursele sunt considerate evaluate din momentul n care
sunt conectate la un obiect RenderedOp.
36
imagini. Acestea au ca scop simplificarea operaiilor asupra coleciilor de
imagini i permite dezvoltarea de operatori care lucreaz direct cu aceste
abstractizri.
Operatori punctuali. Operatorii punctuali permit modificarea
modului n care datele ocup un domeniu disponibil de nivele de gri. Operatorii
punctuali transform imaginea de intrare ntr-o imagine de ieire n aa fel nct
fiecare pixel de ieire depinde doar de pixelul corespunztor de la intrare.
Operatorii punctuali nu modific relaia spaial dintr-o imagine.
Cteva exemple de operatori punctuali sunt descrise n Tabelul 7.7.
Operator Descriere
Add Preia dou imagini surs Rendered sau
Renderable i adun fiecare pereche de pixeli,
cte un pixel de la fiecare imagine surs de la
poziia i banda corespunztoare.
BandCombine Preia o imagine surs Rendered sau
Renderable i calculeaz un set de combinaii
liniare arbitrare asupra benzilor folosind o
matrice specific.
Composite Preia dou imagini surs Rendered sau
Renderable i combin cele dou imagini
bazndu-se pe valorile alfa a fiecrui pixel.
Invert Preia o imagine surs Rendered sau
Renderable i inverseaz valorile pixelilor.
Tabelul 7.7. Exemple de operatori punctuali din JAI
Operator Descriere
Border Preia o imagine surs Rendered i i adaug o
bordur n jurul ei.
BoxFilter Preia o imagine surs Rendered i determin
intensitatea unui pixel din imagine prin medierea
pixelilor surs din interiorul unei arii
dreptunghiulare din jurul acelui pixel.
37
Convolve Preia o imagine surs Rendered i execut o
operaie spaial care calculeaz fiecare eantion
de ieire prin nmulirea elementelor unui nucleu
cu eantioanele nconjurtoare unui eantion
particular.
Crop Preia o imagine surs Rendered sau Renderable
i ajusteaz imaginea la o arie specificat.
MedianFilter Preia o imagine surs Rendered i o trece printr-
un filtru neliniar care este util pentru eliminarea
linilor sau pixelilor izolai, pstrnd n mare
nfiarea imaginii.
Tabelul 7.8. Operatori de arie
Operator Descriere
Affine Preia o surs Rendered sau Renderable i execut o
alocare affine
Rotate Preia o imagine surs Rendered sau Renderable i o
rotete n jurul unui punct dat cu un unghi dat,
specificat n radiani.
Scale Preia o imagine surs Rendered sau Renderable i
translateaz i redimensioneaz imaginea.
Shear Preia o imagine surs Rendered sau Renderable i
execut o ntindere (shearing) spaial pe
orizontal i vertical
Translate Preia o imagine surs Rendered sau Renderable i
copiaz imaginea la o nou locaie din plan.
Transpose Preia o imagine surs Rendered sau Renderable i o
ntoarce sau o rotete.
Wrap Preia o imagine surs Rendered sau Renderable i
execut o operaie de ntindere general a imaginii
Tabelul 7.9. Operatori geometrici
Operator Descriere
38
ErrorDiffusion Preia o surs Rendered sau Renderable i execut
cuantizarea culorii prin cutarea celei mai apropiate
culori pentru fiecare pixel dintr-o palet de culori
dat i difuzarea erorii de cuantizare a culorii n
partea de jos i dreapta a pixelului
OrderedDither Preia o surs Rendered sau Renderable i execut
cuantizarea culorii prin cutarea celei mai apropiate
culori pentru fiecare pixel dintr-un cub de culori dat
i translatarea valorii indexului rezultat cu o
cantitate pseudoaleatoare determinat de valorile
date de masca dither
Tabelul 7.10. Operatorii de cuantizare a culorii
Operator Descriere
AWTImage Convertete un obiect standard java.awt.Image ntr-
o imagine Rendered
BMP Citete un flux de intrare standard BMP
Encode Preia o imagine surs Rendered i scrie imaginea la
un obiect OutputStream n formatul specificat
folosind parametrii de codare dai.
FileLoad Citete o imagine dintr-un fiier
FileStore Preia o imagine surs Rendered i scrie imaginea
ntr-un fiier dat n formatul specificat folosind
parametrii de codare furnizai.
TIFF Citete date de tip TIFF 6.0 dintr-un
SeekableStream
URL Creeaz o imagine de ieire a crui surs este
specificat de un URL
Tabelul 7.11. Exemple de operatori de fiier
39
precum i transformata discret cosinus mpreun cu variantele lor de
transformri inverse. Cteva exemple de operatori n domeniul frecven sunt
prezentai n Tabelul 7.12.
Operator Descriere
DCT Preia o imagine surs Rendered sau Renderable i
calculeaz transformata discret cosinus (DCT)
par a imaginii. Fiecare band a imaginii destinaie
este derivat prin executarea unei transformri
DCT bidimensionale asupra benzii corespunztoare
din imaginea surs.
DFT Preia o imagine surs Rendered sau Renderable i
calculeaz transformata discret Fourier a imaginii.
Phase Preia o imagine surs Rendered sau Renderable
coninnd date complexe i calculeaz unghiul
fazei pentru fiecare pixel.
Tabelul 7.12. Exemple de operatori n domeniul frecven
Operator Descriere
Extrema Preia o surs imagine Rendered, citete o regiune
specific din imagine i gsete valorile minime i
maxime ale valorilor pixelilor pentru fiecare band
din acea regiune de imagine. Datele imagine trec
prin acest operator nemodificate.
Histogram Preia o imagine surs Rendered, citete o regiune
specific din imagine i genereaz o histogram
bazndu-se pe valorile pixelilor din acea regiune de
imagine. Datele histogramei sunt stocate ntr-un
obiect de tip javax.media.jai.Histogram obinut de
la utilizator, acesta putndu-se obine printr-un apel
la metoda getProperty asupra acestei operaii cu
numele proprietii histogram. Valoarea de retur
va fi de tipul javax.media.jai.Histogram. Datele
imagine trec neschimbate prin aceast operaie.
Mean Preia o surs imagine Rendered, citete o regiune
specific i calculeaz valoarea medie pentru
fiecare band din interiorul unei regiuni dintr-o
imagine. Datele imagine trec neschimbate prin
40
aceast operaie.
Tabelul 7.13. Operatori statistici
41
Indiciile de reprezentare asociate cu aceast instan a JAI sunt
suprapuse cu indiciile furnizate la aceast metod, indiciile vor fi o uniune
dintre indiciile instanei i indiciile date prin parametru.
Numele operaiei descrie operatorul care va fi creat i este un string.
Blocul de parametrii conine sursa operaiei i un set de parametrii
utilizai de operaie. Coninutul blocului de parametri depinde de operaia care
se creeaz i poate fi doar numele imaginii surs sau poate conine toi
parametrii operatorului. Blocurile de parametrii ncapsuleaz toate informaiile
despre sursele i parametrii utilizai de operaie. Parametrii specificai de ctre
blocul de parametri sunt obiecte.
Aceste obiecte de control, parametri i surse, pot fi editate prin metoda
setParameterBlock pentru a afecta operaii specifice sau chiar structura lanului
de reprezetare. Modificrile afecteaz viitoarele obiecte RenderedImage
derivate din punctele lanului din aval de unde s-a fcut modificarea.
Exist dou clase separate pentru a specifica blocurile de parametrii:
java.awt.image.renderable.ParameterBlock clasa principal
pentru specificarea i schimbarea blocurilor de parametrii.
javax.media.jai.ParameterBlockJAI extinde ParameterBlock
prin permiterea utilizrii a valorilor implicite a parametrilor i
utilizrii numelor de parametrii.
Blocul de parametrii trebuie s conin acelai numr de surse i
parametri n funcie de necesitatea operaiei, cu excepia cnd se folosete
ParameterBlockJAI care furnizeaz valori implicite. Pentru unele operaii,
valorile implicite ale parametrilor nu sunt disponibile i de aceea ele trebuie
furnizate.
Sursele sunt adugate la blocul de parametrii cu metoda addSource. n
exemplul urmtor se creeaz un nou ParameterBlock numit pb i apoi metoda
addSource este utilizat la adugarea imaginii surs im0 la blocul de parametrii.
ParameterBlock pb = new ParameterBlock();
pb.addSource(im0);
Pentru adugarea a dou surse la un bloc de parametrii, se utilizeaz
dou apeluri la metoda addSource.
ParameterBlock pb = new ParameterBlock();
pb.addSource(im0);
pb.addSource(im1);
n cazul folosirii clasei ParameterBlock, parametrii operaiei sunt
adugai la ParameterBlock cu metoda ParameterBlock.add. Exemplul urmtor
adaug dou valori la obiectul ParameterBlock numit pb, care a fost creat n
exemplul anterior.
pb.add(150);
pb.add(200);
42
Metoda add poate fi utilizat cu toate tipurile de date suportate: byte,
short, integer, long, float i double. Atunci cnd se utilizeaz obiectul
ParameterBlock, toi parametrii pe care o operaie are nevoie trebuie s fie
adugai, altfel operaia va eua.
La utilizarea clasei ParameterBlockJAI, deoarece obiectul conine deja
valori implicite pentru parametrii la momentul construciei, parametrii trebuie
schimbai cu metodele ParameterBlockJAI.set(value, index).
Exemplul urmtor (Exemplul 7.12.) arat crearea unui Parameter-
BlockJAI cu intenia de a fi furnizat unei operaii de rotire. Operaia de rotire
preia patru parametrii: xOrigin, yOrigin, angle i interpolation. Valorile
implicite pentru xOrigin i yOrigin sunt 0.0F pentru amndou. n acest
exemplu, aceste dou valori nu sunt modificate, deoarece valorile implicite sunt
suficiente pentru operaie. Ceilali doi parametri (angle i interpolation) au
valoarea implicit null i astfel necesit modificarea valorilor. Imaginea surs
trebuie de asemenea specificat.
43
Clasa RenderingHints creeaz indicii de reprezentare specifice Java
AWT. Pentru a modifica indiciile de reprezentare, se creeaz un obiect
RenderingHints i se transmite unei metode JAI.create asupra creia dorim s
acioneze. Modificnd un indiciu de reprezentare nu se garanteaz c un anume
algoritm de reprezentare va fi folosit, deoarece nu toate platformele suport
modificarea codului de reprezentare.
n codul urmtor, indiciile de reprezentare sunt setate pe calitate.
qualityHints = new
RenderingHints(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
Odat ce un obiect RenderingHints a fost creat, indiciile pot fi utilizate
ntr-o operaie folosind o metod JAI.create.
Fiecare instan a unui obiect JAI conine un set de indicii de
reprezentare care va fi folosit pentru toate crerile de imagini sau colecii de
imagini. Indiciile sunt combinate cu orice alte indicii furnizate metodei
JAI.create. Indiciile furnizate direct au preceden asupra indicilor obinuite.
Atunci cnd o nou instan JAI este construit, indiciile ei sunt iniializate la o
copie a indiciilor asociate cu instana implicit. Indiciile asociate cu alte
instane, incluznd instana implicit, pot fi manipulate folosind metodele
getRenderingHints, setRenderingHints i clearRenderingHints. Pentru
manipularea individual a indiciilor se folosesc metodele getRenderingHint,
setRenderingHint i removeRenderingHint.
Codul urmtor (Exemplul 7.13.) este un exemplu de reprezentare a
unei imagini cu indicii de reprezentare pentru o operaie de scalare. Indiciul de
reprezentare specific originea imaginii destinaie modificat la 200x200.
44
7.4.2. Achiziia i afiarea imaginilor n JAI
45
setTitle(getClass().getName()+": "+fileName);
// afieaz imaginea
add(new ScrollingImagePanel(img, img.getWidth(),
img.getHeight()));
pack();
show();
}
}
(0,0,2) x
(0,0,1)
(0,0,0)
(x,y,2)
(x,y,1)
(x,y,0)
Figura 7.9. Structura unei imagini cu mai
multe benzi
46
n JAI API, unitatea de baz pentru stocarea imaginilor sunt obiectele
DataBuffer. Acestea sunt un fel de obiecte de stocare brute, care stocheaz toate
eantioanele din compoziia unei imagini, dar nu conin nici o informaie despre
felul cum aceste eantioane sunt organizate ca pixeli. Aceast informaie este
stocat ntr-un obiect SampleModel. Clasa SampleModel conine metode pentru
derivarea datelor pixel dintr-un DataBuffer.
JAI suport mai multe tipuri de date imagine, aa c clasa DataBuffer
are urmtoarele subclase, fiecare reprezentnd un tip diferit de date:
DataBufferByte stocheaz date intern ca i bytes (valori pe 8 bii).
DataBufferShort stocheaz date intern ca i short (valori pe 16 bii)
DataBufferUShort stocheaz date intern ca i unsigned short (valori
pe 16 bii)
DataBufferInt stocheaz date intern ca i ntregi (valori pe 32 bii)
DataBufferFloat stocheaz date intern ca i valori flotante n precizie
simpl.
DataBufferBuffer stocheaz date intern ca i valori flotante n
precizie dubl.
JAI suport i alte formate de date imagine, pe lng cele oferite de
pachetul java.awt.image (vezi paragraful 7.3.4.), dar clasa SampleModel
furnizeaz i urmtoarele tipuri de modele de eantioane:
ComponentSampleModelJAI utilizat la extragerea pixelilor din
imagini care stocheaz date eantion astfel nct fiecare eantion al
unui pixel ocup un element dat din DataBuffer.
FloatComponentSampleModel stocheaz n eantioane care formeaz
un pixel n n arii de elemente dat separate, toate acestea sunt stocate
n acelai segment a obiectului DataBuffer.
Combinaia dintre un obiect DataBuffer, un obiect SampleModel i un
element origine constituie o unitate de stocare a imaginilor de tip multi-pixel i
este concretizat prin clasa Raster (vezi paragraful 7.3.2.).
47
imaginii, originea, dimensiunea segmentului, deplasamentul grilei segmentului,
obiectele de tip Vector care pstreaz sursa i destinaia imaginii.
Toate obiectele care nu aparin JAI de tip RenderedImage, dar care se
utilizeaz n JAI trebuie convertite n PlanarImage prin mijloace oferite de
clasa RenderedImageAdapter i clasa WriteableRenderedImageAdapter.
java.awt.Image
implements
PlanarImage ImageJAI
TiledImage CollectionImage
SnapshotImage ImageSequence
RemoteImage ImageStack
ImageMIPMap
ImagePyramid
48
Segmentele formeaz o gril regulat care poate s ocupe orice
regiune dreptunghiular din plan. Segmentele de pixeli care depesc limitele
imaginii au valori nedefinite.
Coninutul unui obiect TiledImage este definit de o singur surs
PlanarImage, furnizat fie la momentul construciei fie cu ajutorul metodei set.
Metoda set asigur un mod de suprascriere selectiv a unei poriuni din
TiledImage.
TiledImage suport manipularea direct a pixelilor prin mijloacele
oferite de metoda getWriteableTile. Aceast metod returneaz un
WritableRaster care poate fi modificat direct.
Un alt mod de a modifica coninutul unui TiledImage este apelarea
metodei createGraphics. Aceast metod returneaz un obiect GraphicsJAI
care poate fi folosit pentru desenarea de grafic, text i imagini n manier
AWT.
TiledImage v-a cauza calcularea segmentelor sale doar atunci cnd
coninutul este solicitat. Odat ce un segment este calculat, coninutul su poate
fi eliminat dac se determin c poate fi recalculat n mod identic din surs.
Metoda lockTile foreaz calcularea unui segment i meninerea lui pe durata de
existen a obiectului TiledImage.
Interfaa TileCache. Aceast interfa este o zon cache comun
pentru segmentele calculate deinute de obiectele OpImage. Acest obiect care se
creeaz (de tipul TileCache) are o capacitate dat, msurat n segmente. n
mod implicit, capacitatea unui TileCache este 300 segmente. Capacitatea
implicit a memoriei rezervat pentru un obiect TileCache este 20M bytes.
Un obiect TileCache care va fi utilizat de o operaie anume poate fi
conceput n momentul construciei operaiei, sau printr-un apel la metoda
JAI.setTileCache. Aceasta face ca obiectul TileCache s fie adugat la setul de
indicii de reprezentare.
Interfaa TileScheduler permite segmentelor s fie programate pentru
calculare. n diferite implementri, calcularea segmentului se poate realiza prin
utilizarea de multithreading i conexiuni n reea multiple n mod simultan
pentru a mbunti performana.
Clasa SnapshotImage. Aceast clas reprezint componenta
principal a motorului de execuie amnat. Un SnapshotImage furnizeaz un
numr arbitrar de variante sincrone a unui posibil obiect WritableRendered-
Image care se modific. SnapshotImage este responsabil pentru stabilizarea
surselor care se modific pentru a permite execuia amnat a operaiilor
dependente de astfel de surse.
Orice RenderedImage poate fi utilizat ca surs pentru un Snapshot-
Image. Dac sursa este un WritableRenderedImage, SnapshotImage se va
nregistra ca TileObserver i va face copii pentru segmentele care sunt pe cale
s se modifice.
49
Mai multe versiuni ale fiecrui segment sunt pstrate intern, att timp
ct se cere. SnapshotImage permite monitorizarea acestor cereri i poate s
simplifice urmtoarele cereri pentru segmente, fr s fie nevoie s facem o
copie.
Atunci cnd se utilizeaz ca i surs, apelurile la metoda getTile vor fi
transmise spre surs, cu alte cuvinte obiectele SnapshotImage sunt complet
transparente. Prin apelul createSnapshot o instan a unei subclase
PlanarImage care nu este public va fi creat i returnat. Obiectul
PlanarImage va returna ntotdeauna segmente de imagini cu coninut ca i n
momentul construciei lui.
Clasa RemoteImage. Aceast clas este o subclas a PlanarImage
care reprezint o imagine pe un server distant. Un obiect RemoteImage poate fi
construit dintr-un RenderedImage sau dintr-un lan de procesare a imaginilor
care este fie de tip Rendered, fie Renderable.
Clasa CollectionImage. Aceast clas este o superclas abstract
pentru clasele care reprezint grupuri de imagini. Exemple de grupuri de
imagini sunt piramidele (ImagePyramid), secvenele temporale (TimeSequence)
i feliile plane suprapuse pentru a forma un volum (ImageStack).
Clasa ImageSequence. Aceast clas reprezint o secven de imagini
asociat cu nite indeci temporali i o poziie a camerei, cu scopul de a
reprezenta secvene video sau fotografie dependent de timp.
Imaginile sunt de tipul ImageJAI, indecii temporali sunt de tipul long,
iar poziiile camerei sunt de tipul Point. Acest triplet este reprezentat printr-un
obiect de tipul SequentialImage.
Clasa ImageStack. Clasa ImageStack reprezint o stiv de imagini,
fiecare cu o orientare spaial definit ntr-un sistem de coordonate.
Imaginile sunt de tipul PlanarImage, coordonatele sunt de tipul
javax.media.jai.Coordinate. Aceste date sunt reprezentate printr-un obiect
javax.media.jai.CoordinateImage.
Clasa ImageMIPMap. O imagine de tip hart MIP este o stiv de
imagini cu o relaie fix ntre feliile adiacente. Fiind dat felia cu cea mai mare
rezoluie, celelalte pot fi obinute prin derivare folosind operaii specifice.
Datele pot fi extrase felie cu felie sau prin iteratori speciali.
O imagine hart MIP (MIP vine din lmba latin multim im parvo
care nseamn multe lucruri n spaii mici) este similar cu o alocare de
textur. La alocarea texturilor, imaginea hart MIP conine versiuni de diferite
mrimi ale aceleiai imagini n aceeai locaie. Pentru utilizarea acestei alocri
a texturilor, trebuie furnizate toate mrimile imaginii n putere de 2 din cea mai
mare imagine la o hart de 1x1.
Clasa ImageMIPMap preia sursa original la cel mai mare nivel de
rezoluie, considerat a fi nivelul 0 i un lan RenderedOp care definete modul
50
n care imaginea de la nivelul de rezoluie imediat inferior este derivat din
nivelul de rezoluie curent.
Lanul RenderedOp poate s aib mai multe operaii, dar prima
operaie din lan trebuie s preia doar o singur imagine surs, care este
imaginea de la nivelul de rezoluie curent.
Clasa ImagePyramid. Aceast clas implementeaz o operaie
piramid (pyramid) asupra unui obiect RenderedImage. Prin aceast clas se
poate genera imagini adiionale prin medierea succesiv a unui bloc de 2x2
pixeli, fiecare dat se elimin toate celelalte coloane i rnduri de pixeli. De
exemplu, pentru o imagine de tip RenderedImage de 1024x1024, vom avea
imagini de 512x512, 256x256 i tot aa pn la 1x1.
n practic, imaginile de rezoluie mai mic pot fi derivate prin
execuia unui lan de operaii n mod repetat care subeantioneaz felia de
imagine cu rezoluie mai mare. n mod similar, odat ce o felie de imagine este
obinut, feliile de imagine cu rezoluia mai mare pot fi derivate prin execuia
unui alt lan de operaiuni n mod repetat care supraeantioneaz felia de
imagine cu rezoluia mai mic. De asemenea, un al treilea lan de operaii poate
fi folosit pentru gsirea diferenelor dintre felia original a imaginii i felia
rezultat obinut prin prima subeantionare apoi supraeantionnd felia
original.
Clasa MultiResolutionRenderableImage. Aceast clas produce
reprezentri bazate pe un set de obiecte RenderedImage de diferite rezoluii.
Obiectul este construit dintr-o dimensiune specificat i un vector de obiecte
RenderdImage care reprezint imagini cu rezoluii progresiv mai mici.
7.4.2.3. Streamuri
JAI API extinde tipurile de streamuri din Java prin adugarea de apte
clase de tip stream seekable (vezi Figura 7.11.). Tabelul 7.14. descrie pe
scurt fiecare dintre aceste noi clase.
InputStream
implements
SeekableStream DataInput
Clasa Descriere
SeekableStream Clas abstract care combin funcionalitile lui
InputStream i RandomAccessFile, cu abilitile
de a citi tipuri de date primitive n format little-
endian.
FileSeekableStream Furnizeaz funcionalitate SeekableStream
asupra datelor stocate ntr-un obiect File
ByteArraySeekable Implementeaz funcionalitate SeekableStream
Stream asupra datelor stocate ntr-o arie de bytes
SegmentedSeekable Furnizeaz informaii despre un subset al altui
Stream SeekableStream care conine o serie de segmente
cu o poziie de start dat n fluxul sursei i
lungime. Fluxul rezultat se comport ca i un
SeekableStream obinuit.
ForwardSeekable Furnizeaz funcionalitate SeekableStream
Stream asupra datelor dintr-un InputStream cu adugare
de date minim, dar nu permite cutri napoi.
Poate fi utilizat cu formate de intrare care
suport streaming, evitnd nevoia de a aduce n
avans (cache) datele de intrare.
FileCacheSeekable Furnizeaz funcionalitate SeekableStream
Stream asupra datelor dintr-un InputStream cu adugare
de date minim, dar nu permite cutri napoi.
Poate fi utilizat cu formate de intrare care
suport streaming, evitnd nevoia de a aduce n
avans (cache) datele de intrare. n circumstanele
n care nu permit crearea unui fiier temporar (de
exemplu, datorit securitii sau absena unui
disc local), poate fi utilizat MemoryCache-
SeekableStream.
MemoryCache Furnizeaz funcionalitate SeekableStream
52
SeekableStream asupra datelor dintr-un InputStream, folosind un
cache n memorie pentru a permite cutarea
napoi. Aceast clas se utilizeaz atunci cnd
securitatea sau lipsa accesului la un disc local nu
poate fi fcut cu FileCacheSeekableStream.
Tabelul 7.14. Clasele stream din JAI
53
acoper clasa File sau clasa RandomAccessFile i execut o operaie limitat de
aducere n avans a datelor (caching) pentru a evita operaiile I/O prea dese.
Metoda wrapInputStream este furnizat pentru a construi o instan
potrivit a SeekableStream a crui date sunt furnizate de un InputStream dat.
Cel care apeleaz, prin mijloace ale parametrului canSeekBackwards, determin
dac este necesar suportul pentru cutri n urm.
54
una din cele dou metode de recunoatere a fiierelor imagine. Codecul la
nceput apeleaz metoda getNumHeaderBytes, care fie returneaz 0 dac
accesul arbitrar la stream este necesar, sau returneaz numrul de bytes din
header necesari pentru a recunoate formatul. n funcie de ce returneaz
metoda getNumHeaderBytes, codorul citete streamul sau headerul.
Odat ce codecul a determinat formatul de imagine, prin metoda citirii
streamului sau cea a headerului, el returneaz numele codecului asociat cu
formatul de imagine detectat. Dac nu este nregistrat nici un codec cu acel
nume, se returneaz null. Numele codecului definete subclasa care este
apelat, care decodeaz imaginea.
Pentru cele mai multe tipuri de imagine, JAI ofer opiunea de a citi
fiierul cu date imagine ca obiect java.io.File sau ca una din subclasele de tipul
java.io.InputStream.
JAI ofer civa operatori de fiier pentru citirea fiierelor cu date
imagine, listai n Tebelul 7.16.
Operator Descriere
AWTImage Import o imagine AWT standard n JAI
BMP Citete date BMP dintr-un stream de intrare
FileLoad Citete o imagine dintr-un fiier
FPX Citete date FlashPix dintr-un stream de intrare
FPXFile Citete un fiier standard FlashPix
GIF Citete date GIF dintr-un stream de intrare
JPEG Citete un fiier standard JPEG (JFIF)
PNG Citete un stream de intrare PNG
PNM Citete un fiier standard PNM, inclusiv imagini
PBM, PGM i PPM n format ASCII sau brut.
Stream Citete obiecte de tip java.io.InputStream
TIFF Citete date TIFF 6.0 dintr-un stream de intrare.
URL Creeaz o imagine surs care este specificat de un
URL
Tabelul 7.16. Operatori pentru fiiere imagine
55
// exemplu de operaie fileload
// ncarc imaginea surs dintr-un fiier
RenderedImage src = (RenderedImage)JAI.create("fileload", fileName)
...
// exemplu de citire a unei imagini FPX
// specific numele fiierului
File file = new File(filename);
// specific rezoluia fiierului
ImageDecodeParam param = new FPXDecodeParam(resolution);
56
// creeaz operaia PNM
op = JAI.create("PNM", pb);
...
// exemplu de citire a unei imagini AWT
// creeaz ParameterBlock.
ParameterBlock pb = new ParameterBlock();
pb.add(image);
// creeaz o operaie AWTImage.
PlanarImage im = (PlanarImage)JAI.create("awtImage", pb);
...
// exemplu de citire a unei imagini de tip URL
// definete o imagine URL.
url = new URL("http://www/img/k.gif");
// citete imaginea de la URL-ul specificat.
RenderedOp src = JAI.create("url", url);
57
Renderable. De exemplu, pentru a folosi o imagine obinut de la un server
distant ntr-un lan Renderable, trebuie tratat imaginea surs ca i
RenderedImage, apoi convertit la RenderableImage pentru urmtoarele
procesri.
Operaia Renderable produce un obiect RenderableImage dintr-o surs
RenderedImage. Obiectul RenderableImage care este produs este format dintr-o
piramid de obiecte RenderedImage la rezoluii progresiv mai mici. Imaginile
cu rezoluiile mai mici sunt produse prin invocarea lanului de operaii
specificat prin parametrul downSampler asupra imaginii de la nivelul de
rezoluie imediat superior al piramidei. Lanul de operaii downSampler trebuie
s adere la specificaiile descrise pentru constructorii clasei ImageMIPMap,
care accept acest tip de parametru.
Numrul de nivele din piramid va fi astfel nct cea mai mare
dimensiune (lime sau nlime) a nivelului de piramid cu cea mai mic
rezoluie s fie mai mic sau egal cu valoarea parametrului maxLowResDim,
care trebuie s fie pozitiv. Valoarea implicit pentru maxLowResDim este 64,
ceea ce nseamn c nivelul de piramid cu rezoluia cea mai mic va fi
imaginea cu dimensiunea cea mai mare egal cu 64 pixeli sau mai mic.
Parametrii operaiei Renderable sunt descrii n Tabelul 7.17.
58
Exemplul 7.16. demonstreaz o operaie Renderable. Valorile
implicite sunt folosite pentru toi cei cinci parametrii ai operaiei. Rezultatul
operaiei poate fi transmis la urmtoarea operaie din graf.
59
Afiarea imaginilor n JAI poate fi fcut prin mai multe moduri.
Pentru nceput, apelul metodei drawRenderedImage asupra obiectului
Graphics2D poate fi folosit pentru a produce o reprezentare imediat. O alt
metod este instanierea unei componente de afiare care rspunde la cererile
utilizatorului cum ar fi derularea sau translatarea i de asemenea expunerea
evenimentelor i obinerea datelor imagine dintr-o surs RenderedImage.
Aceast tehnic permite ca datele imagine s fie calculate la cerere.
Pentru acest scop JAI furnizeaz o component de afiare, disponibil
n pachetul javax.media.jai.widget, numit ScrollingImagePanel. Aceast clas
preia un obiect RenderedImage i o lime i nlime specific i creeaz un
panou cu bare de derulare, iar imaginea este aezat n centrul panoului.
Odat ce ScrollingImagePanel este creat, acesta poate fi aezat
oriunde ntr-un Frame, la fel ca i orice alt panou din AWT. Exemplul 7.18.
demonstreaz utilizarea unui astfel de panou.
60
ColorModel descrie un mod particular prin care valorile pixelilor sunt
mapate la culori. Un obiect ColorModel este de obicei asociat cu un
obiect Image sau BufferedImage i furnizeaz informaia necesar
pentru a interpreta corect valorile pixelilor. Aceast clas este definit
n pachetul java.awt.image.
ColorSpace reprezint un sistem pentru msurarea culorilor, n mod
obinuit folosind trei valori sau componente separate. Clasa
ColorSpace conine metode pentru conversia ntre spaiul de culoare
original i una sau dou spaii de culoare standard, CIEXYZ i RGB.
Aceast clas este definit n pachetul java.awt.color.
Color reprezint o culoare fix, definit prin componentele sale ntr-
un obiect ColorSpace. Aceast clas este definit n pachetul java.awt.
Un obiect ColorModel este utilizat pentru interpretarea datelor pixel
dintr-o imagine. Aceasta include:
Maparea componentelor din benzile unei imagini la componentele unui
spaiu de culoare particular.
Extragerea componentelor pixelului din datele pixel mpachetate.
Obinerea de componente multiple dintr-o singur band folosind
mti.
Conversia datelor pixel printr-un tabel de cutare.
Pentru a determina valoarea culorii a unui pixel particular dintr-o
imagine, trebuie cunoscut modul n care informaia de culoare este codat n
fiecare pixel. Obiectul ColorModel asociat unei imagini ncapsuleaz datele i
metodele necesare pentru translatarea valorii unui pixel spre i de la
componentele sale de culoare constituente.
JAI suport cinci modele de culoare:
DirectColorModel lucreaz cu valorile pixelilor care reprezint
informaie despre culori RGB i canal alfa ca i eantioane separate i
mpacheteaz toate eantioanele pentru un singur pixel ntr-un singur
int, short, sau byte. Aceast clas poate fi utilizat doar cu spaii de
culoare de tipul ColorSpace.TYPE_RGB.
IndexColorModel lucreaz cu valorile pixelilor care reprezint un
singur eantion care este un index ntr-o hart de culori fix n spaiul
de culoare RGB implicit. Harta de culori specific componentele de
rou, verde, albastru i opional alfa corespunztoare pentru fiecare
index.
ComponentColorModel poate s manevreze un obiect arbitrar
ColorSpace i o arie de componente de culoare pentru a se potrivi cu
spaiul de culoare. Acest model poate fi folosit pentru a reprezenta cele
mai utilizate modele culoare pe cele mai utilizate dispozitive grafice
(GraphicsDevice).
61
PackedColorModel clas de baz pentru modele care reprezint
valorile pixelilor n care sunt ncorporate componentele de culoare n
mod direct n biii unui pixel ntreg. Un astfel de obiect stocheaz
informaia de mpachetare care descrie modul n care componentele de
culoare i alfa sunt extrase din canal. Obiectele DirectColorModel sunt
de tipul PackedColorModel.
FloatDoubleColorModel lucreaz cu valorile pixelilor care reprezint
informaie de culoare i alfa ca i eantioane separate, folosind
elemente float i double.
Urmtorul exemplu (Exemplul 7.19.) prezint construcia unui obiect
ComponentColorModel pentru un model de culoare RGB.
62
Operatori aritmetici
Efect de vibraie (dithering)
Fixarea (clamping) valorilor pixelilor
Copierea benzilor
63
este operaia NOT (complementare imagine) asupra fiecrui pixel a unei
imagini surs pe baza benzilor.
JAI suport urmtoarele operaii logice:
And preia rezultatul unei operaii pe bii AND asupra a dou
imagini surs i stocheaz rezultatul ntr-o destinaie.
AdConst preia rezultatul unei operaii pe bii AND asupra unei
imagini surs i a unei constante dintr-un set al benzilor.
Or - preia rezultatul unei operaii pe bii OR asupra a dou imagini
surs i stocheaz rezultatul ntr-o destinaie.
OrConst - preia rezultatul unei operaii pe bii OR asupra unei
imagini surs i a unei constante dintr-un set al benzilor.
Xor - preia rezultatul unei operaii pe bii XOR asupra a dou
imagini surs i stocheaz rezultatul ntr-o destinaie.
XorConst - preia rezultatul unei operaii pe bii XOR asupra unei
imagini surs i a unei constante dintr-un set al benzilor.
Not - preia rezultatul unei operaii pe bii NOT asupra fiecrui pixel
din benzi a unei imagini surs.
Asemenea operatorilor relaionali, operatorii logici necesit ca
amndou imaginile surs i imaginea destinaie s aib acelai tip de dat i
numr de benzi. Mrimea celor dou imagini (nlime i lime) poate s
difere.
Operatori aritmetici. JAI suport operatori aritmetici monadici i
diadici. Operaiile aritmetice monadice includ adunarea pe band, scderea,
divizarea i multiplicarea ntre o imagine surs i o constant pentru a produce
o imagine destinaie. Operaiile aritmetice diadice includ adunarea pe band,
scderea, divizarea i multiplicarea ntre dou imagini surs pentru a produce o
imagine destinaie.
JAI suport urmtorii operatori aritmetici:
Add adunarea a dou imagini surs i stocarea rezultatului n
imaginea destinaie
AddConst adunarea unei valori constante la pixelii dintr-o imagine
surs i stocarea rezultatelor ntr-o imagine destinaie.
AddCollection adun o colecie de imagini i stocheaz rezultatele
ntr-o imagine destinaie.
AddConstToCollection adun o arie de constante double la o
colecie de imagini Rendered.
Substract scade o imagine surs din alta i stocheaz rezultatele
ntr-o imagine destinaie.
SubstractConst scade o valoare constant din pixelii unei imagini
surs i stocheaz rezultatele ntr-o imagine destinaie.
Divide mparte o imagine surs cu alta i stocheaz rezultatele
ntr-o imagine destinaie.
64
DivideComplex mparte dou imagini surs cu date complexe i
stocheaz rezultatele ntr-o imagine destinaie.
DivideByConst mparte o imagine surs cu o valoare constant.
Multiply nmulete dou imagini surs i stocheaz rezultatele
ntr-o imagine destinaie.
MultiplyConst nmulete o imagine surs cu o valoare constant.
MultiplyComplex nmulete dou imagini reprezentnd date
complexe.
Absolute gsete valoarea absolut a pixelilor ntr-o imagine surs
i stocheaz rezultatele ntr-o imagine destinaie.
Exp preia exponentul unei imagini i stocheaz rezultatele ntr-o
imagine destinaie.
Asemenea operatorilor relaionali i logici, operatorii aritmetici
necesit ca amndou imaginile surs i destinaie s aib acelai tip de dat i
numr de benzi. Mrimea celor dou imagini (nlime i lime) poate s
difere.
Atunci cnd JAI adun dou imagini, preia valoarea de la locaia 0,0
dintr-o imagine surs, adun la valoarea de la locaia 0,0 din cea de-a doua
imagine surs i scrie suma n imaginea destinaie la locaia 0,0. Pentru toate
celelalte puncte din imagine se procedeaz la fel. Scderea, nmulirea i
mprirea sunt tratate n mod similar.
Operaiile aritmetice asupra imaginilor cu mai multe benzi se execut
pe benzile corespunztoare din imaginile surs.
Efect de vibraie (dithering). Afiarea unei imagini color de 24 bii pe
un bufer cadru de 8 bii necesit o operaie numit dithering. Aceast operaie
comprim cele trei benzi ale unei imagini RGB la o imagine byte cu o singur
band.
Operaia dithering utilizeaz un tabel de cutare prin care imaginea
surs este trecut pentru a produce imaginea destinaie. Cea mai utilizat
facilitate ale acestei operaii este conversia imaginilor true-color (byte cu trei
benzi) n imagini pseudocolor (byte cu o singur band).
Fixarea (clamping) valorilor pixelilor. Operaia clamp restricioneaz
intervalul valorilor pixelilor pentru o imagine surs prin restrngerea
intervalului pixelilor la valori low i high definite. Operaia preia o imagine
surs Rendered sau Renderable i seteaz toi pixelii a cror valoare este sub o
valoare inferioar la acea valoare inferioar i toi pixelii a cror valoare este
peste o valoare superioar la acea valoare superioar. Pixelii a cror valoare
este ntre valoarea inferioar i valoarea superioar sunt lsai nemodificai.
Copierea benzilor. Operaia BandSelect alege N benzi din o imagine
surs Rendered sau Renderable i copiaz datele pixelilor ale acestor benzi la
imaginea destinaie n ordinea specificat.
65
7.4.3.2. mbuntirea imaginilor
66
double[] lowValue = new double[numBands];
double[] highValue = new double[numBands];
for(int i = 0; i < numBands; i++) {
numBins[i] = binCount;
lowValue[i] = 0.0;
highValue[i] = 255.0;
}
// creeaz un obiect Histogram.
Histogram hist = new Histogram(numBins, lowValue, highValue);
ROIShape roi;
if(frame.isGotSelected())// specific ROI
roi = frame.getSelection();
else
roi = new ROIShape(img.getBounds());
// creeaz o operaie histogram.
RenderedOp histImage = JAI.create("histogram", img, hist, roi,
new Integer(1), new Integer(1));
// creeaz un CDF (cumulative distribution function) pentru egalizare
float[][] CDFeq = new float[numBands][];
for(int b = 0; b < numBands; b++) {
CDFeq[b] = new float[binCount];
for(int i = 0; i < binCount; i++) {
CDFeq[b][i] = (float)(i+1)/(float)binCount;
}
}
// creeaz o imagine cu histograma egalizat
frame.setImage(JAI.create("matchcdf", histImage, CDFeq, roi));
67
Intrare Ieire
0 0
1 16
2 23
3 28
... ...
253 254
254 255
255 255
Tabelul 7.18. Exemplu de tabel de cutare
68
int i;
// iniializarea tabelei de cutare
for ( i = 0; i < 256; i++ ) {
lut[0][i] = (byte)i;
lut[1][i] = (byte)0;
lut[2][i] = (byte)0;
}
for ( i = 0; i < 256; i++ ) {
int red = (int)lut[0][i]&0xFF;
int green = (int)lut[1][i]&0xFF;
int blue = (int)lut[2][i]&0xFF;
newlut[0][i] = clamp(red + brightness);
newlut[1][i] = clamp(green + brightness);
newlut[2][i] = clamp(blue + brightness);
}
// creeaz tabela de cutare
LookupTableJAI lookup = new LookupTableJAI(newlut);
ParameterBlock pb = new ParameterBlock();
pb.addSource(image);
pb.add(lookup);
// aplic operaia de cutare n tabel
PlanarImage dst = JAI.create("lookup", pb, null);
}
...
final private byte clamp(int v) {
if ( v > 255 ) {
return (byte)255;
} else if ( v < 0 ) {
return (byte)0;
} else {
return (byte)v;
}
}
69
Filtrarea median. Un filtru median este utilizat pentru a elimina
zgomotul de impuls din imagine i de a netezi imaginea.
Efectul de reducere a zgomotului pe care l are filtrul median asupra
imaginii depinde de extinderea spaial a vecintii (masca) i numrul de
pixeli implicai n procesare. Operaia MedianFilter suport trei forme de mti
diferite: ptrat, plus i form de X.
70
Clasa RenderableGraphics este o implementare a Graphics2D cu
semnificaie de RenderableImage. Aceast clas permite stocarea unei secvene
de comenzi de desenare i replicarea la o rezoluie de ieire arbitrar.
Metodele clasei RenderableGraphics rescriu metodele din clasele
Graphics i Graphics2D. Acest lucru nseamn c se pot utiliza metode n
RenderableGraphics pentru a aplica culori i fonturi, pentru a crea forme
grafice i text, etc.
Clasa Graphics2D permite desenarea de linii, forme geometrice,
imagini i text. Aceste obiecte pot fi pictate deasupra unui TiledImage.
71
Numrul portului este opional i trebuie s fie furnizat doar dac
numele calculatorului gazd a fost furnizat. Dac parametrul serverName este
null, n mod implicit se va cuta serviciul RMIImage de pe calculatorul local de
la portul rmiregistry (implicit 1099).
72
import java.awt.*;
import java.awt.event.WindowEvent;
import java.awt.geom.*;
import java.awt.image.*;
import java.awt.image.renderable.*;
import java.util.*;
import javax.media.jai.*;
import javax.media.jai.operator.*;
import javax.media.jai.widget.*;
public class RemoteImagingTest extends WindowContainer {
/** Serverul distant implicit. */
private static final String DEFAULT_SERVER =
"utcluj.ro:1099";
/** dimensiunile segmentelor. */
private static final int TILE_WIDTH = 256;
private static final int TILE_HEIGHT = 256;
public static void main(String args[]) {
String fileName1 = null;
String fileName2 = null;
// verific argumentele
if(!(args.length >= 0 && args.length <= 3)) {
System.out.println("\nUsage: java RemoteImagingTest "+
"[[[serverName] | [fileName1 fileName2]] | "+
"[serverName fileName1 fileName2]]"+"\n");
System.exit(1);
}
// configureaz numele serverului.
String serverName = null;
if(args.length == 0 || args.length == 2) {
serverName = DEFAULT_SERVER;
System.out.println("\nUsing default server '"+
DEFAULT_SERVER+"'\n");
} else {
serverName = args[0];
}
// seteaz numele fiierelor.
if(args.length == 2) {
fileName1 = args[0];
fileName2 = args[1];
} else if(args.length == 3) {
fileName1 = args[1];
fileName2 = args[2];
73
} else {
fileName1 = "/pic1.tif";
fileName2 = "/pic2.tif";
System.out.println("\nUsing default images '"+
fileName1 + "' and '" + fileName2 + "'\n");
}
RemoteImagingTest riTest =
new RemoteImagingTest(serverName, fileName1, fileName2);
}
/**
* ruleaz un test de procesare a imaginilor distant.
*
* @param serverName numele serverului distant
* @param fileName1 prima imagine adugat.
* @param fileName2 a doua imagine adugat.
*/
RemoteImagingTest(String serverName, String fileName1, String
fileName2) {
// creeaz operaiile pentru ncrcarea imaginilor din fiiere.
RenderedOp src1 = JAI.create("fileload", fileName1);
RenderedOp src2 = JAI.create("fileload", fileName2);
// proceseaz sursele fr a nghea nodurile.
PlanarImage ren1 = src1.createInstance();
PlanarImage ren2 = src2.createInstance();
// creaz obiecte TiledImage cu fiierele imaginile ca surse
// avnd grij ca imaginile serializate sunt cu adevrat segmentate.
SampleModel sampleModel1 =
ren1.getSampleModel().createCompatibleSampleModel(
TILE_WIDTH, TILE_HEIGHT);
TiledImage ti1 = new TiledImage(ren1.getMinX(), ren1.getMinY(),
ren1.getWidth(), ren1.getHeight(), ren1.getTileGridXOffset(),
ren1.getTileGridYOffset(), sampleModel1, ren1.getColorModel());
ti1.set(src1);
SampleModel sampleModel2 =
ren2.getSampleModel().createCompatibleSampleModel(
TILE_WIDTH, TILE_HEIGHT);
TiledImage ti2 = new TiledImage(ren2.getMinX(),
ren2.getMinY(), ren2.getWidth(), ren2.getHeight(),
ren2.getTileGridXOffset(), ren2.getTileGridYOffset(),
sampleModel2, ren2.getColorModel());
ti2.set(src2);
// creaz un indiciu care specific dimansiunea segmenului.
74
ImageLayout layout = new ImageLayout();
layout.setTileWidth(TILE_WIDTH).setTileHeight(TILE_HEIGHT);
RenderingHints rh = new
RenderingHints(JAI.KEY_IMAGE_LAYOUT, layout);
// rescaleaz imaginile n intervalul [0, 127].
ParameterBlock pb = (new ParameterBlock());
pb.addSource(ti1);
pb.add(new double[] {0.5}).add(new double[] {0.0});
RenderedOp addend1 = JAI.create("rescale", pb, rh);
pb = (new ParameterBlock());
pb.addSource(ti2);
pb.add(new double[] {0.5}).add(new double[] {0.0});
RenderedOp addend2 = JAI.create("rescale", pb, rh);
// adun imaginile rescalate.
pb = (new
ParameterBlock()).addSource(addend1).addSource(addend2);
RenderedOp sum = JAI.create("add", pb, rh);
// adaug un efect de vibraie (dither)
// sumei imaginilor rescalate.
pb = (new ParameterBlock()).addSource(sum);
pb.add(ColorCube.BYTE_496).add(KernelJAI.DITHER_MASK_443);
RenderedOp dithered = JAI.create("ordereddither", pb, rh);
// Construiete un obiect RemoteImage din lanul RenderedOp.
RemoteImage remoteImage = new RemoteImage(serverName,
sum);
// definete segmentul de afiare i modelul de fereastr.
setTitle(getClass().getName());
setLayout(new GridLayout(2, 2));
// reprezentare local
add(new ScrollingImagePanel(sum,
sum.getWidth(), sum.getHeight()));
// reprezentare distant RenderedOp.
add(new ScrollingImagePanel(remoteImage,
remoteImage.getWidth(), remoteImage.getHeight()));
// reprezentare distant RenderedImage
PlanarImage sumImage = sum.getRendering();
remoteImage = new RemoteImage(serverName, sumImage);
add(new ScrollingImagePanel(remoteImage,
remoteImage.getWidth(), remoteImage.getHeight()));
// reprezentare distant RenderableOp.
pb = new ParameterBlock();
pb.addSource(dithered);
75
RenderableOp absImage = JAI.createRenderable("absolute",pb);
pb = new ParameterBlock();
pb.addSource(absImage).add(ColorCube.BYTE_496);
RenderableOp lutImage = JAI.createRenderable("lookup", pb);
AffineTransform tf =
AffineTransform.getScaleInstance(384/dithered.getWidth(),
256/dithered.getHeight());
Rectangle aoi = new Rectangle(128, 128, 384, 256);
RenderContext rc = new RenderContext(tf, aoi, rh);
remoteImage = new RemoteImage(serverName, lutImage, rc);
add(new ScrollingImagePanel(remoteImage,
remoteImage.getWidth(), remoteImage.getHeight()));
// la sfrit afim totul
pack();
show();
}
}
76
System.out.println("Creeaz dst1 = log(invert(fileload("+
fileName+"))) n "+node1);
RenderedOp src = JAI.create("fileload", fileName);
RenderedOp op1 = JAI.create("invert", src);
RenderedOp op2 = JAI.create("log", op1);
RemoteImage rmt1 = new RemoteImage(node1, op2);
// creeaz un lan n nodul 2.
System.out.println("Creeaz dst2 = not(exp(dst1)) n "+node2);
RenderedOp op3 = JAI.create("exp", rmt1);
RenderedOp op4 = JAI.create("not", op3);
RemoteImage rmt2 = new RemoteImage(node2, op4);
// afieaz rezultatele pentru nodul 2.
System.out.println("Afieaz rezultate");
setTitle(getClass().getName()+" "+fileName);
add(new ScrollingImagePanel(rmt2, rmt2.getWidth(),
rmt2.getHeight()));
pack();
show();
}
}
grant {
77
// Permite orice de acum nainte.
permission java.security.AllPermission;
};
$ CLASSPATH=$JAI/lib/jai.jar:\
$JAI/lib/mlibwrapper_jai.jar
$ export CLASSPATH
$ LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$JAI/lib
$ export LD_LIBRARY_PATH
$ java \
-Djava.rmi.server.codebase=\
file:$JAI/lib/jai.jar \
-Djava.rmi.server.useCodebaseOnly=false \
-Djava.security.policy=file:$JAI/policy \
com.sun.media.jai.rmi.RMIImageImpl
78
parametrul serverName al oricrui constructor RemoteImage trebuie s fie
myserver.
79
if(args[i].equalsIgnoreCase("-image")) {
imagePath = args[++i];
if(!(imagePath.toLowerCase().endsWith(".fpx")))
imagePath += ".fpx";
}
}
String url = SERVER + "FIF=" + imagePath;
new IIPTest(url);
}
80
pb.set("x", 10); // axa oglinzii
// rmne: profilul ICC implicit
// calitatea JPEG implicit
// tabela index JPEG implicit
int height = DEFAULT_HEIGHT;
AffineTransform at = AffineTransform.getScaleInstance(
height*aspectRatioSource, height);
RenderContext rc = new RenderContext(at);
// creeaz un obiect RenderableImage.
RenderableImage renderable =
JAI.createRenderable("iip", pb);
}
}
81
String url = SERVER + "FIF=" + imagePath;
new IIPResolutionTest(url, resolution);
}
82
Pentru a coda n format BMP se poate utiliza operaia BMP mpreun
cu ali parametrii de codare (versiune BMP, modul de aezare a datelor n
fiier), ceea ce se exemplific n Exemplul 7.27.
83
1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,
};
...
File f; // fiierul n care se va stoca imaginea
PlanarImage img; // imaginea surs
...
// OutputStream-ul spre care se scrie
FileOutputStream fos = new FileOutputStream(f);
// clas JAI, specific diferii parametrii de codare JPEG
JPEGEncodeParam encodeParam = new JPEGEncodeParam();
// creeaz un nou tabel de cuantizare
encodeParam.setQTable(0, 1, qTable);
encodeParam.setQTable(1, 1, qTable);
encodeParam.setQTable(2, 1, qTable);
// tabelul de cuantizare pentru datele de luminan
encodeParam.setLumaQTable(qTable);
// tabelul de cuantizare pentru datele de crominan
encodeParam.setChromaQTable(qTable);
// creaz un nou tabel de cuantizare i l nlocuiete pe cel existent
// i configureaz nivelul de calitate a imaginii
encodeParam.setQuality(0.87F);
// subeantionare pe orizontal aplicat pentru fiecare band
encodeParam.setHorizontalSubsampling(0, 1);
encodeParam.setHorizontalSubsampling(1, 1);
encodeParam.setHorizontalSubsampling(2, 2);
// subeantionare pe vertical aplicat pentru fiecare band
encodeParam.setVerticalSubsampling(0, 1);
encodeParam.setVerticalSubsampling(1, 1);
encodeParam.setVerticalSubsampling(2, 2);
// specific intervalul de restart n Minimum Coded Units (MCU)
encodeParam.setRestartInterval(res);
// scrie doar imaginea i nu scrie tabelele (JPEG abreviat)
encodeParam.setWriteTablesOnly(false);
encodeParam.setWriteImageOnly(true);
// scrie headerul JFIF
encodeParam.setWriteJFIFHeader(true);
// creeaz un codor JPEG
ImageEncoder encoder = ImageCodec.createImageEncoder(
"JPEG", fos, encodeParam);
encoder.encode(img); // codeaz JPEG i scrie spre OutputStream
fos.close();
84
n Exemplul 7.29. se prezint codarea unei imagini n format PNG
folosind o codare pe 16 bii i ntreesere Adam7.
85
// codeaz imaginea apoi o scrie n fiier
enc.encode(img);
fos.close();
86
Toate extensiile la JAI necesit adugarea de noi clase. Toate clasele
trebuie grupate n pachete ca mod de organizare eficient i pentru separare a
acestora de pachetele oferite de alii.
Pentru a extinde JAI API prin crearea de noi operaii, este nevoie s
scriem o nou subclas a OpImage. Aceasta se poate face prin subclasarea a
uneia sau mai multe clase utilitare pentru a automatiza unele dintre detaliile a
operatorului pe care dorim s-l implementm.
Odat creai, noii operatori pot fi fcui disponibili pentru utilizatori n
mod transparent i fr modificarea codului surs de la utilizator, folosind
mecanismul de regitrii JAI.
Pentru a crea un nou operator, trebuie create urmtoarele clase:
O clas care extinde clasa OpImage sau oricare dintre subclasele
acesteia. Aceast nou clas este cea care execut procesarea.
O clas care extinde clasa OperationDescriptor. Aceast nou
clas descrie operaia prin nume, list de parametrii, etc.
O clas care implementeaz java.awt.image.renderable.Rendered-
ImageFactory, dac operatorul va funciona doar n modul
Rendered.
Operaiile care sunt create folosind una dintre metodele JAI.create
trebuie definite n registryFile, care este inclus n arhiva jai_core.jar. Fiecare
operaie are asociat un obiect OperationDesciptor (marcat prin odesc n
registryFile), care furnizeaz o descriere textual a operaiei i specific
numrul i tipul sursei precum i parametrii. Acest descriptor specific de
asemenea dac operaia suport modul Rendered, sau Renderable, sau
amndou.
Toate numele de operaii de nivel nalt (de exemplu, Rotate, Convolve
i AddConst) sunt mapate la instane de tipul RenderedImageFactory (RIF)
i/sau ContextualRenderedImageFactory (CRIF) care sunt capabile de
instanierea de lanuri OpImage pentru execuia operaiei specificate. Obiectele
RIF sunt utilizate pentru operaii n modul Rendered, iar obiectele CRIF sunt
utilizate pentru operaii n modul Renderable sau n modurile Rendered i
Renderable.
Pentru evitarea problemelor asociate cu editarea direct a registryFile
i rempachetarea lui, se pot nregistra obiectele OperationDescriptor, RIF i
CRIF utiliznd metodele registerOperationDescription, registerRIF i
registerCRIF din clasa OperationRegistry. Singurul dezavantaj al acestei
metode de nregistrare este faptul c noul operator nu va fi n mod automat
rencrcat de fiecare dat cnd un program JAI este executat, deoarece operaia
87
nu este nregistrat n registryFile. Noua operaie va trebui nregistrat de
fiecare dat nainte de a putea fi folosit.
Pentru a nregistra temporar o nou operaie trebuie parcuri urmtorii
pai:
1. nregistrarea numelui operaiei
Numele operaiei la nivel nalt, denumit i operation descriptor
(descriptor de operaie), este nregistrat printr-un apel la metoda
registerOperationByName sau la metoda registerOperationDescriptor.
Numele descriptorului de operaie trebuie s fie unic.
Odat ce un descriptor de operaie este nregistrat, acestea pot fi
obinute prin nume prin apelul metodei getOperationDescriptor.
88
PlanarImage img = JAI.create("MyThreshold", pb, renderHints);
...
/**
* O clas de tipul OperationDescriptor i RenderedImageFactory
* i o clas de tipul OpImage pentru crearea unei
* operaieii threshold modificat.
*/
public class MyThresholdDescriptor extends OperationDescriptorImpl
implements RenderedImageFactory {
/**
* stringuri resurs care furnizeaz informaii
* generale despre operaie
*/
private static final String[][] resources = {
{"GlobalName", "MyThreshold"},
{"LocalName", "MyThreshold"},
{"Vendor", "to.go.hfovi"},
{"Description", "A operation that thresholds source pixels"},
{"DocURL", "http://www.geocities.com/hfovi/projects/jai.html"},
{"Version", "1.0"},
{"arg0Desc", "param1"},
{"arg1Desc", "param2"}
};
/**
* Numele parametrilor pentru operaia MyThreshold.
*/
private static final String[] paramNames = {
"param1", "param2"
};
/**
* Tipurile de clase pentru parametrii.
*/
private static final Class[] paramClasses = {
java.lang.Integer.class, java.lang.Integer.class
};
/**
* Parametrii implicii
*/
private static final Object[] paramDefaults = {
new Integer(0), new Integer(255)
};
/** Constructorul. */
89
public MyThresholdDescriptor() {
super(resources, 1, paramClasses, paramNames, paramDefaults);
}
/**
* creeaz un MyThresholdOpImage cu ParameterBlock dat dac
* MyThresholdOpImage accept acest ParameterBlock.
*/
public RenderedImage create(ParameterBlock paramBlock,
RenderingHints renderHints) {
if (!validateParameters(paramBlock)) {
return null;
}
return new MyThresholdOpImage(paramBlock.getRenderedSource(0),
new ImageLayout(),
(Integer)paramBlock.getObjectParameter(0),
(Integer)paramBlock.getObjectParameter(1));
}
/**
* verific dac toi parametrii din ParameterBlock au
* tipul corect nainte de construirea MyThresholdOpImage
*/
public boolean validateParameters(ParameterBlock paramBlock) {
for (int i = 0; i < this.getNumParameters(); i++) {
Object arg = paramBlock.getObjectParameter(i);
if (arg == null) {
return false;
}
if (!(arg instanceof Integer)) {
return false;
}
}
return true;
}
}
/**
* MyThresholdOpImage este o extensie a PointOpImage care preia
* doi parametri ntregi i o surs i execut threshold asupra sursei
*/
class MyThresholdOpImage extends PointOpImage {
private int param1;
private int param2;
/**
90
* Construiete un MyThresholdOpImage.
*/
public MyThresholdOpImage(RenderedImage source,
ImageLayout layout, Integer param1,
Integer param2) {
super(source, null, layout, true);
this.param1 = param1.intValue();
this.param2 = param2.intValue();
}
/**
* Execut o operaie threshold modificat asupra pixelilor n
* suprafaa dreptunghiular dat. Valorile eantioanelor sub o
* limit inferioar sunt limitate la 0, n timp ce acele peste o limit
* superioar sunt limitate la 255. Rezultatele sunt returnate n
* WritableRaster ca destinaie.
*/
protected void computeRect(Raster[] sources,
WritableRaster dest,
Rectangle destRect) {
Raster source = sources[0];
Rectangle srcRect = mapDestRect(destRect, 0);
// RasterAccessor este un mod convenabil pentru reprezentarea
// oricrui Raster ntr-un format utilizabil. Acesta cere foarte puine
// resurse dac substratul Raster este ntr-un format obinuit.
RasterFormatTag[] formatTags = getFormatTags();
RasterAccessor srcAccessor =
new RasterAccessor(sources[0], srcRect, formatTags[0],
getSource(0).getColorModel());
RasterAccessor dstAccessor =
new RasterAccessor(dest, destRect, formatTags[1],
getColorModel());
switch (dstAccessor.getDataType()) {
case DataBuffer.TYPE_BYTE:
byteLoop(srcAccessor,dstAccessor);
break;
case DataBuffer.TYPE_INT:
intLoop(srcAccessor,dstAccessor);
break;
default:
String className = this.getClass().getName();
throw new RuntimeException(className +
" nu implementeaz computeRect" +
91
" pentru date short/float/double");
}
if (dstAccessor.isDataCopy()) {
dstAccessor.clampDataArrays();
dstAccessor.copyDataToRaster();
}
}
/**
* Calculeaz o arie dintr-un Raster tip byte folosind o surs
* RasterAccessor i o destinaie RasterAccesor.
*/
private void byteLoop(RasterAccessor src, RasterAccessor dst) {
int dwidth = dst.getWidth();
int dheight = dst.getHeight();
int dnumBands = dst.getNumBands();
byte dstDataArrays[][] = dst.getByteDataArrays();
int dstBandOffsets[] = dst.getBandOffsets();
int dstPixelStride = dst.getPixelStride();
int dstScanlineStride = dst.getScanlineStride();
byte srcDataArrays[][] = src.getByteDataArrays();
int srcBandOffsets[] = src.getBandOffsets();
int srcPixelStride = src.getPixelStride();
int srcScanlineStride = src.getScanlineStride();
byte bp1 = (byte)(param1 & 0xff);
byte bp2 = (byte)(param2 & 0xff);
for (int k = 0; k < dnumBands; k++) {
byte dstData[] = dstDataArrays[k];
byte srcData[] = srcDataArrays[k];
int srcScanlineOffset = srcBandOffsets[k];
int dstScanlineOffset = dstBandOffsets[k];
for (int j = 0; j < dheight; j++) {
int srcPixelOffset = srcScanlineOffset;
int dstPixelOffset = dstScanlineOffset;
for (int i = 0; i < dwidth; i++) {
int pixel = srcData[srcPixelOffset] & 0xff;
if (pixel < param1) {
dstData[dstPixelOffset] = 0;
} else if (pixel > param2) {
dstData[dstPixelOffset] = (byte)255;
} else {
dstData[dstPixelOffset] = srcData[srcPixelOffset];
}
92
srcPixelOffset += srcPixelStride;
dstPixelOffset += dstPixelStride;
}
srcScanlineOffset += srcScanlineStride;
dstScanlineOffset += dstScanlineStride;
}
}
}
/**
* Calculeaz o arie dintr-un Raster de tip int folosind o surs
* RasterAccessor i o destinaie RasterAccesor.
*/
private void intLoop(RasterAccessor src, RasterAccessor dst) {
int dwidth = dst.getWidth();
int dheight = dst.getHeight();
int dnumBands = dst.getNumBands();
int dstDataArrays[][] = dst.getIntDataArrays();
int dstBandOffsets[] = dst.getBandOffsets();
int dstPixelStride = dst.getPixelStride();
int dstScanlineStride = dst.getScanlineStride();
int srcDataArrays[][] = src.getIntDataArrays();
int srcBandOffsets[] = src.getBandOffsets();
int srcPixelStride = src.getPixelStride();
int srcScanlineStride = src.getScanlineStride();
for (int k = 0; k < dnumBands; k++) {
int dstData[] = dstDataArrays[k];
int srcData[] = srcDataArrays[k];
int srcScanlineOffset = srcBandOffsets[k];
int dstScanlineOffset = dstBandOffsets[k];
for (int j = 0; j < dheight; j++) {
int srcPixelOffset = srcScanlineOffset;
int dstPixelOffset = dstScanlineOffset;
for (int i = 0; i < dwidth; i++) {
int pixel = srcData[srcPixelOffset];
if (pixel < param1) {
dstData[dstPixelOffset] = 0;
} else if (pixel > param2) {
dstData[dstPixelOffset] = 255;
} else {
dstData[dstPixelOffset] = srcData[srcPixelOffset];
}
srcPixelOffset += srcPixelStride;
93
dstPixelOffset += dstPixelStride;
}
srcScanlineOffset += srcScanlineStride;
dstScanlineOffset += dstScanlineStride;
}
}
}
}
94
7.5. Bibliografie
95