svn-gvsig-desktop / tags / Root_v061 / libraries / libCq CMS for java.old / src / org / cresques / io / raster / SharpeningImageFilter.java @ 4812
History | View | Annotate | Download (13.8 KB)
1 | 3578 | nacho | /*
|
---|---|---|---|
2 | * Cresques Mapping Suite. Graphic Library for constructing mapping applications.
|
||
3 | *
|
||
4 | * Copyright (C) 2004-5.
|
||
5 | *
|
||
6 | * This program is free software; you can redistribute it and/or
|
||
7 | * modify it under the terms of the GNU General Public License
|
||
8 | * as published by the Free Software Foundation; either version 2
|
||
9 | * of the License, or (at your option) any later version.
|
||
10 | *
|
||
11 | * This program is distributed in the hope that it will be useful,
|
||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
14 | * GNU General Public License for more details.
|
||
15 | *
|
||
16 | * You should have received a copy of the GNU General Public License
|
||
17 | * along with this program; if not, write to the Free Software
|
||
18 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,USA.
|
||
19 | *
|
||
20 | * For more information, contact:
|
||
21 | *
|
||
22 | * cresques@gmail.com
|
||
23 | */
|
||
24 | package org.cresques.io.raster; |
||
25 | |||
26 | import java.awt.Dimension; |
||
27 | import java.awt.Graphics2D; |
||
28 | import java.awt.Image; |
||
29 | import java.awt.image.BufferedImage; |
||
30 | import java.awt.image.PixelGrabber; |
||
31 | |||
32 | import org.cresques.geo.ViewPortData; |
||
33 | import org.cresques.io.GeoRasterFile; |
||
34 | import org.cresques.px.PxRaster; |
||
35 | |||
36 | |||
37 | /**
|
||
38 | * Filtro de sharpening que se aplica sobre la vista. Tiene como entradas el objeto Image
|
||
39 | * con las bandas del raster visualizadas en la Vista y la banda pancrom?tica. A partir de
|
||
40 | * estas entradas genera un Image de salida como la que hay pero de resoluci?n igual a la
|
||
41 | * de la pancrom?tica.
|
||
42 | * @author Nacho Brodin (brodin_ign@gva.es)
|
||
43 | *
|
||
44 | */
|
||
45 | public class SharpeningImageFilter extends SharpeningFilter { |
||
46 | |||
47 | //Variable que dice para cada pixel de la imagen de entrada cuantos de salida hay.
|
||
48 | private int nOutputPixelsPerInputPixel; |
||
49 | //Vector con los desplazamientos de los pixeles de salida dentro del vector
|
||
50 | private int[] outKernel; |
||
51 | //Kernel aplicado a la pancromatica
|
||
52 | private Kernel kernel = null; |
||
53 | private PixelGrabber pgAct = null, pgPrev = null, pgNext = null; |
||
54 | int[] bufferPrev = null, bufferAct = null, bufferNext = null; |
||
55 | |||
56 | /**
|
||
57 | * Constructor
|
||
58 | *
|
||
59 | */
|
||
60 | public SharpeningImageFilter() {
|
||
61 | super();
|
||
62 | } |
||
63 | |||
64 | /**
|
||
65 | * Validamos que haya alguna otra banda adem?s de la pancrom?tica y que la pancrom?tica
|
||
66 | * sea de mayor resoluci?n que las dem?s.
|
||
67 | */
|
||
68 | private void checkInput(){ |
||
69 | exec = true;
|
||
70 | if(heightMultiespec >= heightPancr || widthMultiespec >= widthPancr || heightMultiespec == 0 || widthMultiespec == 0) |
||
71 | exec = false;
|
||
72 | for(int i=0;i<files.length;i++){ |
||
73 | if(i != posPancromatica){
|
||
74 | if(files[i].getHeight() != heightMultiespec || files[i].getWidth() != widthMultiespec){
|
||
75 | exec = false;
|
||
76 | break;
|
||
77 | } |
||
78 | } |
||
79 | } |
||
80 | } |
||
81 | |||
82 | /**
|
||
83 | * Carga los par?metros pasados al filtro en las variables de
|
||
84 | * instancia que corresponde,
|
||
85 | */
|
||
86 | private void loadParam(){ |
||
87 | //Carga de parametros
|
||
88 | this.image = (Image) params.get("raster"); |
||
89 | posPancromatica = ((Integer) params.get("pancromatica")).intValue(); |
||
90 | files = (GeoRasterFile[]) params.get("files"); |
||
91 | bandOrder = (int[]) params.get("order"); |
||
92 | alpha = ((Integer) params.get("alpha")).intValue(); |
||
93 | method = (String) params.get("method"); |
||
94 | coef = ((Double) params.get("coef")).doubleValue(); |
||
95 | coefBrovey = ((Integer) params.get("coefBrovey")).intValue(); |
||
96 | |||
97 | //Asignamos el nombre de la banda pancrom?tica como par?metro para que cuando
|
||
98 | //volvamos a abrir el dialogo pueda recuperarse y seleccionarse en el cuadro
|
||
99 | 4160 | nacho | pancrName = files[posPancromatica].getName().substring( |
100 | files[posPancromatica].getName().lastIndexOf("/")+1, |
||
101 | files[posPancromatica].getName().length()); |
||
102 | this.addParam("pancrName", pancrName); |
||
103 | 3578 | nacho | |
104 | height = image.getHeight(null);
|
||
105 | width = image.getWidth(null);
|
||
106 | heightPancr = files[posPancromatica].getHeight(); |
||
107 | widthPancr = files[posPancromatica].getWidth(); |
||
108 | for(int i=0;i<files.length;i++){ |
||
109 | if(i != posPancromatica){
|
||
110 | heightMultiespec = files[i].getHeight(); |
||
111 | widthMultiespec = files[i].getWidth(); |
||
112 | } |
||
113 | } |
||
114 | |||
115 | relX = (int)widthPancr/widthMultiespec;
|
||
116 | relY = (int)heightPancr/heightMultiespec;
|
||
117 | } |
||
118 | |||
119 | /* (non-Javadoc)
|
||
120 | * @see org.cresques.io.raster.IRasterFilter#pre()
|
||
121 | */
|
||
122 | public void pre() { |
||
123 | |||
124 | loadParam(); |
||
125 | checkInput(); |
||
126 | |||
127 | //Creamos el buffer donde se pinta la pancromatica
|
||
128 | |||
129 | imagePancr = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); |
||
130 | Graphics2D graphicsPancr = (Graphics2D)imagePancr.getGraphics(); |
||
131 | PxRaster rasterPancr = new PxRaster(files[posPancromatica], null, files[posPancromatica].getView()); |
||
132 | |||
133 | rasterPancr.setBand(GeoRasterFile.RED_BAND, 0);
|
||
134 | rasterPancr.setBand(GeoRasterFile.GREEN_BAND, 1);
|
||
135 | rasterPancr.setBand(GeoRasterFile.BLUE_BAND, 2);
|
||
136 | |||
137 | ViewPortData vp = (ViewPortData)viewPortData.clone(); |
||
138 | vp.zoom(extent); |
||
139 | rasterPancr.draw(graphicsPancr, vp); |
||
140 | rasterPancr = null;
|
||
141 | |||
142 | //Creamos el buffer donde se pinta la imagen de entrada
|
||
143 | |||
144 | imageMultiespec = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); |
||
145 | Graphics2D graphicsMultiespec = (Graphics2D)imageMultiespec.getGraphics(); |
||
146 | PxRaster rasterMultiespec = null;
|
||
147 | boolean first = true; |
||
148 | for(int i = 0;i<files.length;i++){ |
||
149 | if(first){
|
||
150 | rasterMultiespec = new PxRaster(files[i], null, files[posPancromatica].getView()); |
||
151 | first = false;
|
||
152 | }else
|
||
153 | rasterMultiespec.addFile(files[i].getName()); |
||
154 | } |
||
155 | |||
156 | rasterMultiespec.setBand(GeoRasterFile.RED_BAND, bandOrder[0]);
|
||
157 | rasterMultiespec.setBand(GeoRasterFile.GREEN_BAND, bandOrder[1]);
|
||
158 | rasterMultiespec.setBand(GeoRasterFile.BLUE_BAND, bandOrder[2]);
|
||
159 | |||
160 | rasterMultiespec.draw(graphicsMultiespec, vp); |
||
161 | rasterMultiespec = null;
|
||
162 | |||
163 | super.pre();
|
||
164 | } |
||
165 | |||
166 | /**
|
||
167 | * Aplica la operaci?n de refinamiento sobre el buffer Multiespectral que contiene
|
||
168 | * el RGB que es pasado por par?metro utilizando la pancrom?tica.
|
||
169 | * @param bufferInput Buffer rgb
|
||
170 | * @param length longitud del buffer de la pancromatica utilizado
|
||
171 | * @param iLine l?nea leida de la imagen multiespectral
|
||
172 | * @return buffer con el resultado de la operaci?n
|
||
173 | */
|
||
174 | private int[] processBrovey(int[] bufferInput, int iLine){ |
||
175 | double[] hsl; |
||
176 | int[] rgb; |
||
177 | PixelGrabber pg = null; |
||
178 | |||
179 | //Longitud del buffer de salida
|
||
180 | int widthDst = width * relX;
|
||
181 | //Buffer de salida
|
||
182 | int[] bufferPancr = new int[width]; |
||
183 | |||
184 | pg = new PixelGrabber(imagePancr, 0, iLine, width, 1, bufferPancr , 0, width); |
||
185 | |||
186 | |||
187 | try {
|
||
188 | pg.grabPixels(); |
||
189 | } catch (InterruptedException e) { |
||
190 | e.printStackTrace(); |
||
191 | } |
||
192 | |||
193 | for(int iElem=0; iElem<width; iElem++){ |
||
194 | int r = ((bufferInput[iElem] >> 16) & 0xff); |
||
195 | int g = ((bufferInput[iElem] >> 8) & 0xff); |
||
196 | int b = (bufferInput[iElem] & 0xff); |
||
197 | byte i = (byte)((bufferPancr[iElem] >> 16) & 0xff); |
||
198 | double scale = (3.0*(i+coefBrovey))/(r+g+b+1.0); |
||
199 | r *= scale;g *= scale;b *= scale; |
||
200 | bufferPancr[iElem] = ((alpha << 24) & 0xff000000) | |
||
201 | ((r << 16) & 0x00ff0000)| |
||
202 | ((g << 8) & 0x0000ff00) | |
||
203 | (b & 0x000000ff);
|
||
204 | } |
||
205 | return bufferPancr;
|
||
206 | |||
207 | } |
||
208 | |||
209 | /**
|
||
210 | * Aplica la operaci?n de refinamiento sobre el buffer Multiespectral que contiene
|
||
211 | * el RGB que es pasado por par?metro utilizando la pancrom?tica.
|
||
212 | * @param bufferInput Buffer rgb
|
||
213 | * @param length longitud del buffer de la pancromatica utilizado
|
||
214 | * @param iLine l?nea leida de la imagen multiespectral
|
||
215 | * @return buffer con el resultado de la operaci?n
|
||
216 | */
|
||
217 | private int[] processKernel(int[] bufferInput, int iLine){ |
||
218 | int[] bufferDst = new int[width]; |
||
219 | |||
220 | if(iLine != 0){ |
||
221 | bufferPrev = bufferAct; |
||
222 | bufferAct = bufferNext; |
||
223 | }else{
|
||
224 | bufferPrev = null;
|
||
225 | bufferAct = new int[width]; |
||
226 | pgAct = new PixelGrabber(imagePancr, 0, iLine, width, 1, bufferAct , 0, width); |
||
227 | try {
|
||
228 | pgAct.grabPixels(); |
||
229 | } catch (InterruptedException e) {e.printStackTrace();} |
||
230 | } |
||
231 | |||
232 | if(iLine != (height - 1)){ |
||
233 | bufferNext = new int[width]; |
||
234 | pgNext = new PixelGrabber(imagePancr, 0, iLine + 1, width, 1, bufferNext , 0, width); |
||
235 | try {
|
||
236 | pgNext.grabPixels(); |
||
237 | } catch (InterruptedException e) {e.printStackTrace();} |
||
238 | }else
|
||
239 | bufferNext = null;
|
||
240 | |||
241 | |||
242 | for(int iElem=0; iElem<width; iElem++){ |
||
243 | int a = ((bufferInput[iElem] >> 24) & 0xff); |
||
244 | int r = ((bufferInput[iElem] >> 16) & 0xff); |
||
245 | int g = ((bufferInput[iElem] >> 8) & 0xff); |
||
246 | int b = (bufferInput[iElem] & 0xff); |
||
247 | |||
248 | float[][] op = new float[3][3]; |
||
249 | if(bufferPrev != null){ |
||
250 | if(iElem != 0)op[0][0] = (bufferPrev[iElem - 1] & 0x000000ff); |
||
251 | op[0][1] = (bufferPrev[iElem] & 0x000000ff); |
||
252 | if(iElem != (width -1))op[0][2] = (bufferPrev[iElem + 1] & 0x000000ff); |
||
253 | } |
||
254 | if(iElem != 0)op[1][0] = (bufferAct[iElem - 1] & 0x000000ff); |
||
255 | op[1][1] = (bufferAct[iElem] & 0x000000ff); |
||
256 | if(iElem != (width -1))op[1][2] = (bufferAct[iElem + 1] & 0x000000ff); |
||
257 | if(bufferNext != null){ |
||
258 | if(iElem != 0)op[2][0] = (bufferNext[iElem - 1] & 0x000000ff); |
||
259 | op[2][1] = (bufferNext[iElem] & 0x000000ff); |
||
260 | if(iElem != (width -1))op[2][2] = (bufferNext[iElem + 1] & 0x000000ff); |
||
261 | } |
||
262 | Kernel operando = new Kernel(op); |
||
263 | double i = kernel.kernelOperation(operando) * 0.15; |
||
264 | r += i; |
||
265 | g += i; |
||
266 | b += i; |
||
267 | bufferDst[iElem] = ((a << 24) & 0xff000000) | |
||
268 | ((r << 16) & 0x00ff0000)| |
||
269 | ((g << 8) & 0x0000ff00) | |
||
270 | (b & 0x000000ff);
|
||
271 | } |
||
272 | return bufferDst;
|
||
273 | |||
274 | } |
||
275 | |||
276 | /**
|
||
277 | * Aplica la operaci?n de refinamiento sobre el buffer Multiespectral que contiene
|
||
278 | * el RGB que es pasado por par?metro utilizando la pancrom?tica.
|
||
279 | * @param bufferInput Buffer rgb
|
||
280 | * @param length longitud del buffer de la pancromatica utilizado
|
||
281 | * @param iLine l?nea leida de la imagen multiespectral
|
||
282 | * @return buffer con el resultado de la operaci?n
|
||
283 | */
|
||
284 | private int[] processIHS(int[] bufferInput, int iLine){ |
||
285 | double[] hsl; |
||
286 | int[] rgb; |
||
287 | PixelGrabber pg = null; |
||
288 | |||
289 | //Buffer de salida
|
||
290 | int[] bufferPancr = new int[width]; |
||
291 | |||
292 | pg = new PixelGrabber(imagePancr, 0, iLine, width, 1, bufferPancr , 0, width); |
||
293 | |||
294 | try {
|
||
295 | pg.grabPixels(); |
||
296 | } catch (InterruptedException e) { |
||
297 | e.printStackTrace(); |
||
298 | } |
||
299 | |||
300 | int[] uvw , tmp = new int[3]; |
||
301 | double[] xyz; |
||
302 | for(int iElem=0; iElem<width; iElem++){ |
||
303 | xyz = ColorSpaceConversion.RGBtoHSL( (bufferInput[iElem] >> 16) & 0x000000ff, |
||
304 | (bufferInput[iElem] >> 8) & 0x000000ff, |
||
305 | bufferInput[iElem] & 0x000000ff);
|
||
306 | |||
307 | xyz[2] = ((bufferPancr[iElem] & 0x000000ff)/255.0) + coef; |
||
308 | |||
309 | tmp[0] = (int)(255.0 * xyz[0] / 360.0 + 0.5); |
||
310 | tmp[2] = (int) (xyz[2]*255. + 0.5); |
||
311 | tmp[1] = (int) (xyz[1]*255. + 0.5); |
||
312 | |||
313 | uvw = ColorSpaceConversion.HSLtoRGB(tmp[ColorSpaceConversion.H], |
||
314 | tmp[ColorSpaceConversion.S], |
||
315 | tmp[ColorSpaceConversion.L]); |
||
316 | bufferPancr[iElem] = ((alpha << 24) & 0xff000000) | |
||
317 | ((uvw[0] << 16) & 0x00ff0000)| |
||
318 | ((uvw[1] << 8) & 0x0000ff00) | |
||
319 | (uvw[2] & 0x000000ff); |
||
320 | } |
||
321 | return bufferPancr;
|
||
322 | |||
323 | } |
||
324 | |||
325 | /**
|
||
326 | * Aplica el filtro sobre el raster pasado pixel a pixel
|
||
327 | */
|
||
328 | public void execute() { |
||
329 | pre(); |
||
330 | if (exec) {
|
||
331 | int[] pRGBArrayMultiesp = new int[width]; |
||
332 | int[] pRGBArrayPancr = null; |
||
333 | PixelGrabber pg = null; |
||
334 | int widthDst = width * relX;
|
||
335 | |||
336 | //Para cada linea leemos los valores RGB del image. Aplicamos el algoritmo
|
||
337 | //y escribimos el resultado.
|
||
338 | |||
339 | if(method.equals("hsl")){ |
||
340 | float[][] k = {{-1F, -1F, -1F},{-1F, 8F, -1F},{-1F, -1F, -1F}}; |
||
341 | kernel = new Kernel(k); |
||
342 | for(int iLine=0;iLine<height ;iLine++){ |
||
343 | pg = new PixelGrabber(imageMultiespec, 0, iLine, width, 1, pRGBArrayMultiesp, 0, width); |
||
344 | try {
|
||
345 | pg.grabPixels(); |
||
346 | } catch (InterruptedException e) {e.printStackTrace();} |
||
347 | pRGBArrayPancr = processIHS(pRGBArrayMultiesp, iLine); |
||
348 | ((BufferedImage)imagePancr).setRGB(0, iLine, width, 1, pRGBArrayPancr, 0, width); |
||
349 | } |
||
350 | }else{
|
||
351 | for(int iLine=0;iLine<height ;iLine++){ |
||
352 | pg = new PixelGrabber(imageMultiespec, 0, iLine, width, 1, pRGBArrayMultiesp, 0, width); |
||
353 | try {
|
||
354 | pg.grabPixels(); |
||
355 | } catch (InterruptedException e) {e.printStackTrace();} |
||
356 | pRGBArrayPancr = processBrovey(pRGBArrayMultiesp, iLine); |
||
357 | ((BufferedImage)imagePancr).setRGB(0, iLine, width, 1, pRGBArrayPancr, 0, width); |
||
358 | } |
||
359 | } |
||
360 | } |
||
361 | |||
362 | post(); |
||
363 | } |
||
364 | |||
365 | /* (non-Javadoc)
|
||
366 | * @see org.cresques.io.raster.IRasterFilter#process(int, int)
|
||
367 | */
|
||
368 | public void process(int x, int y) { |
||
369 | |||
370 | } |
||
371 | |||
372 | /* (non-Javadoc)
|
||
373 | * @see org.cresques.io.raster.IRasterFilter#getInRasterDataType()
|
||
374 | */
|
||
375 | public int getInRasterDataType() { |
||
376 | return RasterBuf.TYPE_IMAGE;
|
||
377 | } |
||
378 | |||
379 | /* (non-Javadoc)
|
||
380 | * @see org.cresques.io.raster.IRasterFilter#getOutRasterDataType()
|
||
381 | */
|
||
382 | public int getOutRasterDataType() { |
||
383 | return RasterBuf.TYPE_IMAGE;
|
||
384 | } |
||
385 | |||
386 | /* (non-Javadoc)
|
||
387 | * @see org.cresques.io.raster.IRasterFilter#getResult(java.lang.String)
|
||
388 | */
|
||
389 | public Object getResult(String name) { |
||
390 | if (name.equals("raster")) { |
||
391 | return (Object) this.imagePancr; |
||
392 | } else {
|
||
393 | return null; |
||
394 | } |
||
395 | } |
||
396 | |||
397 | /* (non-Javadoc)
|
||
398 | * @see org.cresques.io.raster.RasterFilter#processLine(int)
|
||
399 | */
|
||
400 | public void processLine(int y) { |
||
401 | } |
||
402 | |||
403 | /* (non-Javadoc)
|
||
404 | * @see org.cresques.io.raster.IRasterFilter#post()
|
||
405 | */
|
||
406 | public void post() { |
||
407 | } |
||
408 | } |