Statistics
| Revision:

root / trunk / docs / Cresques / Cresques.html @ 11445

History | View | Annotate | Download (48.4 KB)

1 2248 igbrotru
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
2
<HTML>
3
<HEAD>
4
        <META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=iso-8859-15">
5 2732 nacho
        <TITLE>Cresques</TITLE>
6 2248 igbrotru
        <META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.0  (Linux)">
7
        <META NAME="CREATED" CONTENT="20050622;16400400">
8 2845 nacho
        <META NAME="CHANGED" CONTENT="20050901;10340300">
9 2248 igbrotru
        <STYLE>
10
        <!--
11
                @page { size: 21cm 29.7cm; margin-left: 2cm; margin-right: 1.06cm; margin-top: 1.06cm; margin-bottom: 1.06cm }
12
                TD P { color: #676767; font-family: "Verdana", "Arial", "Helvetica", sans-serif; font-size: 9pt; font-style: normal; text-align: justify }
13
                P { font-family: "Verdana", "Arial", "Helvetica", sans-serif; font-size: 9pt; text-align: justify }
14
                PRE { margin-left: 5cm }
15
                A:link { color: #e86d26; font-family: "Verdana", "Arial", "Helvetica", sans-serif; font-size: 9pt; font-style: normal }
16
        -->
17
        </STYLE>
18
</HEAD>
19
<BODY LANG="es-ES" LINK="#e86d26" DIR="LTR">
20
<TABLE WIDTH=600 BORDER=0 CELLPADDING=2 CELLSPACING=0 STYLE="page-break-before: always">
21
        <COL WIDTH=30>
22
        <COL WIDTH=562>
23
        <TR>
24
                <TD WIDTH=30>
25
                        <P>&nbsp;</P>
26
                </TD>
27
                <TD WIDTH=562 BGCOLOR="#e86d26">
28 2732 nacho
                        <P><A HREF="#Intro"><SPAN STYLE="background: #e86d26"><B><FONT COLOR="#ffffff">1.
29 2248 igbrotru
                        Introducci&oacute;n</FONT></B></SPAN></A></P>
30
                </TD>
31
        </TR>
32
        <TR>
33
                <TD WIDTH=30>
34 2732 nacho
                        <P><BR>
35
                        </P>
36
                </TD>
37
                <TD WIDTH=562 BGCOLOR="#e86d26">
38
                        <P><A HREF="#Filtros"><SPAN STYLE="background: #e86d26"><B><FONT COLOR="#ffffff">2.Drivers</FONT></B></SPAN></A></P>
39
                </TD>
40
        </TR>
41
        <TR>
42
                <TD WIDTH=30>
43
                        <P><BR>
44
                        </P>
45
                </TD>
46
                <TD WIDTH=562>
47
                        <P>&nbsp;&nbsp;&nbsp; <A HREF="#DLectura">2.1 Drivers de lectura</A></P>
48
                </TD>
49
        </TR>
50
        <TR>
51
                <TD WIDTH=30>
52
                        <P><BR>
53
                        </P>
54
                </TD>
55
                <TD WIDTH=562>
56
                        <P>&nbsp;&nbsp;&nbsp; <A HREF="#DEscritura">2.2 Drivers de
57
                        escritura</A></P>
58
                </TD>
59
        </TR>
60
        <TR>
61
                <TD WIDTH=30>
62 2248 igbrotru
                        <P>&nbsp;</P>
63
                </TD>
64
                <TD WIDTH=562 BGCOLOR="#e86d26">
65 2732 nacho
                        <P><A HREF="#Filtros"><SPAN STYLE="background: #e86d26"><B><FONT COLOR="#ffffff">3.Filtros</FONT></B></SPAN></A></P>
66 2248 igbrotru
                </TD>
67
        </TR>
68
        <TR>
69
                <TD WIDTH=30>
70
                        <P>&nbsp;</P>
71
                </TD>
72
                <TD WIDTH=562>
73 2732 nacho
                        <P>&nbsp;&nbsp;&nbsp; <A HREF="#NewFiter">3.1 Creaci&oacute;n de
74 2248 igbrotru
                        un nuevo filtro</A></P>
75
                </TD>
76
        </TR>
77
        <TR>
78
                <TD WIDTH=30>
79
                        <P><BR>
80
                        </P>
81
                </TD>
82
                <TD WIDTH=562>
83 2732 nacho
                        <P>&nbsp;&nbsp;&nbsp; <A HREF="#ManageFilter">3.2 Gesti&oacute;n
84 2248 igbrotru
                        de un nuevo filtro</A></P>
85
                </TD>
86
        </TR>
87 2732 nacho
        <TR>
88
                <TD WIDTH=30>
89
                        <P><BR>
90
                        </P>
91
                </TD>
92
                <TD WIDTH=562 BGCOLOR="#eb613d">
93
                        <P><A HREF="#Interfaces"><SPAN STYLE="background: #e86d26"><B><FONT COLOR="#ffffff">4.Interfaces
94
                        Gr&aacute;ficas</FONT></B></SPAN></A></P>
95
                </TD>
96
        </TR>
97
        <TR>
98
                <TD WIDTH=30>
99
                        <P><BR>
100
                        </P>
101
                </TD>
102
                <TD WIDTH=562>
103
                        <P>&nbsp;&nbsp;&nbsp; <A HREF="#InterfazPropiedades">4.1 Interfaz
104
                        de Propiedades</A></P>
105
                </TD>
106
        </TR>
107
        <TR>
108
                <TD WIDTH=30>
109
                        <P><BR>
110
                        </P>
111
                </TD>
112
                <TD WIDTH=562>
113
                        <P>&nbsp;&nbsp;&nbsp; <A HREF="#InterfazSalvar">4.1 Interfaz de
114
                        salvar a raster </A>
115
                        </P>
116
                </TD>
117
        </TR>
118 2248 igbrotru
</TABLE>
119 2732 nacho
<P><STRONG><FONT SIZE=5>1.Introducci&oacute;n</FONT></STRONG></P>
120
<P STYLE="margin-bottom: 0cm">&nbsp;&nbsp;&nbsp; La librer&iacute;a
121
de Cresques consta de los siguientes elementos:</P>
122
<UL>
123
        <LI><P STYLE="margin-bottom: 0cm">Un interfaz homogeneo de acceso a
124
        los datos de todos los formatos soportados .
125
        </P>
126
        <LI><P STYLE="margin-bottom: 0cm">Drivers de acceso de lectura a
127
        formatos raster georeferenciados como ecw, mrsid, tif, jpg, png a
128
        trav&eacute;s de sus respectivas librerias.
129
        </P>
130
        <LI><P STYLE="margin-bottom: 0cm">Drivers de acceso a formatos Dxf y
131
        gml.
132
        </P>
133
        <LI><P STYLE="margin-bottom: 0cm">Drivers de escritura para GeoTiff
134
        y Ecw(solo linux kernel 2.4)
135
        </P>
136
        <LI><P STYLE="margin-bottom: 0cm">Una arquitectura para filtros
137
        sobre los formatos raster soportados.
138
        </P>
139
        <LI><P STYLE="margin-bottom: 0cm">Una interfaz gr&aacute;fica en
140
        java para la gesti&oacute;n de filtros.
141
        </P>
142
        <LI><P STYLE="margin-bottom: 0cm">Una interfaz gr&aacute;fica en
143
        java para el manejo del salvado a raster.
144
        </P>
145
</UL>
146
<P STYLE="margin-left: 0.02cm"><A NAME="Drivers"></A><STRONG><FONT SIZE=5>2.
147
Drivers</FONT></STRONG></P>
148
<P STYLE="margin-left: 0.02cm">&nbsp;&nbsp;&nbsp; Los drivers de
149
Cresques son clases que contiene un interfaz de acceso a un tipo de
150
fichero a trav&eacute;s de una librer&iacute;a o implementando sus
151
propias funcionalidades. Para el acceso a Ecw, MrSID y Gdal utiliza
152
librerias externas en C por lo que deber&aacute;n estar instaladas
153
correctamente para hacer uso de estos drivers. Las librerias externas
154
al estar en C necestan un interfaz para el uso desde java. Este
155
interfaz puede constar de otra librer&iacute;a en C que debe estar
156
tambi&eacute;n instalada y un fichero .jar con las funciones en java
157
de acceso a la librer&iacute;a que debe estar en el classpath. El
158
directorio depend del proyecto de Cresques contiene las librerias C
159
necesarias y el directorio lib las de java.
160
</P>
161
<P STYLE="margin-left: 0.02cm">&nbsp;&nbsp;&nbsp; Los drivers de
162
lectura y escritura para un mismo tipo de fichero est&aacute;n
163
separadas en clases disintas.
164
</P>
165
<P STYLE="margin-left: 0.02cm"><A NAME="DLectura"></A><STRONG><FONT SIZE=4>2.1
166
Drivers de lectura</FONT></STRONG></P>
167
<P STYLE="margin-left: 0.02cm">&nbsp;&nbsp;&nbsp; El nombre de la
168
clase de un driver de lectura est&aacute; compuesto por el tipo de
169
fichero al que accede seguido de la palabra File, as&iacute; tenemos
170
los siguientes drivers de lectura:</P>
171
<UL>
172
        <LI><P STYLE="margin-bottom: 0cm">EcwFile para el driver de acceso a
173
        ficheros con formato ecw.</P>
174
        <LI><P STYLE="margin-bottom: 0cm">MrSIDFile para el driver de acceso
175
        a ficheros con formato MrSID.</P>
176
        <LI><P STYLE="margin-bottom: 0cm">GdalFile para el acceso a ficheros
177
        raster a trav&eacute;s de la librer&iacute;a gdal.</P>
178
        <LI><P STYLE="margin-bottom: 0cm">DxfFile para acceso a ficheros
179
        dxf.</P>
180
        <LI><P STYLE="margin-bottom: 0cm">GmlFile para acceso a ficheros
181
        gml.</P>
182
</UL>
183
<P STYLE="margin-left: 0.02cm; margin-bottom: 0cm">&nbsp;&nbsp;&nbsp;
184
Los drivers de lectura de acceso a raster hereda todos de una misma
185
clase abstracta GeoRasterFile para darles a todos ellos una interfaz
186
homogenea de acceso a los datos. Los drivers que dependen de
187
GeoRasterFile deben usar un mecanismo de registro para ser accesible.
188
Este mecanismo permite que si creamos un driver fuera de cresques
189
pero que herede de GeoRasterFile sea reconocido por este y pueda
190
accederse a su funcionalidad. Para el registro, el driver en cuesti&oacute;n
191
deber&aacute; incluir un bloque static en su c&oacute;digo y a&ntilde;adir
192
una entrada en la variable TreeMap supportedExtensions de
193
GeoRasterFile con el nombre del driver y la clase que lo implementa.
194
Esto se har&aacute; con la funci&oacute;n registerExtension. Por
195
ejemplo, si quisieramos hacer un driver para acceso a Jpg que use
196
nuestra propia librer&iacute;a le incluiriamos un c&oacute;digo como
197
este:</P>
198
<P STYLE="margin-left: 0.02cm; margin-bottom: 0cm"><BR>
199
</P>
200
<PRE>          static {
201
                registerExtension(&quot;jpg&quot;,  JpgGeoRefFile.class);
202
          }</PRE><P STYLE="margin-left: 0.02cm; margin-bottom: 0cm">
203
<BR>
204
</P>
205
<P STYLE="margin-left: 0.02cm; margin-bottom: 0cm">&nbsp;&nbsp;&nbsp;
206
Sin necesidad de instanciar la nueva clase se ejecutar&aacute; el
207
bloque static asignando a la gesti&oacute;n de la extensi&oacute;n
208
jpg la nueva clase creada. Como esta nuevo driver heredar&aacute; de
209
GeoRasterFile tendr&aacute; el interfaz necesario para acceso a los
210
datos por lo que no habr&aacute; ning&uacute;n problema. Por lo
211
tanto, los m&eacute;todos abstractos de GeoRasterFile son de
212
obligatoria implementaci&oacute;n en nuestro driver. Los drivers de
213
GeoRasterFile est&aacute;n registrados en esta misma clase ya que son
214
drivers que no varian dentro de Cresques.</P>
215
<P STYLE="margin-left: 0.02cm; margin-bottom: 0cm"><BR>
216
</P>
217
<P STYLE="margin-left: 0.02cm"><A NAME="DEscritura"></A><STRONG><FONT SIZE=4>2.2
218
Drivers de escritura</FONT></STRONG></P>
219
<P STYLE="margin-left: 0.02cm">&nbsp;&nbsp;&nbsp; El nombre de la
220
clase de un driver de escritura est&aacute; compuesto por el tipo de
221
fichero al que accede seguido de la palabra Writer, as&iacute;
222
tenemos los siguientes drivers de lectura:</P>
223
<UL>
224
        <LI><P STYLE="margin-bottom: 0cm">EcwWriter para el driver de
225
        escritura sobre ficheros con formato ecw (solo Linux kernel 2.4).
226
        </P>
227
        <LI><P STYLE="margin-bottom: 0cm">GdalWriter para la escritura sobre
228
        ficheros georeferenciados a trav&eacute;s de Gdal.</P>
229
</UL>
230
<P STYLE="margin-left: 0.02cm; margin-bottom: 0cm"><BR>
231
</P>
232
<P STYLE="margin-left: 0.02cm; margin-bottom: 0cm">&nbsp;&nbsp;&nbsp;
233
Estos drivers son para la escritura de ficheros raster
234
georeferenciados.
235
</P>
236
<P STYLE="margin-left: 0.02cm; margin-bottom: 0cm"><BR>
237
</P>
238
<P STYLE="margin-left: 0.02cm; margin-bottom: 0cm">&nbsp;&nbsp;&nbsp;
239
Los drivers de escritura en raster georeferenciados deben heredar de
240
la misma clase abstracta GeoRasterWriter para darles a todos ellos
241
una interfaz homogenea de escritura de datos. Los drivers que
242
dependen de GeoRasterFile deben usar un mecanismo de registro para
243
ser accesible. Este mecanismo permite que si creamos un driver fuera
244
de cresques pero que herede de GeoRasterWriter sea reconocido por
245
este y pueda accederse a su funcionalidad. Para el registro, el
246
driver en cuesti&oacute;n deber&aacute; incluir un bloque static en
247
su c&oacute;digo y a&ntilde;adir una entrada en la variable TreeMap
248
supportedExtensions de GeoRasterFile con el nombre del driver y la
249
clase que lo implementa. Esto se har&aacute; con la funci&oacute;n
250
registerWriterExtension. Por ejemplo, si quisieramos hacer un driver
251
de escritura en Jpg que use nuestra propia librer&iacute;a le
252
incluiriamos un c&oacute;digo como este:</P>
253
<P STYLE="margin-left: 0.02cm; margin-bottom: 0cm"><BR>
254
</P>
255
<PRE>          static {
256
                registerWriterExtension(&quot;jpg&quot;,  JpgGeoRefWriter.class);
257
          }</PRE><P STYLE="margin-left: 0.02cm; margin-bottom: 0cm">
258
<BR>
259
</P>
260
<P ALIGN=LEFT STYLE="margin-bottom: 0cm">&nbsp;&nbsp;&nbsp; Dentro
261
del driver tendremos que escribir una clase que deber&aacute;
262
llamarse &lt;NombreFormato&gt;SupportOptions y que deber&aacute;
263
heredar de WriterSupportOptions. Esta clase contendr&aacute; las
264
opciones de escritura concretas para este formato. Esta opciones son
265
las que el usuario visualizar&aacute; en la ventana de propiedades de
266
escritura. Es conveniente que las opciones que corresponderan a una
267
lista de selecci&oacute;n (combo) se guarden aqu&iacute; como un
268
vector de Strings o cualquier otro tipo de lista de esta forma:</P>
269
<PRE STYLE="margin-bottom: 0.5cm">        <FONT FACE="Nimbus Mono L">private String[]                formatList = {&quot;NONE&quot;,&quot;UINT8&quot;,&quot;YUV&quot;,&quot;MULTI&quot;,&quot;RGB&quot;};</FONT></PRE><P ALIGN=LEFT STYLE="margin-bottom: 0cm">
270
<FONT FACE="Verdana, Arial, Helvetica, sans-serif"><FONT SIZE=2 STYLE="font-size: 9pt">y
271
adem&aacute;s se definan variables para los valores seleccionados por
272
defecto </FONT></FONT>
273
</P>
274
<P ALIGN=LEFT STYLE="margin-bottom: 0cm"><BR>
275
</P>
276
<P ALIGN=LEFT STYLE="margin-bottom: 0cm">&nbsp;&nbsp;&nbsp; Deben
277
crearse m&eacute;todos para la lectura y escritura de todas las
278
propiedades</P>
279
<P ALIGN=LEFT STYLE="margin-bottom: 0cm"><BR>
280
</P>
281
<P ALIGN=LEFT STYLE="margin-bottom: 0cm"><FONT FACE="Verdana, Arial, Helvetica, sans-serif"><FONT SIZE=2 STYLE="font-size: 9pt">El
282
constructor estar&aacute; vacio en funcionalidades pero llamar&aacute;
283
al constructor del padre pasando como par&aacute;metro un string que
284
identifica al driver.</FONT></FONT></P>
285
<PRE>        <FONT FACE="Nimbus Mono L">EcwSupportOptions(){</FONT>
286
                super(&quot;Ecw&quot;);
287
        }</PRE><P ALIGN=LEFT STYLE="margin-bottom: 0cm; text-decoration: none">
288
&nbsp;&nbsp;&nbsp; Constructor sin par&aacute;metros:</P>
289
<P ALIGN=LEFT STYLE="margin-bottom: 0cm"><BR>
290
</P>
291
<P ALIGN=LEFT STYLE="margin-bottom: 0cm; text-decoration: none">&nbsp;&nbsp;&nbsp;
292
Este constructor inicializa el xxxSupportOptions que contiene las
293
opciones de escritura y asigna valores a estas opciones especificas
294
del driver que estamos implementando</P>
295
<PRE>         public EcwWriter(){
296
                this.support = new EcwSupportOptions();
297
                this.driver = &quot;ecw&quot;;
298
                this.support.setBlockSize(64);
299
                this.support.setCompressionDefault(10);
300
                this.support.setFormatDefault(4);
301
                this.support.setWriteGeoref(true);
302
                this.ident = &quot;Ecw&quot;;
303
                this.consulta = true;
304
305
        }</PRE><P ALIGN=LEFT STYLE="margin-bottom: 0cm; text-decoration: none">
306
&nbsp;&nbsp;&nbsp; Constructor para salvar una sola imagen completa</P>
307
<PRE>         <FONT FACE="Nimbus Mono L">public EcwWriter(      PxRaster raster, </FONT>
308
                        String outfilename,
309
                        String infilename,
310
                        int compresion)throws EcwException, IOException </PRE><P ALIGN=LEFT STYLE="margin-bottom: 0cm; text-decoration: none">
311
&nbsp;&nbsp;&nbsp; Para este constructor se ha de pasar como
312
par&aacute;metro el PxRaster de la imagen que se desea salvar a
313
disco. Se inicializar&aacute; la clase xxxSupportOptions de la misma
314
forma que en el constructor anterior y se asignar&aacute;n valores a
315
variables de instancia con datos para salvar a raster tales como
316
georeferenciaci&oacute;n, n&uacute;mero de bandas, ancho, alto,
317
tama&ntilde;o de pixel, ...</P>
318
<P STYLE="margin-left: 0.02cm; margin-bottom: 0cm"><BR>
319
</P>
320
<P ALIGN=LEFT STYLE="margin-left: 0.02cm; margin-bottom: 0cm; text-decoration: none">
321
&nbsp;&nbsp;&nbsp; Los drivers de escritura dise&ntilde;an su propia
322
ventana de propiedades en java. Para ello tiene un m&eacute;todo
323
getXMLPropertiesDialog que dice como ser&aacute; esta ventana. Para
324
ello debe devolver una cadena de texto con un XML que contiene esta
325
configuraci&oacute;n. El Xml deber&aacute; comenzar definiendo el
326
tama&ntilde;o de la ventana de esta forma:</P>
327
<PRE>&lt;window sizex=&quot;340&quot; sizey=&quot;180&quot;&gt;
328
... Cuerpo de la ventana ...
329
&lt;/window&gt;</PRE><P STYLE="margin-left: 0.02cm">
330
<SPAN STYLE="text-decoration: none">&nbsp;&nbsp;&nbsp; </SPAN>Dentro
331
del cuerpo de la ventana deber&aacute;n definirse los panels con los
332
componentes. Solo est&aacute; permitido un nivel de anidamiento y el
333 2845 nacho
uso de Checkbox, labels, combos, sliders.
334 2732 nacho
</P>
335
<PRE>&lt;panel sizex=&quot;330&quot; sizey=&quot;170&quot; layout=&quot;FlowLayout&quot; border=&quot;yes&quot; &gt;
336
&lt;/panel&gt;
337
338
&lt;label&gt;Tama&ntilde;o bloque:
339
&lt;/label&gt;
340
341
&lt;combo ident=&quot;BLOCKSIZE&quot; selected=&quot;64&quot;&gt;
342
  &lt;elem&gt;32&lt;/elem&gt;
343
  &lt;elem&gt;64&lt;/elem&gt;
344
  &lt;elem&gt;128&lt;/elem&gt;
345
&lt;/combo&gt;
346
347
&lt;check ident=&quot;GEOREF&quot; selected=&quot;10&rdquo;&gt;
348 2845 nacho
&lt;/check&gt;</PRE><P>
349
<SPAN STYLE="text-decoration: none">&nbsp;&nbsp;&nbsp; </SPAN>Las
350
opciones del driver que se incorporan pueden ser almacenadas y
351
consultadas en una clase que herede de WriteSupportOptions.
352
WriterSupportOptions contiene todas las opciones de salvado comunes a
353
todos los drivers. Por ejemplo, el driver de escritura de ecw tendr&aacute;
354
una clase EcwSupportOptions con las opciones especificas de salvado.
355
</P>
356
<P STYLE="margin-left: 0.02cm; text-decoration: none">&nbsp;&nbsp;&nbsp;
357
El salvado a raster puede realizarse en dos modos:</P>
358 2732 nacho
<UL>
359
        <LI><P STYLE="text-decoration: none">El primero se hace a partir de
360
        un GeoRasterFile leyendo datos de una imagen raster soportada de
361
        entrada y salvandolos en la imagen de la salida. Este m&eacute;todo
362
        es rapido y directo para la conversi&oacute;n de unos formatos
363
        raster a otros. Para esta forma se usa el m&eacute;todo fileWrite.</P>
364
        <LI><P STYLE="text-decoration: none">El segundo se realiza salvando
365
        la imagen a partir de los datos pasados por un cliente utilizando el
366
        m&eacute;todo dataWrite. En la construcci&oacute;n del filtro se
367
        especificar&aacute; el tama&ntilde;o de la imagen de salida, nombre
368
        de la misma, coordenadas de georeferenciaci&oacute;n, compresi&oacute;n
369
        si la hubiere, ... Cuando se invoca el m&eacute;todo dataWrite
370
        solicitar&aacute; datos al cliente cuando vacie su buffer hasta que
371
        haya terminado con toda la imagen. De esta forma es el escritor el
372
        que controla el flujo de bytes y el cliente puede salvar a raster
373
        cualquier dato que quiera y que venga de otras fuentes. De esta
374
        forma podriamos tener una aplicaci&oacute;n con una vista que
375
        deseemos salvar a raster, si somos capaces de leer los bytes de ella
376
        podemos crear un flujo de datos para salvarlos.
377
        </P>
378
        <P STYLE="text-decoration: none">El cliente debe crear una clase
379
        servidora de datos. Un ejemplo de esto es la clase Rasterizer que
380
        debe implementar el interfaz IDataWriter que obliga al m&eacute;todo
381
        readData. Este servidor de datos se pasar&aacute; en el constructor
382
        del driver de escritura y lo utilizar&aacute; para solicitar los
383
        datos. Por esto, es el cliente el encargado de controlar los datos
384
        que ha pasado y los que le quedan por pasar. El driver ir&aacute;
385
        cogiendo hasta que complete la ventana que necesita.</P>
386
        <P STYLE="text-decoration: none">En la clase Rasterizer a partir de
387
        una capa de PxRaster (PxLayerList) se crea calcula el recuadro del
388
        trozo de la vista que se necesita en cada petici&oacute;n, se leen
389
        los datos desde un image y se devuelven en forma de array de
390
        enteros. Ser&aacute; el driver el que escriba a disco ese array. En
391
        general, si se necesita hacer uso de salvar a raster se deber&aacute;
392
        escribir una clase como Rasterizer para el caso concreto que estamos
393
        tratando. GvSIG hace uso de esta funcionalidad a trav&eacute;s de la
394
        clase RasterizerLayer en el paquete com.iver.cit.gvsig, la cual
395
        sirve los datos para salvar a raster una vista.</P>
396
        <P STYLE="text-decoration: none">Normalmente la escritura de las
397
        imagenes debe ser por franjas. Cada franja tiene la anchura total de
398
        la imagen y una altura que viene definida por el tama&ntilde;o de
399
        bloque que el usuario podr&iacute;a variar en la ventana de
400
        propiedades del driver.</P>
401
</UL>
402
<P ALIGN=LEFT><A NAME="Filtros"></A><A NAME="NewFiter"></A><STRONG><FONT SIZE=5>3.
403
Filtros</FONT></STRONG><BR><BR><STRONG><FONT SIZE=4>3.1 Creaci&oacute;n
404 2248 igbrotru
de un nuevo filtro</FONT></STRONG></P>
405
<P STYLE="margin-left: 0.02cm">&nbsp;&nbsp;&nbsp; Crear una nueva
406
clase abstracta que heredar&aacute; de RasterFilter y que tendr&aacute;
407
como nombre el nombre del filtro (en ingl&eacute;s a poder ser)
408
seguido de Filter. Usaremos como ejemplo la generaci&oacute;n del
409
filtro de transparencia. En este caso, esta clase abstracta debe
410
llamarse TransparencyFilter.
411
</P>
412
<P>&nbsp;&nbsp;&nbsp; Crear una clase que hereda de esta clase que
413
hemos creado para cada tipo de dato b&aacute;sico que se da soporte.
414
En nuestro caso dos clases heredan de TransparencyFilter y son
415
TransparencyImageFilter y TransparencyShortFilter. Notese que la
416
nomenclatura hace referencia al tipo de dato que maneja. La primera
417
funciona para objetos Image de java y la segunda para im&aacute;genes
418
de 16 bits.Estas &uacute;ltimas est&aacute;n representadas por una
419
clase llamada RasterBuf. Si fuera necesario deber&iacute;a hacerse
420
para Float, Double, ...
421
</P>
422
<P>&nbsp;&nbsp;&nbsp; El constructor de los filtros es recomendable
423
que est&eacute; vacio.</P>
424
<P>&nbsp;&nbsp;&nbsp; En la clase base del filtro que estamos creando
425
(TransparencyFilter) deben ponerse las variables de instancia que
426
contengan los par&aacute;metros necesarios para el filtro. En este
427
caso tendriamos 3 vectores bidimensionales que contendran los
428
intervalos de valores a poner como transparentes y cuatro enteros que
429
representan el alpha y el color de transparencia en caso de querer
430
proporcionar alguno. Por defecto ser&aacute; blanco, es decir
431
totalmente transparente y sin ninguna tonalidad.</P>
432
<P>&nbsp;&nbsp;&nbsp; Aqu&iacute; deben ponerse tambi&eacute;n todas
433
las funcionalidades comunes a todos los tipos de filtro de
434
transparencia. Como TransparencyFilter hereda de RasterFilter que es
435
abstracta y tiene m&eacute;todos abstractos obligar&aacute; a
436
implementar estos. Si es necesario que estos m&eacute;todos
437
abstractos tengan c&oacute;digo podemos implementarlos aqu&iacute;
438
sino podr&aacute; hacerse en las clases hijas que contienen la
439
especificaci&oacute;n para el filtro de transparencia sobre cada tipo
440
de dato concreto. Los m&eacute;todos abstractos que es preciso
441
implementar son:</P>
442
<UL>
443
        <LI><P><B>abstract public void pre();</B> .</P>
444
</UL>
445
<P>&nbsp;&nbsp;&nbsp; Aqu&iacute; pondremos las operaciones que hay
446
que realizar antes de ejecutar el filtro que estamos creando. En
447
nuestro caso est&aacute; implementado en la clase base del filtro y
448
en las hijas . En la clase base tiene c&oacute;digo com&uacute;n para
449
los filtros de transparencia de cualquier tipo de datos.</P>
450
<PRE>        public void pre(){
451
                this.rangesR = (int[][])params.get(&quot;red&quot;);
452
                this.rangesG = (int[][])params.get(&quot;green&quot;);
453
                this.rangesB = (int[][])params.get(&quot;blue&quot;);
454
                this.alpha = ((Integer)params.get(&quot;alpha&quot;)).intValue();
455
                this.transparencyColorRed = ((Integer)params.get(&quot;transparencyRed&quot;)).intValue();
456
                this.transparencyColorGreen = ((Integer)params.get(&quot;transparencyGreen&quot;)).intValue();
457
                this.transparencyColorBlue = ((Integer)params.get(&quot;transparencyBlue&quot;)).intValue();
458
        }</PRE><P>
459
&nbsp;&nbsp;&nbsp; En las clases hijas se pone la implementaci&oacute;n
460
concreta para ese tipo de dato. En el caso de la transparencia sobre
461
un Image obtenemos el par&aacute;metro que contiene la Image y
462
asignamos los valore de altura y anchura de raster a partir de este
463
Image. Antes de finalizar llama al pre() de TransparencyFilter.</P>
464
<PRE>        public void pre(){
465
                this.image = (Image)params.get(&quot;raster&quot;);
466
                height = image.getHeight(null);
467
                width = image.getWidth(null);
468
                super.pre();
469
        }</PRE>
470
<UL>
471
        <LI><P><B>abstract public void post();</B></P>
472
</UL>
473
<P>&nbsp;&nbsp;&nbsp; Aqu&iacute; se ponen las operaciones a realizar
474
despu&eacute;s de ejecutar el filtro. En el caso que estamos viendo
475
no es necesario hacer nada por lo que estar&aacute; vacio. Podria ser
476
necesario alguna operaci&oacute;n como por ejemplo cargar el
477
resultado de la operaci&oacute;n en alguna variable de salida o algo
478
as&iacute;.</P>
479
<UL>
480
        <LI><P><B>abstract public void process(int x, int y);</B></P>
481
</UL>
482
<P>&nbsp;&nbsp;&nbsp; Este m&eacute;todo es el encargado de procesar
483
el filtro para un pixel de la imagen. La clase abstracta RasterFilter
484
de la cual heredan todos los filtros tiene el metodo execute() que
485
har&aacute; lo siguiente:</P>
486
<PRE>                pre();
487
                     for (int y=0; y&lt;height; y=y+incY)
488
                        for (int x=0; x&lt;width; x=x+incX) {
489
                                process(x, y);
490
                        }
491
                post();</PRE><P>
492
&nbsp;&nbsp;&nbsp; Por esto debemos tener en process el c&oacute;digo
493
que ejecuta el filtro. Esto siempre suele rellenarse en las clases
494
que representan a un filtro de un tipo de dato concreto. Para nuestro
495
ejemplo en TransparencyImageFilter el process tendr&aacute; el
496
siguiente c&oacute;digo:</P>
497
<PRE>        public void process(int x, int y) {
498
                int pt = ((BufferedImage) image).getRGB(x,y);
499
                int []px4 = {(pt &amp; 0xff000000) &gt;&gt; 24,(pt &amp; 0xff0000) &gt;&gt; 16, (pt &amp; 0x00ff00) &gt;&gt; 8, (pt &amp;                                 0x0000ff)};
500
                if(rangesR!=null)
501
                        processRange(rangesR, 1, px4);
502
                if(rangesG!=null)
503
                        processRange(rangesG, 2, px4);
504
                if(rangesB!=null)
505
                        processRange(rangesB, 3, px4);
506
                ((BufferedImage) image).setRGB(x,y, (
507
                        (px4[0] &lt;&lt; 24) &amp; 0xff000000 | (px4[1] &lt;&lt; 16) &amp; 0x00ff0000 |
508
                        (px4[2] &lt;&lt; 8)  &amp; 0x0000ff00 | (px4[3] &amp; 0x0000ff) ));
509
        }</PRE><P>
510
<BR><BR>
511
</P>
512
<P>&nbsp;&nbsp;&nbsp; Esta funci&oacute;n obtendr&aacute; el pixel
513
del buffer lo procesar&aacute; y salvar&aacute; el resultado sobre el
514
mismo buffer.</P>
515
<UL>
516
        <LI><P><B>abstract public void processLine(int y);</B></P>
517
</UL>
518
<P>&nbsp;&nbsp;&nbsp; Esta funci&oacute;n realizar&aacute; el mismo
519
proceso que process(int x, int y) pero aplicada directamente a una
520
l&iacute;nea del buffer.</P>
521
<UL>
522
        <LI><P><B>abstract public int getInRasterDataType();</B></P>
523
</UL>
524
<P>&nbsp;&nbsp;&nbsp; Devuelve el tipo de dato del buffer de entrada.
525
La clase RasterBuf tiene constantes que tiene todos los tipos de
526
datos posibles por lo que puede realizarse algo as&iacute;:</P>
527
<PRE>        public int getInRasterDataType(){
528
                return RasterBuf.TYPE_IMAGE;
529 2732 nacho
        <I>}    </I>   </PRE>
530 2248 igbrotru
<UL>
531
        <LI><P><B>abstract public int getOutRasterDataType();</B></P>
532
</UL>
533
<P>&nbsp;&nbsp;&nbsp; Devuelve el tipo de dato del buffer de salida.
534
La clase RasterBuf tiene constantes que tiene todos los tipos de
535
datos posibles por lo que puede realizarse algo as&iacute;:
536
</P>
537 2845 nacho
<PRE>        public int getOutRasterDataType(){
538 2248 igbrotru
                return RasterBuf.TYPE_IMAGE;
539
        }</PRE>
540
<UL>
541
        <LI><P><B>abstract public Object getResult(String name);</B></P>
542
</UL>
543
<P>&nbsp;&nbsp;&nbsp; Obtiene el resultado del filtro en un Object.
544
Para esto se la pasa un par&aacute;metro con la clave del resultado y
545
nos devolver&aacute; el Object correspondiente. Esto es necesario
546
porque un mismo filtro puede tener varias salidas, por ejemplo puede
547
tener un raster con el resultado de aplicar el filtro y una clase con
548
algunas estadisticas calculadas en el proceso. En este caso el filtro
549
de transparencia solo devuelve un raster de salida por lo que se har&aacute;
550
una funci&oacute;n por tipo de dato tal que:</P>
551
<PRE>        public Object getResult(String name){
552
                if(name.equals(&quot;raster&quot;))
553
                        return (Object)this.image;
554
                else
555
                        return null;
556
        <FONT SIZE=2 STYLE="font-size: 9pt">}</FONT></PRE><P>
557 2732 nacho
&nbsp;&nbsp;&nbsp; Esta es la que se har&aacute; para
558
TransparencyImageFilter ya que devuelve un tipo Image.</P>
559
<P><A NAME="ManageFilter"></A><BR>&nbsp;<BR><STRONG><FONT SIZE=4>3.2
560
Gesti&oacute;n de un nuevo filtro</FONT></STRONG></P>
561 2248 igbrotru
<P>&nbsp;&nbsp;&nbsp; Para el almacenaje de filtros seleccionados hay
562
una clase llamada RasterFilterStack que contiene la pila de filtros y
563
que es generica para cualquier tipo de filtro realizado, es decir, en
564
condiciones normales, en la creaci&oacute;n de un nuevo filtro esta
565
clase no debe tocarse. Sin embargo si debe a&ntilde;adirse la gesti&oacute;n
566
del nuevo filtro con filterStackManager . Para a&ntilde;adir este
567
nuevo filtro deber&aacute; crearse una nueva clase que heredar&aacute;
568
de RasterFilterStackManager. RasterFilter esla encargada de a&ntilde;adir
569
filtros a la pila ya que ella es la que sabr&aacute; el orden en el
570
que deben ir estos . Un orden de la pila incorrecto da un resultado
571
de aplicaciones de filtros indeseado. Con esto deducimos que la pila
572
es tratada como tal para la ejecuci&oacute;n de filtros pero que
573
estos deben estar de antemano ordenados correctamente por lo que no
574
es una pila en el sentido estricto.</P>
575
<P>&nbsp;&nbsp;&nbsp; Este nuevo gestor de filtros deber&aacute;
576
implementar la interfaz StackManager de forma que la definici&oacute;n
577
de nuestra nueva clase ser&iacute;a m&aacute;s o menos asi:</P>
578
<PRE>public class PruebaStackManager extends RasterFilterStackManager implements StackManager{
579
...
580
}</PRE><P>
581
&nbsp;&nbsp;&nbsp; Para el nuevo filtro debe a&ntilde;adirse en esta
582
nueva clase una constante que represente el tipo del nuevo filtro. Lo
583
m&aacute;s l&oacute;gico es darle un n&uacute;mero de orden
584
consecutivo a las que hay pero podr&iacute;a asignarse otro en caso
585
de haber una causa justificada. Las actualmente asignadas en la
586
RasterFilterStackManager son
587
</P>
588
<PRE>        <I>transparency = 0;</I>
589
        enhanced=1;
590
        computeminmax=2;
591
        tail=3;</PRE><P>
592
&nbsp;&nbsp;&nbsp; El vector order de RasterFilterStackManager
593
contiene la forma de ordenaci&oacute;n de los filtros de la pila.
594
Este orden es importante, por ejemplo la transparencia debe aplicarse
595
despues del realce de la imagen ya que esta se aplica a rangos de
596
colores y antes o despu&eacute;s del realce los rangos de colores
597
difieren por lo que la transparencia debe aplicarse sobre la imagen
598
realzada y no al rev&eacute;s. Para asignar este nuevo order
599
deberemos indicarlo en el constructor de esta clase que hemos creado.</P>
600
<PRE>        public PruebaStackManager(RasterFilterStack filterStack){
601
                super(filterStack);
602
                addTypeFilter(&quot;prueba&quot;, PruebaStackManager.prueba, 2);
603
        }</PRE><P>
604
<BR><BR>
605
</P>
606
<P>&nbsp;&nbsp;&nbsp; Habr&aacute; que elegir una posici&oacute;n
607
para el nuevo filtro creado para que produzca el resultado deseado.
608
La funci&oacute;n addTypeFilter tendr&aacute; como par&aacute;metros
609
en nombre del filtro, constante asignada y posici&oacute;n para la
610
ordenaci&oacute;n. Si introducimos el nuevo filtro en la posici&oacute;n
611
3 la ordenaci&oacute;n inicial:</P>
612
<PRE STYLE="margin-bottom: 0.5cm">computeminmax, tail, enhanced, transparency </PRE><P>
613
<BR><BR>
614
</P>
615
<P>quedar&aacute;
616
</P>
617
<PRE STYLE="margin-bottom: 0.5cm">computeminmax, tail, prueba, enhanced, transparency </PRE><P>
618
<BR><BR>
619
</P>
620
<P>ya que la posici&oacute;n en el vector de ordenaci&oacute;n tiene
621
en cuenta la posici&oacute;n 0.</P>
622
<P>&nbsp;&nbsp;&nbsp; En RasterFilterStackManager tambi&eacute;n
623
existe una funci&oacute;n llamada getType que devuelve el tipo de
624
filtro que contiene un RasterFilter. Deberemos a&ntilde;adir el
625
nuestro para una correcta gesti&oacute;n. Para ello sobrescribiremos
626
el m&eacute;todo getType de esta forma:</P>
627 2732 nacho
<PRE>        public int getType(RasterFilter rasterFilter){
628 2248 igbrotru
                if(rasterFilter instanceof &lt;&lt;NuestoFiltro&gt;&gt;)
629
                        return PruebaStackManager.&lt;&lt;Nuestra constante&gt;&gt;;
630
631
                return super.getType(rasterFilter);
632
        }</PRE><P>
633
<BR><BR>
634
</P>
635
<P>sustituyendo &lt;&lt;NuestroFiltro&gt;&gt; por el nombre de la
636
clase abstracta base del filtro que hemos construido y &lt;&lt;Nuestra
637
constante&gt;&gt; por la constante que representa nuestro filtro.</P>
638
<P>&nbsp;&nbsp;&nbsp; Dentro de nuestra clase habr&aacute; que
639
definir una funci&oacute;n para a&ntilde;adir el nuevo filtro. Esta
640
funci&oacute;n debe tener como argumentos los par&aacute;metros
641
necesarios para el nuevo filtro. En el caso de un filtro de
642
transparencia podrian ser los intervalos para RGB y el color de
643
transparencia.</P>
644
<P>&nbsp;&nbsp;&nbsp; En esta funci&oacute;n hay que hacer algunas
645
acciones obligatorias y otras opcionales. Podemos verlas sobre un
646
ejemplo:</P>
647
<P>&nbsp;&nbsp;&nbsp; Cabecera de la funci&oacute;n ya comentada:</P>
648
<P><BR><BR>
649
</P>
650 2732 nacho
<PRE>                public void addTransparencyFilter(      int[][] red,
651 2248 igbrotru
                                                        int[][] green,
652
                                                        int[][] blue,
653
                                                        int alpha,
654
                                                        int transparencyRed,
655
                                                        int transparencyGreen,
656
                                                        int transparencyBlue){
657
                </PRE><P>
658
&nbsp;&nbsp;&nbsp; Es necesario crear un RasterFilter de un tipo u
659
otro dependiendo del tipo de dato que nos diga la pila que necesita.
660
El m&eacute;todo
661
filterStack.getDataTypeInFilter(RasterFilterStackManager.transparency)
662
devuelve el tipo de dato que necesitamos si el filtro que vamos a
663
meter es de transparencia. Esta funci&oacute;n de la pila calcular&aacute;
664
en que posici&oacute;n debe ir el filtro y que tipo de dato devuelve
665
el que tendr&aacute; por encima, por lo tanto sabremos de que tipo es
666
el filtro que debemos crear. Podemos hacer la selecci&oacute;n con un
667
switch de esta forma:</P>
668 2732 nacho
<PRE>                RasterFilter filtro = null;
669 2248 igbrotru
                switch(filterStack.getDataTypeInFilter(((Integer)typeFilters.get(&quot;transparency&quot;)).intValue())){
670
                        case RasterBuf.TYPE_IMAGE:filtro = new TransparencyImageFilter();break;
671
                        case RasterBuf.TYPE_SHORT:
672
                        case RasterBuf.TYPE_USHORT:
673
                        case RasterBuf.TYPE_INT:filtro = new TransparencyShortFilter();break;
674
                }</PRE><P>
675
<BR><BR>
676
</P>
677
<P>&nbsp;&nbsp;&nbsp; Si tiene par&aacute;metros deberemos a&ntilde;adirlos
678
al filtro creado con addParam. Cada par&aacute;metro debe ser a&ntilde;adido
679
con una clave. Esta debe coincidir con la que definimos para su
680
recuperaci&oacute;n en el m&eacute;todo pre() del filtro.</P>
681 2732 nacho
<PRE>                if(red != null)filtro.addParam(&quot;red&quot;, red);
682 2248 igbrotru
                if(green != null)filtro.addParam(&quot;green&quot;, green);
683
                if(blue != null)filtro.addParam(&quot;blue&quot;, blue);
684
                filtro.addParam(&quot;alpha&quot;, new Integer(alpha));
685
                filtro.addParam(&quot;transparencyRed&quot;, new Integer(transparencyRed));
686
                filtro.addParam(&quot;transparencyGreen&quot;,  new Integer(transparencyGreen));
687
                filtro.addParam(&quot;transparencyBlue&quot;,  new Integer(transparencyBlue));</PRE><P>
688
&nbsp;&nbsp;&nbsp; En este momento podriamos a&ntilde;adir el filtro
689
a la pila con addFilter si no necesitara ninguna restricci&oacute;n.
690
En este caso tenemos que a&ntilde;adir c&oacute;digo para comprobar
691
que si hay filtros equivalentes no ser&aacute; necesario a&ntilde;adir
692
el nuevo o si hay varios filtros de transparencia que est&aacute;n
693
contenidos en el nuevo tendremos que eliminar estos y a&ntilde;adir
694
el nuevo.</P>
695
<PRE>                //Elimina los filtros que son equivalentes a este
696
697 2732 nacho
                for(int i=0;i&lt;filterStack.lenght();i++){
698 2248 igbrotru
                        if( filterStack.get(i) instanceof TransparencyImageFilter ||
699
                                filterStack.get(i) instanceof TransparencyShortFilter){
700
701
                                //Si este filtro es equivalente a uno de la pila se elimina este
702
                                if(((TransparencyFilter)filtro).isEquivalent((TransparencyFilter)filterStack.get(i)))
703
                                        filterStack.removeFilter(filterStack.get(i));
704
705
                        }
706
                }
707
                //A&ntilde;ade el filtro si no hay uno equivalente
708
709 2732 nacho
                boolean equivalentFilter = false;
710 2248 igbrotru
                for(int i=0;i&lt;filterStack.lenght();i++){
711
                        if( filterStack.get(i) instanceof TransparencyImageFilter ||
712
                                filterStack.get(i) instanceof TransparencyShortFilter){
713
714
                                //Si no existe en la pila un filtro equivalente se a&ntilde;ade
715
                                if(((TransparencyFilter)filterStack.get(i)).isEquivalent((TransparencyFilter)filtro)){
716
                                        equivalentFilter = true;
717
                                        break;
718
                                }
719
                        }
720
                }
721
                if(!equivalentFilter)
722
                        filterStack.addFilter(RasterFilterStackManager.transparency, filtro);
723
        }</PRE><P>
724
&nbsp;&nbsp;&nbsp; Teniendo la nueva funci&oacute;n para a&ntilde;adir
725
filtro ya podremos a&ntilde;adirlo desde un dialogo creando un
726
RasterFilterStackManager o usando uno ya creado y leyendo los
727
par&aacute;metros del filtro desde el cuadro (tambi&eacute;n podemos
728
ponerlos fijos si nos interesa). En nuestro caso:</P>
729
<PRE>stackManager.addTransparencyFilter( contentPane.getRangeRed(),  //Par&aacute;metros leidos desde el dialogo                                            contentPane.getRangeGreen(),
730
contentPane.getRangeBlue(),
731
0x10,                                                                 //Par&aacute;metros a valor fijo
732
0xff,
733
0xff,
734
0xff);</PRE><P>
735
&nbsp;&nbsp;&nbsp; Para que sea posible salvar el estado de un raster
736
cuando se salva un proyecto y se le hayan aplicado filtros es
737
necesario codificar esta posibilidad para ello deberemos crear dos
738
m&eacute;todos obligados por el interfaz en nuestro Manager. Estos
739
son:</P>
740
<PRE>        public ArrayList getStringsFromStack(RasterFilter rf);  y
741
        public void createStackFromStrings(ArrayList f, Integer pos);</PRE><P>
742
&nbsp;&nbsp;&nbsp; En el primero es para a&ntilde;adir las cadenas al
743
XML que salva el proyecto y habr&aacute; que comprobar si primero si
744
el RasterFilter pasado es instancia de este filtro que estamos
745
implementando y si lo es a&ntilde;adir las cadenas adecuadas de esta
746
forma:</P>
747
<PRE>        public ArrayList getStringsFromStack(RasterFilter rf){
748
                if(rf instanceof PruebaFilter){
749
                        filterList.add(&quot;filter.prueba.active=true&quot;);
750
                }
751
        }</PRE><P>
752
&nbsp;&nbsp;&nbsp; El segundo es para recuperar el estado de un
753
proyecto. Para ello lo primero que deberemos hacer es recuperar del
754
array el elemento analizado, comprobar que contiene la cadena que
755
representa nuestro filtro y si es as&iacute; eliminar esa entrada del
756
vector ya que ya ha sido analizada y a&ntilde;adir las acciones que
757
conllevan la adici&oacute;n de nuestro filtro. En este caso un simple
758
addPruebaFilter a&ntilde;adir&aacute; el filtro creado cuando se
759
habra un proyecto con la cadena filter.prueba.active=true.</P>
760
<PRE>        public void createStackFromStrings(ArrayList f, Integer pos){
761
                String fil = (String)f.get(pos);
762
                if(fil.startsWith(&quot;filter.prueba.active&quot;) &amp;&amp; getValue(fil).equals(&quot;true&quot;)){
763
                        filters.remove(pos.intValue());
764
                        this.addPruebaFilter();
765
                        pos = -1;
766
                }
767 2732 nacho
        }</PRE><P ALIGN=LEFT>
768
<A NAME="Interfaces"></A><STRONG><FONT SIZE=5>4.Interfaces Gr&aacute;ficas</FONT></STRONG></P>
769
<P ALIGN=LEFT><BR>&nbsp;&nbsp;&nbsp; Cresques tiene incluidas
770
interfaces gr&aacute;ficas para la gesti&oacute;n de propiedades y
771
filtros y el salvado a raster. Estas interfaces no tienen
772
funcionalidad completa sino que son paneles con los controles para
773
una recogida de datos desde la aplicaci&oacute;n cliente. El cliente
774
debe insertar estos paneles dentro de sus propios frames y gestionar
775
la recogida y escritura de datos.
776
</P>
777
<P ALIGN=LEFT><A NAME="InterfazPropiedades"></A><BR><STRONG><FONT SIZE=4>4.1
778
Interfaz de propiedades</FONT></STRONG></P>
779
<P ALIGN=LEFT>&nbsp;&nbsp;&nbsp; Para la gesti&oacute;n de los
780
controles de propiedades, el cliente deber&aacute; crear una clase
781
que herede de org.cresques.ui.raster.FilterRasterDialogPanel para
782
tener el acceso a los controles protected que tiene. Por ejemplo,
783
podemos querer incluir los paneles dentro de un frame con un bot&oacute;n
784
de Aceptar, otro de Cancelar y otro de Aplicar. Un ejemplo de lo que
785
aqu&iacute; se explica puede encontrarse en gvSIG dentro de la clase
786
com.iver.cit.gvsig.gui.panels.PropertiesRasterDialog.
787
</P>
788
<P ALIGN=LEFT>&nbsp;&nbsp;&nbsp; Si se desea gestionar la
789
restauraci&oacute;n de valores cuando se pulsa cancelar deber&aacute;
790
hacerlo en esta clase. Una posibilidad es crear una clase, por
791
ejemplo Status que guarde los valores al entrar y los restaure al
792
salir en caso que las acciones sean canceladas.</P>
793
<P ALIGN=LEFT>&nbsp;&nbsp;&nbsp; Para la traducci&oacute;n del panel
794
habr&aacute; que crear una funci&oacute;n normalmente llamada por el
795
constructor que sustituya las siguientes cadenas por el idioma que se
796
desee:</P>
797
<PRE>this.getBandSetup().getFileList().getJButtonAdd().setText(&quot;Anadir&quot;);
798
this.getBandSetup().getFileList().getJButtonRemove().setText(&ldquo;Eliminar&quot;);
799
this.getBandSetup().getFileList().lbandasVisibles.setText(&quot;bandas&quot;);
800
801
RasterTransparencyPanel tpan = this.getTransparencyPanel();
802
tpan.lGreenValue.setText(&quot;Valor verde:&quot;);
803
tpan.lRedValue.setText(&quot;Valor rojo:&quot;);
804
tpan.lBlueValue.setText(&quot;Valor azul:&quot;);
805
tpan.getTransparencyCheck().setText(&quot;transparencia&quot;);
806
tpan.getOpacityCheck().setText(&quot;opacidad&quot;);
807
tpan.lRange.setText(&quot;usar_rango: 1,3,5:8&quot;);
808
tpan.lPixelValue.setText(&quot;valor pixel: 0 a 255&quot;);
809
810
EnhancedPanel ep = this.getEnhancedPanel();
811
ep.lLineal.setText(&quot;lineal directo&quot;);
812
ep.lQueue.setText(&quot;recorte colas&quot;);
813
ep.lWithoutEnhanced.setText(&quot;sin realce&quot;);
814
ep.lCut.setText(&quot;% &quot;recorte&quot;);
815
ep.lRemove.setText(&quot;eliminar extremos&quot;);
816
817
for(int i=0;i&lt;this.getTab().getTabCount();i++){
818
        if(this.getTab().getTitleAt(i).equals(&quot;Info&quot;))
819
                this.getTab().setTitleAt(i,&quot;info&quot;);
820
        if(this.getTab().getTitleAt(i).equals(&quot;Transparencia&quot;))
821
                this.getTab().setTitleAt(i,&quot;Transparencia&quot;);
822
        if(this.getTab().getTitleAt(i).equals(&quot;Bandas&quot;))
823
                this.getTab().setTitleAt(i,&quot;bandas&quot;);
824
        if(this.getTab().getTitleAt(i).equals(&quot;Realce&quot;))
825
                this.getTab().setTitleAt(i,&quot;realce&quot;);
826
}
827
828
this.getAcceptButton().setText(&quot;Aceptar&quot;);
829
this.getApplyButton().setText(&quot;Aplicar&quot;);
830
this.getCancelButton().setText(&quot;Cancelar&quot;);</PRE><P ALIGN=LEFT>
831
&nbsp;&nbsp;&nbsp; En la gesti&oacute;n de eventos del bot&oacute;n
832
Aceptar hay que controlar el estado de cada panel a acceder a los
833
m&eacute;todos de estos para recuperar la informaci&oacute;n y poder
834
procesarla. Cada panel tiene los suyos:</P>
835
<UL>
836
        <LI><P ALIGN=LEFT STYLE="margin-bottom: 0cm; font-weight: medium"><FONT SIZE=2 STYLE="font-size: 9pt">Panel
837
        de realce:</FONT></P>
838
        <P ALIGN=LEFT STYLE="margin-bottom: 0cm; font-weight: medium"><FONT SIZE=2 STYLE="font-size: 9pt">this.getEnhancedPanel():
839
        Recupera el panel de tipo EnhancedPanel.</FONT></P>
840
        <P ALIGN=LEFT STYLE="margin-bottom: 0cm; font-weight: medium"><FONT SIZE=2 STYLE="font-size: 9pt">panel.getLinealDirectoRadioButton():
841
        Obtiene el control de selecci&oacute;n de filtro de realce.</FONT></P>
842
        <P ALIGN=LEFT STYLE="margin-bottom: 0cm; font-weight: medium"><FONT SIZE=2 STYLE="font-size: 9pt">panel.getTailCheck():
843
        Obtiene el control de selecci&oacute;n de recorte de colas.</FONT></P>
844
        <P ALIGN=LEFT STYLE="margin-bottom: 0cm; font-weight: medium"><FONT SIZE=2 STYLE="font-size: 9pt">panel.getRemoveCheck():
845
        Obtiene el control de eliminar extremos.</FONT></P>
846
        <P ALIGN=LEFT STYLE="margin-bottom: 0cm; font-weight: medium"><FONT SIZE=2 STYLE="font-size: 9pt">Panel.getTailText():
847
        Obtiene el porcentaje de recorte del cuadro de texto.</FONT></P>
848
        <LI><P ALIGN=LEFT STYLE="margin-bottom: 0cm; font-weight: medium"><FONT SIZE=2 STYLE="font-size: 9pt">Panel
849
        de transparencia:</FONT></P>
850
        <P ALIGN=LEFT STYLE="margin-bottom: 0cm">this.getTransparencyPanel():
851
        Recupera el panel de tipo TransparencyPanel.</P>
852
        <P ALIGN=LEFT STYLE="margin-bottom: 0cm">panel.getOpacityCheck():
853
        Obtiene el control de opacidad activada (nivel de traslucidez de la
854
        imagen).</P>
855
        <P ALIGN=LEFT STYLE="margin-bottom: 0cm">panel..getTransparencyCheck():
856
        Obtiene el control de transparencia activada (transparencia por
857
        rangos de pixeles).</P>
858
        <P ALIGN=LEFT STYLE="margin-bottom: 0cm">this.getRangeRed(): Obtiene
859
        los rangos de colores de pixeles de transparencia para la banda del
860
        rojo como vector de enteros.</P>
861
        <P ALIGN=LEFT STYLE="margin-bottom: 0cm">this.getRangeGreen():
862
        Obtiene los rangos de colores de pixeles de transparencia para la
863
        banda del verde como vector de enteros.</P>
864
        <P ALIGN=LEFT STYLE="margin-bottom: 0cm">this.getRangeBlue():
865
        Obtiene los rangos de colores de pixeles de transparencia para la
866
        banda del azul como vector de enteros.</P>
867
        <LI><P ALIGN=LEFT STYLE="margin-bottom: 0cm; font-weight: medium"><FONT SIZE=2 STYLE="font-size: 9pt">Panel
868
        de bandas:</FONT></P>
869
        <P ALIGN=LEFT STYLE="margin-bottom: 0cm; font-weight: medium"><FONT SIZE=2 STYLE="font-size: 9pt">this.getBandSetup():
870
        Recupera el panel de tipo BandSetup</FONT></P>
871
        <P ALIGN=LEFT STYLE="margin-bottom: 0cm">this.getAssignedBand(GeoRasterFile.RED_BAND):
872
        Obtiene la banda asignada al rojo.</P>
873
        <P ALIGN=LEFT STYLE="margin-bottom: 0cm">this.getAssignedBand(GeoRasterFile.GREEN_BAND):
874
        Obtiene la banda asignada al verde.</P>
875
        <P ALIGN=LEFT STYLE="margin-bottom: 0cm">this.getAssignedBand(GeoRasterFile.BLUE_BAND):
876
        Obtiene la banda asignada al azul.</P>
877
</UL>
878
<P ALIGN=LEFT><A NAME="InterfazSalvar"></A><STRONG><FONT SIZE=4>4.2
879
Interfaz de salvar a raster</FONT></STRONG></P>
880
<P ALIGN=LEFT>&nbsp;&nbsp;&nbsp; Para la gesti&oacute;n de los
881
controles de raster, el cliente deber&aacute; crear una clase que
882
herede de org.cresques.ui.raster.SaveRasterDialogPanel para tener el
883
acceso a los controles protected que tiene. Por ejemplo, podemos
884
querer incluir los paneles dentro de un frame con un bot&oacute;n de
885
Aceptar y otro de Cancelar. Un ejemplo de lo que aqu&iacute; se
886
explica puede encontrarse en gvSIG dentro de la clase
887
com.iver.cit.gvsig.gui.panels.SaveRasterDialog.
888
</P>
889
<P ALIGN=LEFT>&nbsp;&nbsp;&nbsp; Para la traducci&oacute;n del panel
890
habr&aacute; que crear una funci&oacute;n normalmente llamada por el
891
constructor que sustituya las siguientes cadenas por el idioma que se
892
desee:</P>
893
<PRE>DataInputSaveRaster dInput = ((SaveSetupPanel)super.getContentPanel()).getSaveParameters();
894
dInput.lSupIzq.setText(&quot;lsup izq :&quot;);
895
dInput.lInfDer.setText(&quot;linf der :&quot;);
896
dInput.lFile.setText(&quot;Fichero :&quot;);
897
dInput.lResolucion.setText(&quot;resolucion&quot;);
898
dInput.lEscala.setText(&quot;escala 1:&quot;);
899
dInput.lPpp.setText(&quot;ppp&quot;);
900
dInput.bSeleccion.setText(&quot;Seleccionar&quot;);
901
dInput.lAncho.setText(&quot;ancho.&quot;);
902 2845 nacho
dInput.lAlto.setText(&quot;alto.&quot;);</PRE><P ALIGN=LEFT>
903 2732 nacho
&nbsp;&nbsp;&nbsp; En la gesti&oacute;n de eventos del bot&oacute;n
904
Aceptar hay que controlar el estado de cada panel a acceder a los
905
m&eacute;todos de estos para recuperar la informaci&oacute;n y poder
906
procesarla.</P>
907
<P ALIGN=LEFT STYLE="margin-bottom: 0cm">(DataInputSaveRaster)((SaveSetupPanel)((SaveRasterDialogPanel)this.getContentPane()).getContentPanel()).getSaveParameters():
908
Obtiene el dialogo de tipo DataInputSaveRaster</P>
909
<P ALIGN=LEFT STYLE="margin-bottom: 0cm">dialog.getTinf_derX().getText():
910
Obtiene la coordenada X inferior derecha.</P>
911
<P ALIGN=LEFT STYLE="margin-bottom: 0cm">dialog.getTinf_derY().getText():
912
Obtiene la coordenada Y inferior derecha.</P>
913
<P ALIGN=LEFT STYLE="margin-bottom: 0cm">dialog.getTsup_izqX().getText():
914
Obtiene la coordenada X superior izquierda.</P>
915
<P ALIGN=LEFT STYLE="margin-bottom: 0cm">dialog.getTsup_izqY().getText():
916
Obtiene la coordenada Y superior izquierda.</P>
917
<P ALIGN=LEFT STYLE="margin-bottom: 0cm">((SaveSetupPanel)((SaveRasterDialogPanel)this.getContentPane()).getContentPanel()).getFileName();
918
Obtiene el nombre del fichero sobre el que se salvar&aacute;.</P>
919
<P ALIGN=LEFT STYLE="margin-bottom: 0cm">dialog.getBPropiedades():
920
Obtiene el bot&oacute;n de propiedades.</P>
921
<P ALIGN=LEFT STYLE="margin-bottom: 0cm"><BR>
922
</P>
923
<P ALIGN=LEFT STYLE="margin-bottom: 0cm">&nbsp;&nbsp;&nbsp; El bot&oacute;n
924
de propiedades de raster debe de capturarse el evento de pulsado para
925
ser procesado. Dependiendo del tipo de driver cargado har&aacute; una
926
acci&oacute;n u otra. El tipo de driver puede determinarse a trav&eacute;s
927
del texto del control, ya que este cambia cuando hemos seleccionado
928
una extensi&oacute;n de raster con &ldquo;Seleccionar&rdquo;. Este
929
bot&oacute;n de propiedades mostrar&aacute; el dialogo de propiedades
930
del driver. La configuraci&oacute;n de esta ventana es leida
931
directamente desde el mismo driver a trav&eacute;s de un texto en
932
formato XML. Para esto crearemos la ventana en una clase, por ejemplo
933 2845 nacho
SaveRasterPropsDialog que puede heredar de Jdialog en cuyo
934 2732 nacho
constructor crearemos el parser del XML y asignaremos el tama&ntilde;o
935
a nuestra ventana de esta forma:</P>
936 2845 nacho
<PRE>         String xml = writer.getXMLPropertiesDialog();
937
        if(xml!=null){
938
                CXMLParser parser = new CXMLParser(xml);
939
                widthWindow = Integer.parseInt(parser.getAttr(&quot;window&quot;,&quot;sizex&quot;));
940
                heightWindow = Integer.parseInt(parser.getAttr(&quot;window&quot;,&quot;sizey&quot;));
941
        }
942 2732 nacho
                   setContentPane(getContentPane());</PRE><P>
943
donde el writer es el driver de tipo GeoRasterWriter y contentPane es
944
un SaveRasterPropsDialogPanel. El panel de propiedades puede a&ntilde;adirse
945
de forma facil con una funci&oacute;n como esta:</P>
946
<PRE>         public Container getContentPane() {
947 2845 nacho
                if (contentPane == null) {
948
                        contentPane = new SaveRasterPropsDialogPanel(writer);
949
                }
950
                return contentPane;
951
        }</PRE><P>
952 2732 nacho
Este dialogo puede tener botones de aceptar y cancelar cuyos eventos
953
de pulsado deben ser capturados.
954
</P>
955 2248 igbrotru
</BODY>
956
</HTML>