svn-gvsig-desktop / tags / Root_v06 / libraries / libCq CMS for java.old / src / org / cresques / io / raster / SharpeningImageFilter.java @ 4811
History | View | Annotate | Download (13.8 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.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 |
pancrName = files[posPancromatica].getName().substring( |
100 |
files[posPancromatica].getName().lastIndexOf("/")+1, |
101 |
files[posPancromatica].getName().length()); |
102 |
this.addParam("pancrName", pancrName); |
103 |
|
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 |
} |
409 |
|