svn-gvsig-desktop / trunk / docs / Cresques / Cresques.html @ 18386
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> </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ó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> <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> <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> </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> </P> |
||
71 | </TD>
|
||
72 | <TD WIDTH=562> |
||
73 | 2732 | nacho | <P> <A HREF="#NewFiter">3.1 Creació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> <A HREF="#ManageFilter">3.2 Gestió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á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> <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> <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ón</FONT></STRONG></P> |
120 | <P STYLE="margin-bottom: 0cm"> La librerí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é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áfica en |
||
140 | java para la gestión de filtros.
|
||
141 | </P>
|
||
142 | <LI><P STYLE="margin-bottom: 0cm">Una interfaz grá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"> Los drivers de |
||
149 | Cresques son clases que contiene un interfaz de acceso a un tipo de |
||
150 | fichero a través de una librerí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á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ía en C que debe estar
|
||
156 | también instalada y un fichero .jar con las funciones en java
|
||
157 | de acceso a la librerí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"> Los drivers de |
||
162 | lectura y escritura para un mismo tipo de fichero está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"> El nombre de la |
||
168 | clase de un driver de lectura está compuesto por el tipo de
|
||
169 | fichero al que accede seguido de la palabra File, así 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és de la librerí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"> |
||
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ón
|
||
191 | deberá incluir un bloque static en su código y añ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á con la función registerExtension. Por |
||
195 | ejemplo, si quisieramos hacer un driver para acceso a Jpg que use |
||
196 | nuestra propia librería le incluiriamos un código como |
||
197 | este:</P>
|
||
198 | <P STYLE="margin-left: 0.02cm; margin-bottom: 0cm"><BR> |
||
199 | </P>
|
||
200 | <PRE> static {
|
||
201 | registerExtension("jpg", 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"> |
||
206 | Sin necesidad de instanciar la nueva clase se ejecutará el
|
||
207 | bloque static asignando a la gestión de la extensión |
||
208 | jpg la nueva clase creada. Como esta nuevo driver heredará de
|
||
209 | GeoRasterFile tendrá el interfaz necesario para acceso a los
|
||
210 | datos por lo que no habrá ningún problema. Por lo |
||
211 | tanto, los métodos abstractos de GeoRasterFile son de
|
||
212 | obligatoria implementación en nuestro driver. Los drivers de
|
||
213 | GeoRasterFile está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"> El nombre de la |
||
220 | clase de un driver de escritura está compuesto por el tipo de
|
||
221 | fichero al que accede seguido de la palabra Writer, así
|
||
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é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"> |
||
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"> |
||
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ón deberá incluir un bloque static en |
||
247 | su código y añ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á con la función |
||
250 | registerWriterExtension. Por ejemplo, si quisieramos hacer un driver |
||
251 | de escritura en Jpg que use nuestra propia librería le
|
||
252 | incluiriamos un código como este:</P> |
||
253 | <P STYLE="margin-left: 0.02cm; margin-bottom: 0cm"><BR> |
||
254 | </P>
|
||
255 | <PRE> static {
|
||
256 | registerWriterExtension("jpg", 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"> Dentro |
||
261 | del driver tendremos que escribir una clase que deberá
|
||
262 | llamarse <NombreFormato>SupportOptions y que deberá |
||
263 | heredar de WriterSupportOptions. Esta clase contendrá las
|
||
264 | opciones de escritura concretas para este formato. Esta opciones son |
||
265 | las que el usuario visualizará en la ventana de propiedades de
|
||
266 | escritura. Es conveniente que las opciones que corresponderan a una |
||
267 | lista de selección (combo) se guarden aquí 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 = {"NONE","UINT8","YUV","MULTI","RGB"};</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á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"> Deben |
||
277 | crearse mé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á vacio en funcionalidades pero llamará |
||
283 | al constructor del padre pasando como parámetro un string que
|
||
284 | identifica al driver.</FONT></FONT></P> |
||
285 | <PRE> <FONT FACE="Nimbus Mono L">EcwSupportOptions(){</FONT> |
||
286 | super("Ecw"); |
||
287 | }</PRE><P ALIGN=LEFT STYLE="margin-bottom: 0cm; text-decoration: none"> |
||
288 | Constructor sin parámetros:</P> |
||
289 | <P ALIGN=LEFT STYLE="margin-bottom: 0cm"><BR> |
||
290 | </P>
|
||
291 | <P ALIGN=LEFT STYLE="margin-bottom: 0cm; text-decoration: none"> |
||
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 = "ecw"; |
||
298 | this.support.setBlockSize(64); |
||
299 | this.support.setCompressionDefault(10); |
||
300 | this.support.setFormatDefault(4); |
||
301 | this.support.setWriteGeoref(true); |
||
302 | this.ident = "Ecw"; |
||
303 | this.consulta = true; |
||
304 | |||
305 | }</PRE><P ALIGN=LEFT STYLE="margin-bottom: 0cm; text-decoration: none"> |
||
306 | 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 | Para este constructor se ha de pasar como |
||
312 | parámetro el PxRaster de la imagen que se desea salvar a
|
||
313 | disco. Se inicializará la clase xxxSupportOptions de la misma
|
||
314 | forma que en el constructor anterior y se asignarán valores a
|
||
315 | variables de instancia con datos para salvar a raster tales como |
||
316 | georeferenciación, número de bandas, ancho, alto, |
||
317 | tamañ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 | Los drivers de escritura diseñan su propia |
||
322 | ventana de propiedades en java. Para ello tiene un método
|
||
323 | getXMLPropertiesDialog que dice como será esta ventana. Para
|
||
324 | ello debe devolver una cadena de texto con un XML que contiene esta |
||
325 | configuración. El Xml deberá comenzar definiendo el |
||
326 | tamaño de la ventana de esta forma:</P> |
||
327 | <PRE><window sizex="340" sizey="180"> |
||
328 | ... Cuerpo de la ventana ... |
||
329 | </window></PRE><P STYLE="margin-left: 0.02cm"> |
||
330 | <SPAN STYLE="text-decoration: none"> </SPAN>Dentro |
||
331 | del cuerpo de la ventana deberán definirse los panels con los
|
||
332 | componentes. Solo está permitido un nivel de anidamiento y el
|
||
333 | 2845 | nacho | uso de Checkbox, labels, combos, sliders. |
334 | 2732 | nacho | </P>
|
335 | <PRE><panel sizex="330" sizey="170" layout="FlowLayout" border="yes" > |
||
336 | </panel> |
||
337 | |||
338 | <label>Tamaño bloque: |
||
339 | </label> |
||
340 | |||
341 | <combo ident="BLOCKSIZE" selected="64"> |
||
342 | <elem>32</elem> |
||
343 | <elem>64</elem> |
||
344 | <elem>128</elem> |
||
345 | </combo> |
||
346 | |||
347 | <check ident="GEOREF" selected="10”> |
||
348 | 2845 | nacho | </check></PRE><P> |
349 | <SPAN STYLE="text-decoration: none"> </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á
|
||
354 | una clase EcwSupportOptions con las opciones especificas de salvado. |
||
355 | </P>
|
||
356 | <P STYLE="margin-left: 0.02cm; text-decoration: none"> |
||
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étodo
|
||
362 | es rapido y directo para la conversión de unos formatos
|
||
363 | raster a otros. Para esta forma se usa el mé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étodo dataWrite. En la construcción del filtro se |
||
367 | especificará el tamaño de la imagen de salida, nombre |
||
368 | de la misma, coordenadas de georeferenciación, compresión |
||
369 | si la hubiere, ... Cuando se invoca el método dataWrite
|
||
370 | solicitará 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ó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étodo
|
||
381 | readData. Este servidor de datos se pasará en el constructor
|
||
382 | del driver de escritura y lo utilizará 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á
|
||
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ón, se leen
|
||
389 | los datos desde un image y se devuelven en forma de array de |
||
390 | enteros. Será el driver el que escriba a disco ese array. En
|
||
391 | general, si se necesita hacer uso de salvar a raster se deberá
|
||
392 | escribir una clase como Rasterizer para el caso concreto que estamos |
||
393 | tratando. GvSIG hace uso de esta funcionalidad a travé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ño de
|
||
399 | bloque que el usuario podrí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ón |
||
404 | 2248 | igbrotru | de un nuevo filtro</FONT></STRONG></P> |
405 | <P STYLE="margin-left: 0.02cm"> Crear una nueva |
||
406 | clase abstracta que heredará de RasterFilter y que tendrá |
||
407 | como nombre el nombre del filtro (en inglés a poder ser)
|
||
408 | seguido de Filter. Usaremos como ejemplo la generación del
|
||
409 | filtro de transparencia. En este caso, esta clase abstracta debe |
||
410 | llamarse TransparencyFilter. |
||
411 | </P>
|
||
412 | <P> Crear una clase que hereda de esta clase que |
||
413 | hemos creado para cada tipo de dato bá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ágenes
|
||
418 | de 16 bits.Estas últimas están representadas por una |
||
419 | clase llamada RasterBuf. Si fuera necesario debería hacerse
|
||
420 | para Float, Double, ... |
||
421 | </P>
|
||
422 | <P> El constructor de los filtros es recomendable |
||
423 | que esté vacio.</P> |
||
424 | <P> En la clase base del filtro que estamos creando |
||
425 | (TransparencyFilter) deben ponerse las variables de instancia que |
||
426 | contengan los pará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á blanco, es decir
|
||
431 | totalmente transparente y sin ninguna tonalidad.</P>
|
||
432 | <P> Aquí deben ponerse tambié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étodos abstractos obligará a |
||
436 | implementar estos. Si es necesario que estos métodos
|
||
437 | abstractos tengan código podemos implementarlos aquí |
||
438 | sino podrá hacerse en las clases hijas que contienen la
|
||
439 | especificación para el filtro de transparencia sobre cada tipo
|
||
440 | de dato concreto. Los mé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> Aquí pondremos las operaciones que hay |
||
446 | que realizar antes de ejecutar el filtro que estamos creando. En |
||
447 | nuestro caso está implementado en la clase base del filtro y
|
||
448 | en las hijas . En la clase base tiene código común para |
||
449 | los filtros de transparencia de cualquier tipo de datos.</P>
|
||
450 | <PRE> public void pre(){
|
||
451 | this.rangesR = (int[][])params.get("red"); |
||
452 | this.rangesG = (int[][])params.get("green"); |
||
453 | this.rangesB = (int[][])params.get("blue"); |
||
454 | this.alpha = ((Integer)params.get("alpha")).intValue(); |
||
455 | this.transparencyColorRed = ((Integer)params.get("transparencyRed")).intValue(); |
||
456 | this.transparencyColorGreen = ((Integer)params.get("transparencyGreen")).intValue(); |
||
457 | this.transparencyColorBlue = ((Integer)params.get("transparencyBlue")).intValue(); |
||
458 | }</PRE><P> |
||
459 | En las clases hijas se pone la implementación |
||
460 | concreta para ese tipo de dato. En el caso de la transparencia sobre |
||
461 | un Image obtenemos el pará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("raster"); |
||
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> Aquí se ponen las operaciones a realizar |
||
474 | después de ejecutar el filtro. En el caso que estamos viendo
|
||
475 | no es necesario hacer nada por lo que estará vacio. Podria ser
|
||
476 | necesario alguna operación como por ejemplo cargar el
|
||
477 | resultado de la operación en alguna variable de salida o algo
|
||
478 | así.</P> |
||
479 | <UL>
|
||
480 | <LI><P><B>abstract public void process(int x, int y);</B></P> |
||
481 | </UL>
|
||
482 | <P> Este mé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á lo siguiente:</P> |
||
486 | <PRE> pre();
|
||
487 | for (int y=0; y<height; y=y+incY)
|
||
488 | for (int x=0; x<width; x=x+incX) {
|
||
489 | process(x, y); |
||
490 | } |
||
491 | post();</PRE><P> |
||
492 | Por esto debemos tener en process el có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á el
|
||
496 | siguiente código:</P> |
||
497 | <PRE> public void process(int x, int y) {
|
||
498 | int pt = ((BufferedImage) image).getRGB(x,y); |
||
499 | int []px4 = {(pt & 0xff000000) >> 24,(pt & 0xff0000) >> 16, (pt & 0x00ff00) >> 8, (pt & 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] << 24) & 0xff000000 | (px4[1] << 16) & 0x00ff0000 | |
||
508 | (px4[2] << 8) & 0x0000ff00 | (px4[3] & 0x0000ff) )); |
||
509 | }</PRE><P> |
||
510 | <BR><BR> |
||
511 | </P>
|
||
512 | <P> Esta función obtendrá el pixel |
||
513 | del buffer lo procesará y salvará 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> Esta función realizará el mismo |
||
519 | proceso que process(int x, int y) pero aplicada directamente a una |
||
520 | línea del buffer.</P> |
||
521 | <UL>
|
||
522 | <LI><P><B>abstract public int getInRasterDataType();</B></P> |
||
523 | </UL>
|
||
524 | <P> 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í:</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> 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í:
|
||
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> Obtiene el resultado del filtro en un Object. |
||
544 | Para esto se la pasa un parámetro con la clave del resultado y
|
||
545 | nos devolverá 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á
|
||
550 | una función por tipo de dato tal que:</P> |
||
551 | <PRE> public Object getResult(String name){
|
||
552 | if(name.equals("raster")) |
||
553 | return (Object)this.image; |
||
554 | else |
||
555 | return null; |
||
556 | <FONT SIZE=2 STYLE="font-size: 9pt">}</FONT></PRE><P> |
||
557 | 2732 | nacho | Esta es la que se hará para |
558 | TransparencyImageFilter ya que devuelve un tipo Image.</P>
|
||
559 | <P><A NAME="ManageFilter"></A><BR> <BR><STRONG><FONT SIZE=4>3.2 |
||
560 | Gestión de un nuevo filtro</FONT></STRONG></P> |
||
561 | 2248 | igbrotru | <P> 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ón de un nuevo filtro esta
|
||
565 | clase no debe tocarse. Sin embargo si debe añadirse la gestión |
||
566 | del nuevo filtro con filterStackManager . Para añadir este
|
||
567 | nuevo filtro deberá crearse una nueva clase que heredará |
||
568 | de RasterFilterStackManager. RasterFilter esla encargada de añadir
|
||
569 | filtros a la pila ya que ella es la que sabrá 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ó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> Este nuevo gestor de filtros deberá |
||
576 | implementar la interfaz StackManager de forma que la definición
|
||
577 | de nuestra nueva clase sería más o menos asi:</P> |
||
578 | <PRE>public class PruebaStackManager extends RasterFilterStackManager implements StackManager{
|
||
579 | ... |
||
580 | }</PRE><P> |
||
581 | Para el nuevo filtro debe añadirse en esta |
||
582 | nueva clase una constante que represente el tipo del nuevo filtro. Lo |
||
583 | más lógico es darle un número de orden |
||
584 | consecutivo a las que hay pero podrí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 | El vector order de RasterFilterStackManager |
||
593 | contiene la forma de ordenació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é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é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("prueba", PruebaStackManager.prueba, 2); |
||
603 | }</PRE><P> |
||
604 | <BR><BR> |
||
605 | </P>
|
||
606 | <P> Habrá que elegir una posición |
||
607 | para el nuevo filtro creado para que produzca el resultado deseado. |
||
608 | La función addTypeFilter tendrá como parámetros |
||
609 | en nombre del filtro, constante asignada y posición para la
|
||
610 | ordenación. Si introducimos el nuevo filtro en la posición |
||
611 | 3 la ordenación inicial:</P> |
||
612 | <PRE STYLE="margin-bottom: 0.5cm">computeminmax, tail, enhanced, transparency </PRE><P> |
||
613 | <BR><BR> |
||
614 | </P>
|
||
615 | <P>quedará |
||
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ón en el vector de ordenación tiene |
||
621 | en cuenta la posición 0.</P> |
||
622 | <P> En RasterFilterStackManager también |
||
623 | existe una función llamada getType que devuelve el tipo de
|
||
624 | filtro que contiene un RasterFilter. Deberemos añadir el
|
||
625 | nuestro para una correcta gestión. Para ello sobrescribiremos
|
||
626 | el método getType de esta forma:</P> |
||
627 | 2732 | nacho | <PRE> public int getType(RasterFilter rasterFilter){
|
628 | 2248 | igbrotru | if(rasterFilter instanceof <<NuestoFiltro>>) |
629 | return PruebaStackManager.<<Nuestra constante>>; |
||
630 | |||
631 | return super.getType(rasterFilter); |
||
632 | }</PRE><P> |
||
633 | <BR><BR> |
||
634 | </P>
|
||
635 | <P>sustituyendo <<NuestroFiltro>> por el nombre de la |
||
636 | clase abstracta base del filtro que hemos construido y <<Nuestra |
||
637 | constante>> por la constante que representa nuestro filtro.</P> |
||
638 | <P> Dentro de nuestra clase habrá que |
||
639 | definir una función para añadir el nuevo filtro. Esta |
||
640 | función debe tener como argumentos los pará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> En esta función hay que hacer algunas |
||
645 | acciones obligatorias y otras opcionales. Podemos verlas sobre un |
||
646 | ejemplo:</P>
|
||
647 | <P> Cabecera de la funció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 | 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é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ón de la pila calculará |
||
664 | en que posición debe ir el filtro y que tipo de dato devuelve
|
||
665 | el que tendrá por encima, por lo tanto sabremos de que tipo es
|
||
666 | el filtro que debemos crear. Podemos hacer la selecció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("transparency")).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> Si tiene parámetros deberemos añadirlos |
||
678 | al filtro creado con addParam. Cada parámetro debe ser añadido |
||
679 | con una clave. Esta debe coincidir con la que definimos para su |
||
680 | recuperación en el método pre() del filtro.</P> |
||
681 | 2732 | nacho | <PRE> if(red != null)filtro.addParam("red", red); |
682 | 2248 | igbrotru | if(green != null)filtro.addParam("green", green); |
683 | if(blue != null)filtro.addParam("blue", blue); |
||
684 | filtro.addParam("alpha", new Integer(alpha)); |
||
685 | filtro.addParam("transparencyRed", new Integer(transparencyRed)); |
||
686 | filtro.addParam("transparencyGreen", new Integer(transparencyGreen)); |
||
687 | filtro.addParam("transparencyBlue", new Integer(transparencyBlue));</PRE><P> |
||
688 | En este momento podriamos añadir el filtro |
||
689 | a la pila con addFilter si no necesitara ninguna restricción.
|
||
690 | En este caso tenemos que añadir código para comprobar |
||
691 | que si hay filtros equivalentes no será necesario añadir |
||
692 | el nuevo o si hay varios filtros de transparencia que están
|
||
693 | contenidos en el nuevo tendremos que eliminar estos y añadir
|
||
694 | el nuevo.</P>
|
||
695 | <PRE> //Elimina los filtros que son equivalentes a este
|
||
696 | |||
697 | 2732 | nacho | for(int i=0;i<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ñade el filtro si no hay uno equivalente
|
||
708 | |||
709 | 2732 | nacho | boolean equivalentFilter = false; |
710 | 2248 | igbrotru | for(int i=0;i<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ñ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 | Teniendo la nueva función para añadir |
||
725 | filtro ya podremos añadirlo desde un dialogo creando un
|
||
726 | RasterFilterStackManager o usando uno ya creado y leyendo los |
||
727 | parámetros del filtro desde el cuadro (también podemos |
||
728 | ponerlos fijos si nos interesa). En nuestro caso:</P>
|
||
729 | <PRE>stackManager.addTransparencyFilter( contentPane.getRangeRed(), //Parámetros leidos desde el dialogo contentPane.getRangeGreen(), |
||
730 | contentPane.getRangeBlue(), |
||
731 | 0x10, //Parámetros a valor fijo
|
||
732 | 0xff, |
||
733 | 0xff, |
||
734 | 0xff);</PRE><P> |
||
735 | 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é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 | En el primero es para añadir las cadenas al |
||
743 | XML que salva el proyecto y habrá que comprobar si primero si
|
||
744 | el RasterFilter pasado es instancia de este filtro que estamos |
||
745 | implementando y si lo es añadir las cadenas adecuadas de esta
|
||
746 | forma:</P>
|
||
747 | <PRE> public ArrayList getStringsFromStack(RasterFilter rf){
|
||
748 | if(rf instanceof PruebaFilter){ |
||
749 | filterList.add("filter.prueba.active=true"); |
||
750 | } |
||
751 | }</PRE><P> |
||
752 | 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í eliminar esa entrada del
|
||
756 | vector ya que ya ha sido analizada y añadir las acciones que
|
||
757 | conllevan la adición de nuestro filtro. En este caso un simple
|
||
758 | addPruebaFilter añadirá 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("filter.prueba.active") && getValue(fil).equals("true")){ |
||
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áficas</FONT></STRONG></P> |
||
769 | <P ALIGN=LEFT><BR> Cresques tiene incluidas |
||
770 | interfaces gráficas para la gestió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ó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> Para la gestión de los |
||
780 | controles de propiedades, el cliente deberá 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ón
|
||
784 | de Aceptar, otro de Cancelar y otro de Aplicar. Un ejemplo de lo que |
||
785 | aquí se explica puede encontrarse en gvSIG dentro de la clase
|
||
786 | com.iver.cit.gvsig.gui.panels.PropertiesRasterDialog. |
||
787 | </P>
|
||
788 | <P ALIGN=LEFT> Si se desea gestionar la |
||
789 | restauración de valores cuando se pulsa cancelar deberá |
||
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> Para la traducción del panel |
||
794 | habrá que crear una funció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("Anadir"); |
||
798 | this.getBandSetup().getFileList().getJButtonRemove().setText(“Eliminar"); |
||
799 | this.getBandSetup().getFileList().lbandasVisibles.setText("bandas"); |
||
800 | |||
801 | RasterTransparencyPanel tpan = this.getTransparencyPanel(); |
||
802 | tpan.lGreenValue.setText("Valor verde:"); |
||
803 | tpan.lRedValue.setText("Valor rojo:"); |
||
804 | tpan.lBlueValue.setText("Valor azul:"); |
||
805 | tpan.getTransparencyCheck().setText("transparencia"); |
||
806 | tpan.getOpacityCheck().setText("opacidad"); |
||
807 | tpan.lRange.setText("usar_rango: 1,3,5:8"); |
||
808 | tpan.lPixelValue.setText("valor pixel: 0 a 255"); |
||
809 | |||
810 | EnhancedPanel ep = this.getEnhancedPanel(); |
||
811 | ep.lLineal.setText("lineal directo"); |
||
812 | ep.lQueue.setText("recorte colas"); |
||
813 | ep.lWithoutEnhanced.setText("sin realce"); |
||
814 | ep.lCut.setText("% "recorte"); |
||
815 | ep.lRemove.setText("eliminar extremos"); |
||
816 | |||
817 | for(int i=0;i<this.getTab().getTabCount();i++){
|
||
818 | if(this.getTab().getTitleAt(i).equals("Info")) |
||
819 | this.getTab().setTitleAt(i,"info"); |
||
820 | if(this.getTab().getTitleAt(i).equals("Transparencia")) |
||
821 | this.getTab().setTitleAt(i,"Transparencia"); |
||
822 | if(this.getTab().getTitleAt(i).equals("Bandas")) |
||
823 | this.getTab().setTitleAt(i,"bandas"); |
||
824 | if(this.getTab().getTitleAt(i).equals("Realce")) |
||
825 | this.getTab().setTitleAt(i,"realce"); |
||
826 | } |
||
827 | |||
828 | this.getAcceptButton().setText("Aceptar"); |
||
829 | this.getApplyButton().setText("Aplicar"); |
||
830 | this.getCancelButton().setText("Cancelar");</PRE><P ALIGN=LEFT> |
||
831 | En la gestión de eventos del botón |
||
832 | Aceptar hay que controlar el estado de cada panel a acceder a los |
||
833 | métodos de estos para recuperar la informació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ó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ó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> Para la gestión de los |
||
881 | controles de raster, el cliente deberá 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ón de
|
||
885 | Aceptar y otro de Cancelar. Un ejemplo de lo que aquí 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> Para la traducción del panel |
||
890 | habrá que crear una funció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("lsup izq :"); |
||
895 | dInput.lInfDer.setText("linf der :"); |
||
896 | dInput.lFile.setText("Fichero :"); |
||
897 | dInput.lResolucion.setText("resolucion"); |
||
898 | dInput.lEscala.setText("escala 1:"); |
||
899 | dInput.lPpp.setText("ppp"); |
||
900 | dInput.bSeleccion.setText("Seleccionar"); |
||
901 | dInput.lAncho.setText("ancho."); |
||
902 | 2845 | nacho | dInput.lAlto.setText("alto.");</PRE><P ALIGN=LEFT> |
903 | 2732 | nacho | En la gestión de eventos del botón |
904 | Aceptar hay que controlar el estado de cada panel a acceder a los |
||
905 | métodos de estos para recuperar la informació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á.</P> |
||
919 | <P ALIGN=LEFT STYLE="margin-bottom: 0cm">dialog.getBPropiedades(): |
||
920 | Obtiene el botón de propiedades.</P> |
||
921 | <P ALIGN=LEFT STYLE="margin-bottom: 0cm"><BR> |
||
922 | </P>
|
||
923 | <P ALIGN=LEFT STYLE="margin-bottom: 0cm"> El botón |
||
924 | de propiedades de raster debe de capturarse el evento de pulsado para |
||
925 | ser procesado. Dependiendo del tipo de driver cargado hará una
|
||
926 | acción u otra. El tipo de driver puede determinarse a través |
||
927 | del texto del control, ya que este cambia cuando hemos seleccionado |
||
928 | una extensión de raster con “Seleccionar”. Este |
||
929 | botón de propiedades mostrará el dialogo de propiedades |
||
930 | del driver. La configuración de esta ventana es leida
|
||
931 | directamente desde el mismo driver a travé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ñ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("window","sizex")); |
||
940 | heightWindow = Integer.parseInt(parser.getAttr("window","sizey")); |
||
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ñadirse
|
||
945 | de forma facil con una funció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> |