gvsig-raster / org.gvsig.raster / tags / 2.0.0 / org.gvsig.raster.lib / org.gvsig.raster.lib.impl / src / main / java / org / gvsig / raster / impl / grid / render / ImageDrawerImpl.java @ 1708
History | View | Annotate | Download (15.7 KB)
1 |
/* gvSIG. Geographic Information System of the Valencian Government
|
---|---|
2 |
*
|
3 |
* Copyright (C) 2007-2008 Infrastructures and Transports Department
|
4 |
* of the Valencian Government (CIT)
|
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., 51 Franklin Street, Fifth Floor, Boston,
|
19 |
* MA 02110-1301, USA.
|
20 |
*
|
21 |
*/
|
22 |
package org.gvsig.raster.impl.grid.render; |
23 |
|
24 |
import java.awt.Image; |
25 |
import java.awt.image.BufferedImage; |
26 |
|
27 |
import org.gvsig.fmap.dal.coverage.RasterLocator; |
28 |
import org.gvsig.fmap.dal.coverage.dataset.Buffer; |
29 |
import org.gvsig.fmap.dal.coverage.datastruct.Extent; |
30 |
import org.gvsig.fmap.dal.coverage.exception.FileNotOpenException; |
31 |
import org.gvsig.fmap.dal.coverage.exception.FilterTypeException; |
32 |
import org.gvsig.fmap.dal.coverage.exception.ProcessInterruptedException; |
33 |
import org.gvsig.fmap.dal.coverage.exception.RasterDriverException; |
34 |
import org.gvsig.fmap.dal.coverage.grid.RasterFilterList; |
35 |
import org.gvsig.fmap.dal.coverage.grid.render.ImageDrawer; |
36 |
import org.gvsig.fmap.dal.coverage.store.props.Statistics; |
37 |
import org.gvsig.fmap.dal.coverage.store.props.Transparency; |
38 |
import org.gvsig.raster.impl.DefaultRasterManager; |
39 |
import org.gvsig.raster.impl.buffer.RasterBuffer; |
40 |
import org.gvsig.raster.impl.grid.filter.enhancement.DefaultLinearStretchParams; |
41 |
import org.gvsig.raster.impl.grid.filter.enhancement.EnhancementStretchListManager; |
42 |
import org.gvsig.raster.impl.process.RasterTask; |
43 |
import org.gvsig.raster.impl.process.RasterTaskQueue; |
44 |
import org.slf4j.LoggerFactory; |
45 |
|
46 |
/**
|
47 |
* Objeto para la escritura de datos desde un buffer a un objeto Image. En este nivel de
|
48 |
* renderizado no se gestiona extents, ni rotaciones ni coordenadas del mundo, solo la
|
49 |
* escritura desde un buffer hasta otro de tama?o dado. Por medio de par?metros y de objetos
|
50 |
* de estado varia el resultado de la escritura, selecci?n de bandas a escribir desde el buffer
|
51 |
* a RGB, transparencias aplicadas o paletas.
|
52 |
*
|
53 |
* @author Nacho Brodin (nachobrodin@gmail.com)
|
54 |
*/
|
55 |
public class ImageDrawerImpl implements ImageDrawer { |
56 |
private Buffer rasterBuf = null; |
57 |
private double[] step = null; |
58 |
private int width = -1; |
59 |
private int height = -1; |
60 |
private double scaleX = 1; //rate between input and output buffer |
61 |
private double scaleY = 1; |
62 |
private Transparency transparency = null; |
63 |
|
64 |
public ImageDrawerImpl() {
|
65 |
} |
66 |
|
67 |
/*
|
68 |
* (non-Javadoc)
|
69 |
* @see org.gvsig.fmap.dal.coverage.grid.render.ImageDrawer#setLastTransparency(org.gvsig.fmap.dal.coverage.store.props.Transparency)
|
70 |
*/
|
71 |
public void setLastTransparency(Transparency t) { |
72 |
this.transparency = t;
|
73 |
} |
74 |
|
75 |
/*
|
76 |
* (non-Javadoc)
|
77 |
* @see org.gvsig.fmap.dal.coverage.grid.render.ImageDrawer#drawBufferOverImageObject()
|
78 |
*/
|
79 |
public Image drawBufferOverImageObject() throws ProcessInterruptedException { |
80 |
if (rasterBuf == null) |
81 |
return null; |
82 |
|
83 |
try { // Temporal para la traza de un error aleatorio |
84 |
boolean supersamplingOn = false; |
85 |
BufferedImage image = null; |
86 |
if(width <= 0 && height <= 0) { |
87 |
width = rasterBuf.getWidth(); |
88 |
height = rasterBuf.getHeight(); |
89 |
scaleX = scaleY = 1;
|
90 |
} else {
|
91 |
scaleX = rasterBuf.getWidth() / width; |
92 |
scaleY = rasterBuf.getHeight() / height; |
93 |
} |
94 |
image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); |
95 |
|
96 |
if(step != null) { |
97 |
supersamplingOn = true;
|
98 |
} |
99 |
|
100 |
if (rasterBuf.getDataType() != Buffer.TYPE_BYTE) |
101 |
rasterBuf = convertToByte(rasterBuf); |
102 |
|
103 |
byte[] data = new byte[rasterBuf.getBandCount()]; |
104 |
|
105 |
if (transparency != null && transparency.isTransparencyActive()) { |
106 |
if (transparency.existAlphaBand() &&
|
107 |
transparency.getAlphaBand() != null &&
|
108 |
transparency.getAlphaBand().getDataType() != Buffer.TYPE_BYTE) {
|
109 |
transparency.setAlphaBand(convertToByte(transparency.getAlphaBand())); |
110 |
} |
111 |
drawWithTransparency(image, data, supersamplingOn, transparency); |
112 |
} else
|
113 |
drawByte(image, data, supersamplingOn); |
114 |
|
115 |
step = null;
|
116 |
return image;
|
117 |
} catch (OutOfMemoryError error) { // Temporal para la traza de un error |
118 |
// aleatorio
|
119 |
LoggerFactory.getLogger(this.getClass()).debug(
|
120 |
"Buffer: " + rasterBuf.getWidth() + " " + rasterBuf.getHeight() , error); |
121 |
} |
122 |
return null; |
123 |
} |
124 |
|
125 |
/**
|
126 |
* Calcula los vectores de desplazamiento en pixels en X e Y cuando se supersamplea.
|
127 |
* @param r Array de desplazamientos para las filas. Debe tener espacio reservado
|
128 |
* @param c Array de desplazamientos para las columnas. Debe tener espacio reservado
|
129 |
* cargados.
|
130 |
*/
|
131 |
private void calcSupersamplingStepsArrays(int[] r, int[] c) { |
132 |
double pos = step[1]; |
133 |
for(int row = 0; row < r.length; row ++) { |
134 |
r[row] = (int)(pos / step[3]); |
135 |
pos ++; |
136 |
} |
137 |
pos = step[0];
|
138 |
for(int col = 0; col < c.length; col ++) { |
139 |
c[col] = (int)(pos / step[2]); |
140 |
pos ++; |
141 |
} |
142 |
} |
143 |
|
144 |
/**
|
145 |
* Dibuja un raster sobre un BufferedImage
|
146 |
* @param image BufferedImage sobre el que se dibuja
|
147 |
* @param data buffer vacio. Se trata de un array de bytes donde cada elemento representa una banda.
|
148 |
* @param supersampling true si se necesita supersamplear y false si no se necesita
|
149 |
* @throws ProcessInterruptedException
|
150 |
*/
|
151 |
private void drawByte(BufferedImage image, byte[] data, boolean supersampling) throws ProcessInterruptedException { |
152 |
RasterTask task = RasterTaskQueue.get(Thread.currentThread().getId() + ""); |
153 |
try {
|
154 |
if (supersampling) {
|
155 |
int[] r = new int[height]; |
156 |
int[] c = new int[width]; |
157 |
calcSupersamplingStepsArrays(r, c); |
158 |
for (int row = 0; row < height; row++) { |
159 |
for (int col = 0; col < width; col++) |
160 |
try {
|
161 |
rasterBuf.getElemByte(r[row], c[col], data); |
162 |
image.setRGB(col, row, (0xff000000 + ((data[0] & 0xff) << 16) |
163 |
+ ((data[1] & 0xff) << 8) + (data[2] & 0xff))); |
164 |
} catch (ArrayIndexOutOfBoundsException e) { |
165 |
System.err.println("== Size Image:" + image.getWidth() + " " + image.getHeight()); |
166 |
System.err.println("== Position required:" + col + " " + row); |
167 |
break;
|
168 |
} |
169 |
if (task.getEvent() != null) |
170 |
task.manageEvent(task.getEvent()); |
171 |
} |
172 |
} else {
|
173 |
/*Old code
|
174 |
for (int row = 0; row < rasterBuf.getHeight(); row++) {
|
175 |
for (int col = 0; col < rasterBuf.getWidth(); col++)
|
176 |
try {
|
177 |
rasterBuf.getElemByte(row, col, data);
|
178 |
image.setRGB(col, row, (0xff000000 + ((data[0] & 0xff) << 16)
|
179 |
+ ((data[1] & 0xff) << 8) + (data[2] & 0xff)));
|
180 |
} catch (ArrayIndexOutOfBoundsException ex) {
|
181 |
System.err.println("== Size Image:" + image.getWidth() + " " + image.getHeight());
|
182 |
System.err.println("== Position required:" + col + " " + row);
|
183 |
break;
|
184 |
}
|
185 |
if (task.getEvent() != null)
|
186 |
task.manageEvent(task.getEvent());
|
187 |
}*/
|
188 |
for (int row = 0; row < height; row++) { |
189 |
for (int col = 0; col < width; col++) { |
190 |
try {
|
191 |
rasterBuf.getElemByte((int)(row * scaleY), (int)(col * scaleX), data); |
192 |
image.setRGB(col, row, (0xff000000 + ((data[0] & 0xff) << 16) |
193 |
+ ((data[1] & 0xff) << 8) + (data[2] & 0xff))); |
194 |
} catch (ArrayIndexOutOfBoundsException ex) { |
195 |
System.err.println("== Size Image:" + image.getWidth() + " " + image.getHeight()); |
196 |
System.err.println("== Position required:" + (int)(col * scaleX) + " " + (int)(row * scaleY)); |
197 |
break;
|
198 |
} |
199 |
} |
200 |
if (task.getEvent() != null) |
201 |
task.manageEvent(task.getEvent()); |
202 |
} |
203 |
} |
204 |
} catch (Exception e) { |
205 |
LoggerFactory.getLogger(this.getClass()).info(
|
206 |
"Buffer: " + rasterBuf.getWidth() + " " + rasterBuf.getHeight() , e); |
207 |
} |
208 |
} |
209 |
|
210 |
/**
|
211 |
* Dibuja un raster sobre un BufferedImage con las propiedades de paleta y transparencia
|
212 |
* @param image BufferedImage sobre el que se dibuja
|
213 |
* @param data buffer vacio. Se trata de un array de bytes donde cada elemento representa una banda.
|
214 |
* @param supersampling true si se necesita supersamplear y false si no se necesita
|
215 |
* @throws ProcessInterruptedException
|
216 |
*/
|
217 |
private void drawWithTransparency(BufferedImage image, |
218 |
byte[] data, |
219 |
boolean supersampling,
|
220 |
Transparency t) throws ProcessInterruptedException { |
221 |
RasterTask task = RasterTaskQueue.get(Thread.currentThread().getId() + ""); |
222 |
int value = 0; |
223 |
try {
|
224 |
if (supersampling) {
|
225 |
int[] r = new int[height]; |
226 |
int[] c = new int[width]; |
227 |
calcSupersamplingStepsArrays(r, c); |
228 |
for (int row = 0; row < height; row++) { |
229 |
for (int col = 0; col < width; col++) |
230 |
try {
|
231 |
rasterBuf.getElemByte(r[row], c[col], data); |
232 |
value = t.processRGB(data[0] & 0xff, data[1] & 0xff, data[2] & 0xff, r[row], c[col]); |
233 |
image.setRGB(col, row, value); |
234 |
} catch (ArrayIndexOutOfBoundsException e) { |
235 |
System.err.println("== Size Image:" + image.getWidth() + " " + image.getHeight()); |
236 |
System.err.println("== Position required:" + col + " " + row); |
237 |
break;
|
238 |
} |
239 |
if (task.getEvent() != null) |
240 |
task.manageEvent(task.getEvent()); |
241 |
} |
242 |
} else {
|
243 |
/*Old code
|
244 |
for (int row = 0; row < rasterBuf.getHeight(); row++) {
|
245 |
for (int col = 0; col < rasterBuf.getWidth(); col++)
|
246 |
try {
|
247 |
rasterBuf.getElemByte(row, col, data);
|
248 |
value = t.processRGB(data[0] & 0xff, data[1] & 0xff, data[2] & 0xff, row, col);
|
249 |
image.setRGB(col, row, value);
|
250 |
} catch (ArrayIndexOutOfBoundsException e) {
|
251 |
System.err.println("== Size Image:" + image.getWidth() + " " + image.getHeight());
|
252 |
System.err.println("== Position required:" + col + " " + row);
|
253 |
break;
|
254 |
}
|
255 |
if (task.getEvent() != null)
|
256 |
task.manageEvent(task.getEvent());
|
257 |
}
|
258 |
*/
|
259 |
for (int row = 0; row < height; row++) { |
260 |
for (int col = 0; col < width; col++) { |
261 |
try {
|
262 |
int r = (int)(row * scaleY); |
263 |
int c = (int)(col * scaleX); |
264 |
rasterBuf.getElemByte(r, c, data); |
265 |
value = t.processRGB(data[0] & 0xff, data[1] & 0xff, data[2] & 0xff, r, c); |
266 |
image.setRGB(col, row, value); |
267 |
} catch (ArrayIndexOutOfBoundsException e) { |
268 |
System.err.println("== Size Image:" + image.getWidth() + " " + image.getHeight()); |
269 |
System.err.println("== Position required:" + col + " " + row); |
270 |
break;
|
271 |
} //catch (Exception e) {
|
272 |
//System.out.println("Row:" + (int)(row * scaleY) + " Col:" + (int)(col * scaleX) + " " + rasterBuf.getBandCount() + " " + data.length);
|
273 |
//}
|
274 |
} |
275 |
if (task.getEvent() != null) |
276 |
task.manageEvent(task.getEvent()); |
277 |
} |
278 |
|
279 |
} |
280 |
} catch (Exception e) { |
281 |
LoggerFactory.getLogger(this.getClass()).info(
|
282 |
"Buffer: " + rasterBuf.getWidth() + " " + rasterBuf.getHeight() , e); |
283 |
} |
284 |
} |
285 |
|
286 |
/**
|
287 |
* Converts a Buffer object into a byte
|
288 |
* @param buf
|
289 |
* @return
|
290 |
*/
|
291 |
private Buffer convertToByte(Buffer buf) { |
292 |
Buffer b = DefaultRasterManager.getInstance().createBuffer(Buffer.TYPE_BYTE, buf.getWidth(), buf.getHeight(), buf.getBandCount(), true); |
293 |
if(buf.getDataType() == Buffer.TYPE_SHORT) |
294 |
for (int nBand = 0; nBand < buf.getBandCount(); nBand++) |
295 |
for (int row = 0; row < buf.getHeight(); row++) |
296 |
for (int col = 0; col < buf.getWidth(); col++) |
297 |
b.setElem(row, col, nBand, (byte)(buf.getElemShort(row, col, nBand) & 0xffff)); |
298 |
if(buf.getDataType() == Buffer.TYPE_INT) |
299 |
for (int nBand = 0; nBand < buf.getBandCount(); nBand++) |
300 |
for (int row = 0; row < buf.getHeight(); row++) |
301 |
for (int col = 0; col < buf.getWidth(); col++) |
302 |
b.setElem(row, col, nBand, (byte)(buf.getElemInt(row, col, nBand) & 0xffffffff)); |
303 |
if(buf.getDataType() == Buffer.TYPE_FLOAT) |
304 |
for (int nBand = 0; nBand < buf.getBandCount(); nBand++) |
305 |
for (int row = 0; row < buf.getHeight(); row++) |
306 |
for (int col = 0; col < buf.getWidth(); col++) |
307 |
b.setElem(row, col, nBand, (byte)(Math.round(buf.getElemFloat(row, col, nBand)))); |
308 |
if(buf.getDataType() == Buffer.TYPE_DOUBLE) |
309 |
for (int nBand = 0; nBand < buf.getBandCount(); nBand++) |
310 |
for (int row = 0; row < buf.getHeight(); row++) |
311 |
for (int col = 0; col < buf.getWidth(); col++) |
312 |
b.setElem(row, col, nBand, (byte)(Math.round(buf.getElemDouble(row, col, nBand)))); |
313 |
return b;
|
314 |
} |
315 |
|
316 |
/*
|
317 |
* (non-Javadoc)
|
318 |
* @see org.gvsig.fmap.dal.coverage.grid.render.ImageDrawer#setBuffer(org.gvsig.fmap.dal.coverage.dataset.Buffer)
|
319 |
*/
|
320 |
public void setBuffer(Buffer b) { |
321 |
this.rasterBuf = b;
|
322 |
} |
323 |
|
324 |
/*
|
325 |
* (non-Javadoc)
|
326 |
* @see org.gvsig.fmap.dal.coverage.grid.render.ImageDrawer#setSupersamplingOn(double[], int, int)
|
327 |
*/
|
328 |
public void setSupersamplingOn(double[] step) { |
329 |
this.step = step;
|
330 |
} |
331 |
|
332 |
/*
|
333 |
* (non-Javadoc)
|
334 |
* @see org.gvsig.fmap.dal.coverage.grid.render.ImageDrawer#setOutPutSize(int, int)
|
335 |
*/
|
336 |
public void setOutputSize(int w, int h) { |
337 |
this.width = w;
|
338 |
this.height = h;
|
339 |
} |
340 |
|
341 |
/*
|
342 |
* (non-Javadoc)
|
343 |
* @see org.gvsig.fmap.dal.coverage.grid.render.ImageDrawer#dispose()
|
344 |
*/
|
345 |
public void dispose() { |
346 |
if(rasterBuf != null) |
347 |
rasterBuf.dispose(); |
348 |
if(transparency != null) |
349 |
transparency.dispose(); |
350 |
try {
|
351 |
finalize(); |
352 |
} catch (Throwable e) { |
353 |
} |
354 |
} |
355 |
|
356 |
/*
|
357 |
* (non-Javadoc)
|
358 |
* @see org.gvsig.fmap.dal.coverage.grid.render.ImageDrawer#addEnhanced(org.gvsig.fmap.dal.coverage.store.props.Statistics)
|
359 |
*/
|
360 |
public Buffer addEnhanced(Statistics stats) { |
361 |
return addEnhanced(stats, true, 0.0); |
362 |
} |
363 |
|
364 |
/*
|
365 |
* (non-Javadoc)
|
366 |
* @see org.gvsig.fmap.dal.coverage.grid.render.ImageDrawer#addEnhanced(org.gvsig.fmap.dal.coverage.store.props.Statistics)
|
367 |
*/
|
368 |
public Buffer addEnhanced(Statistics stats, boolean tailTrim, double tailTrimValue) { |
369 |
RasterFilterList filterList = RasterLocator.getManager().createEmptyFilterList(rasterBuf.getDataType()); |
370 |
|
371 |
try {
|
372 |
/*RasterFilterListManager enhancementManager = filterList.getManagerByID("EnhancementStretch");
|
373 |
Params params = filterList.createEmptyFilterParams();
|
374 |
params.setParam("stats", stats);
|
375 |
params.setParam("remove", new Boolean(false));
|
376 |
int[] renderBands = new int[rasterBuf.getBandCount()];
|
377 |
for (int i = 0; i < renderBands.length; i++) {
|
378 |
renderBands[i] = i;
|
379 |
}
|
380 |
params.setParam("renderBands", renderBands);
|
381 |
params.setParam("stretchs", null);//coge el LinearStretchParams por defecto
|
382 |
params.setParam("rgb", new Boolean(true));
|
383 |
|
384 |
enhancementManager.addFilter(params);
|
385 |
*/
|
386 |
EnhancementStretchListManager enhancementManager = (EnhancementStretchListManager) filterList.getManagerByClass(EnhancementStretchListManager.class); |
387 |
int[] renderBands = new int[rasterBuf.getBandCount()]; |
388 |
for (int i = 0; i < renderBands.length; i++) { |
389 |
renderBands[i] = i; |
390 |
} |
391 |
enhancementManager.addEnhancedStretchFilter( |
392 |
DefaultLinearStretchParams.createStandardParam(new int[] { 0, 1, 2 }, tailTrimValue, stats, true), |
393 |
stats, |
394 |
renderBands, |
395 |
tailTrim); |
396 |
} catch (FilterTypeException e1) {
|
397 |
} catch (FileNotOpenException e) {
|
398 |
} catch (RasterDriverException e) {
|
399 |
} |
400 |
|
401 |
if(filterList != null) { |
402 |
Extent ext = RasterLocator.getManager().getDataStructFactory(). |
403 |
createExtent(rasterBuf.getDataExtent()); |
404 |
filterList.addEnvParam("IStatistics", stats);
|
405 |
filterList.addEnvParam("Transparency", transparency);
|
406 |
filterList.addEnvParam("GridExtent", ext);
|
407 |
filterList.addEnvParam("WindowExtent", ext);
|
408 |
filterList.setInitRasterBuf(rasterBuf); |
409 |
try {
|
410 |
filterList.execute(); |
411 |
} catch (ProcessInterruptedException e) {
|
412 |
return rasterBuf;
|
413 |
} |
414 |
rasterBuf = (RasterBuffer) filterList.getResult(); |
415 |
} |
416 |
return rasterBuf;
|
417 |
} |
418 |
|
419 |
/*
|
420 |
* (non-Javadoc)
|
421 |
* @see java.lang.Object#finalize()
|
422 |
*/
|
423 |
protected void finalize() throws Throwable { |
424 |
step = null;
|
425 |
rasterBuf = null;
|
426 |
transparency = null;
|
427 |
super.finalize();
|
428 |
} |
429 |
|
430 |
} |