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