001: /*
002: * Geotools 2 - OpenSource mapping toolkit
003: * (C) 2006, Geotools Project Managment Committee (PMC)
004: *
005: * This library is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU Lesser General Public
007: * License as published by the Free Software Foundation; either
008: * version 2.1 of the License, or (at your option) any later version.
009: *
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * Lesser General Public License for more details.
014: *
015: * You should have received a copy of the GNU Lesser General Public
016: * License along with this library; if not, write to the Free Software
017: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
018: */
019: package org.geotools.gce.imagemosaic;
020:
021: import java.awt.Color;
022: import java.awt.Rectangle;
023: import java.awt.image.RenderedImage;
024: import java.io.IOException;
025: import java.net.URL;
026:
027: import javax.media.jai.JAI;
028: import javax.media.jai.widget.ScrollingImagePanel;
029: import javax.swing.JFrame;
030: import javax.swing.SwingUtilities;
031:
032: import junit.framework.Test;
033: import junit.framework.TestCase;
034: import junit.framework.TestSuite;
035: import junit.textui.TestRunner;
036:
037: import org.geotools.coverage.AbstractCoverage;
038: import org.geotools.coverage.grid.GeneralGridRange;
039: import org.geotools.coverage.grid.GridCoverage2D;
040: import org.geotools.coverage.grid.GridGeometry2D;
041: import org.geotools.coverage.grid.io.AbstractGridCoverage2DReader;
042: import org.geotools.coverage.grid.io.AbstractGridFormat;
043: import org.geotools.coverage.grid.io.GridFormatFinder;
044: import org.geotools.coverage.grid.io.UnknownFormat;
045: import org.geotools.geometry.GeneralEnvelope;
046: import org.geotools.test.TestData;
047: import org.opengis.geometry.MismatchedDimensionException;
048: import org.opengis.parameter.GeneralParameterValue;
049: import org.opengis.parameter.ParameterValue;
050: import org.opengis.referencing.FactoryException;
051: import org.opengis.referencing.NoSuchAuthorityCodeException;
052:
053: /**
054: * Testing {@link ImageMosaicReader}.
055: *
056: * @author Simone Giannecchini
057: * @since 2.3
058: *
059: */
060: public class ImageMosaicReaderTest extends TestCase {
061:
062: public static Test suite() {
063: TestSuite suite = new TestSuite();
064:
065: suite.addTest(new ImageMosaicReaderTest(
066: "testDefaultParameterValue"));
067: // suite.addTest(new ImageMosaicReaderTest("testInputAlpha"));
068: // suite.addTest(new ImageMosaicReaderTest("testInputImageROI"));
069: // suite.addTest(new ImageMosaicReaderTest("testCrop"));
070:
071: return suite;
072: }
073:
074: private URL rgbURL;
075:
076: private URL indexURL;
077:
078: private URL indexAlphaURL;
079:
080: private URL grayURL;
081:
082: private URL index_unique_paletteAlphaURL;
083:
084: private URL rgbAURL;
085:
086: // private URL morandini;
087:
088: private boolean interactive;
089:
090: public ImageMosaicReaderTest(String string) {
091: super (string);
092: }
093:
094: /**
095: * Testing input thresholds.
096: *
097: * @throws MismatchedDimensionException
098: * @throws NoSuchAuthorityCodeException
099: * @throws IOException
100: */
101: public void testInputImageROI()
102: throws MismatchedDimensionException,
103: NoSuchAuthorityCodeException, IOException {
104:
105: // //
106: //
107: // This image is RGB. If we do thresholding with a value of 100 we will
108: // just throw away a lot of values and we will replace them with 0.
109: //
110: // //
111: if (interactive)
112: imageMosaicSimpleParamsTest(rgbURL, Double.NaN, null, null,
113: "testInputImageROI-rgbURL", false);
114: imageMosaicSimpleParamsTest(rgbURL, 100, null, null,
115: "testInputImageROI-rgbURL", false);
116:
117: // //
118: //
119: // This image has borders that are transparent black which means
120: // (0,0,0,0) hence if we want the mosaic to come out clean and nice we
121: // have to do Overlay with ROI to get superimposition, otherwise blend
122: // with ROI 1 or Blend without ROI to get average!
123: //
124: // //
125: if (interactive) {
126: imageMosaicSimpleParamsTest(
127: rgbAURL,
128: Double.NaN,
129: null,
130: null,
131: "testInputImageROI-rgbAURL-original-superimposition-bad",
132: false);
133: imageMosaicSimpleParamsTest(
134: rgbAURL,
135: 1,
136: null,
137: null,
138: "testInputImageROI-rgbAURL-original-superimposition-good",
139: false);
140: }
141: imageMosaicSimpleParamsTest(rgbAURL, 1, null, null,
142: "testInputImageROI-rgbAURL-fading-ROI", true);
143: imageMosaicSimpleParamsTest(rgbAURL, Double.NaN, null, null,
144: "testInputImageROI-rgbAURL-fading-intrinsic-alpha",
145: true);
146:
147: // //
148: //
149: // This images have borders that are black and have a color model that
150: // is IndexColorModel but all with different palette hence a color
151: // conversion will be applied.
152: //
153: // The provided threshold will result in having most part of the input
154: // images replaced by the default background values.
155: //
156: // //
157: if (interactive)
158: imageMosaicSimpleParamsTest(indexURL, Double.NaN, null,
159: null, "testInputImageROI-indexURL-original", false);
160: imageMosaicSimpleParamsTest(indexURL, 100, null, null,
161: "testInputImageROI-indexURL", false);
162:
163: // //
164: //
165: // This images have borders that are transparent black which means
166: // (0,0,0,0) and have a color model that
167: // is IndexColorModel but all with different palette hence a color
168: // conversion will be applied.
169: //
170: // The provided threshold will result in having most part of the input
171: // images replaced by the default background values which means the
172: // replaced part will be transparent.
173: //
174: // //
175: if (interactive)
176: imageMosaicSimpleParamsTest(indexAlphaURL, Double.NaN,
177: null, null,
178: "testInputImageROI-indexAlphaURL-original", false);
179: imageMosaicSimpleParamsTest(indexAlphaURL, 100, null, null,
180: "testInputImageROI-indexAlphaURL", false);
181:
182: // //
183: //
184: // Grayscale images. The ROIs will just make them darker because they
185: // will replace part of the input values with zero.
186: //
187: // //
188: if (interactive)
189: imageMosaicSimpleParamsTest(grayURL, Double.NaN, null,
190: null, "testInputImageROI-grayURL-original", false);
191: imageMosaicSimpleParamsTest(grayURL, 100, null, null,
192: "testInputImageROI-grayURL", false);
193:
194: // //
195: //
196: // Grayscale images with index color model with alpha. The ROIs will
197: // just make them more transparent because they
198: // will replace part of the input values with zero.
199: //
200: // //
201: if (interactive)
202: imageMosaicSimpleParamsTest(
203: index_unique_paletteAlphaURL,
204: Double.NaN,
205: null,
206: null,
207: "testInputImageROI-index_unique_paletteAlphaURL-original",
208: false);
209: imageMosaicSimpleParamsTest(index_unique_paletteAlphaURL, 100,
210: null, null,
211: "testInputImageROI-index_unique_paletteAlphaURL", false);
212:
213: }
214:
215: /**
216: * Testing both input threshold and alpha.
217: *
218: * @throws MismatchedDimensionException
219: * @throws NoSuchAuthorityCodeException
220: * @throws IOException
221: */
222: public void testROIAlpha() throws MismatchedDimensionException,
223: NoSuchAuthorityCodeException, IOException {
224:
225: boolean interactive = TestData.isInteractiveTest();
226: if (interactive)
227: imageMosaicSimpleParamsTest(rgbURL, 100, null, null,
228: "testROIAlpha-rgbURL-original", false);
229: imageMosaicSimpleParamsTest(rgbURL, 100, Color.black, null,
230: "testROIAlpha-rgbURL", false);
231:
232: if (interactive)
233: imageMosaicSimpleParamsTest(rgbAURL, 5, null, null,
234: "testROIAlpha-rgbAURL-original", false);
235: imageMosaicSimpleParamsTest(rgbAURL, 5, new Color(35, 34, 25),
236: null, "testROIAlpha-rgbAURL", false);
237:
238: if (interactive)
239: imageMosaicSimpleParamsTest(indexURL, 5, null, null,
240: "testROIAlpha-indexURL-original", false);
241: imageMosaicSimpleParamsTest(indexURL, 5, new Color(58, 49, 8),
242: null, "testROIAlpha-indexURL", false);
243:
244: if (interactive)
245: imageMosaicSimpleParamsTest(indexAlphaURL, 30, null, null,
246: "testROIAlpha-indexAlphaURL-original", false);
247: imageMosaicSimpleParamsTest(indexAlphaURL, 30, new Color(41,
248: 41, 33), null, "testROIAlpha-indexAlphaURL", false);
249:
250: if (interactive)
251: imageMosaicSimpleParamsTest(grayURL, 100, null, null,
252: "testROIAlpha-grayURL-original", false);
253: imageMosaicSimpleParamsTest(grayURL, 100, Color.black, null,
254: "testROIAlpha-grayURL", false);
255:
256: }
257:
258: /**
259: * Testing crop capabilities.
260: *
261: * @throws MismatchedDimensionException
262: * @throws IOException
263: * @throws FactoryException
264: */
265: public void testCrop() throws MismatchedDimensionException,
266: IOException, FactoryException {
267: imageMosaicCropTest(rgbURL, "crop-rgbURL");
268: imageMosaicCropTest(indexURL, "crop-indexURL");
269: imageMosaicCropTest(grayURL, "crop-grayURL");
270: imageMosaicCropTest(indexAlphaURL, "crop-indexAlphaURL");
271: imageMosaicCropTest(rgbAURL, "crop-rgbAURL");
272: imageMosaicCropTest(index_unique_paletteAlphaURL,
273: "crop-index_unique_paletteAlphaURL");
274:
275: }
276:
277: /**
278: * Tests the {@link ImageMosaicReader} with default parameters for the
279: * various input params.
280: *
281: * @throws IOException
282: * @throws MismatchedDimensionException
283: * @throws NoSuchAuthorityCodeException
284: */
285: public void testInputAlpha() throws IOException,
286: MismatchedDimensionException, NoSuchAuthorityCodeException {
287:
288: if (interactive)
289: imageMosaicSimpleParamsTest(rgbURL, Double.NaN, null, null,
290: "testFinalAlpha-rgbURL-original", false);
291: imageMosaicSimpleParamsTest(rgbURL, Double.NaN, Color.black,
292: Color.black, "testFinalAlpha-rgbURL", false);
293:
294: if (interactive)
295: // the input images have transparency and they do overlap, we need
296: // to ask for blending mosaic.
297: imageMosaicSimpleParamsTest(rgbAURL, Double.NaN, null,
298: null, "testFinalAlpha-rgbAURL-original", true);
299: imageMosaicSimpleParamsTest(rgbAURL, Double.NaN, Color.black,
300: Color.black,// new
301: // Color(35,
302: // 34,
303: // 25),
304: "testFinalAlpha-rgbAURL", false);
305:
306: // //
307: //
308: // This images have borders that are black and have a color model that
309: // is IndexColorModel but all with different palette hence a color
310: // conversion will be applied to go to RGB.
311: //
312: // When we do the input transparent color we will add transparency to
313: // the images but only where the transparent color resides. Moreover the
314: // background will be trasparent.
315: //
316: // //
317: if (interactive)
318: imageMosaicSimpleParamsTest(indexURL, Double.NaN, null,
319: null, "testFinalAlpha-indexURL-original", false);
320: imageMosaicSimpleParamsTest(indexURL, Double.NaN, new Color(58,
321: 49, 8), Color.black, "testFinalAlpha-indexURL", false);
322:
323: if (interactive)
324: imageMosaicSimpleParamsTest(indexAlphaURL, Double.NaN,
325: null, null,
326: "testFinalAlpha-indexAlphaURL-original", false);
327: imageMosaicSimpleParamsTest(indexAlphaURL, Double.NaN,
328: new Color(41, 41, 33), Color.black,
329: "testFinalAlpha-indexAlphaURL", false);
330:
331: if (interactive)
332: imageMosaicSimpleParamsTest(grayURL, Double.NaN, null,
333: null, "testFinalAlpha-grayURL-original", false);
334: imageMosaicSimpleParamsTest(grayURL, Double.NaN, Color.black,
335: Color.black, "testFinalAlpha-grayURL", false);
336:
337: //
338: // if (interactive)
339: // imageMosaicSimpleParamsTest(morandini, Double.NaN, null,
340: // "testFinalAlpha-morandini-original", false);
341: // imageMosaicSimpleParamsTest(morandini, Double.NaN, Color.white,
342: // "testFinalAlpha-morandini", false);
343:
344: }
345:
346: /**
347: * Tests the {@link ImageMosaicReader} with default parameters for the
348: * various input params.
349: *
350: * @throws IOException
351: * @throws MismatchedDimensionException
352: * @throws NoSuchAuthorityCodeException
353: */
354: public void testDefaultParameterValue() throws IOException,
355: MismatchedDimensionException, NoSuchAuthorityCodeException {
356:
357: imageMosaicSimpleParamsTest(rgbURL, Double.NaN, null,
358: Color.black, "testDefaultParameterValue", false);
359: imageMosaicSimpleParamsTest(indexURL, Double.NaN, null, null,
360: "testDefaultParameterValue", false);
361: imageMosaicSimpleParamsTest(grayURL, Double.NaN, null, null,
362: "testDefaultParameterValue", false);
363: imageMosaicSimpleParamsTest(indexAlphaURL, Double.NaN, null,
364: null, "testDefaultParameterValue", false);
365:
366: }
367:
368: /**
369: * Tests the {@link ImageMosaicReader}
370: *
371: * @param title
372: *
373: * @param threshold
374: *
375: * @throws IOException
376: * @throws MismatchedDimensionException
377: * @throws NoSuchAuthorityCodeException
378: */
379: private void imageMosaicSimpleParamsTest(URL testURL,
380: double roithreshold, Color inputTransparent,
381: Color outputTransparent, String title, boolean blend)
382: throws IOException, MismatchedDimensionException,
383: NoSuchAuthorityCodeException {
384:
385: // /////////////////////////////////////////////////////////////////
386: //
387: // Get the resources as needed.
388: //
389: //
390: // /////////////////////////////////////////////////////////////////
391: assertNotNull(testURL);
392: final AbstractGridFormat format = getFormat(testURL);
393: final ImageMosaicReader reader = getReader(testURL, format);
394:
395: // /////////////////////////////////////////////////////////////////
396: //
397: // limit yourself to reading just a bit of it
398: //
399: //
400: // /////////////////////////////////////////////////////////////////
401: final ParameterValue roiThreshold = (ParameterValue) ImageMosaicFormat.INPUT_IMAGE_THRESHOLD_VALUE
402: .createValue();
403: roiThreshold.setValue(new Double(roithreshold));
404: final ParameterValue inTransp = (ParameterValue) ImageMosaicFormat.INPUT_TRANSPARENT_COLOR
405: .createValue();
406: inTransp.setValue(inputTransparent);
407: final ParameterValue outTransp = (ParameterValue) ImageMosaicFormat.OUTPUT_TRANSPARENT_COLOR
408: .createValue();
409: outTransp.setValue(outputTransparent);
410: final ParameterValue blendPV = (ParameterValue) ImageMosaicFormat.FADING
411: .createValue();
412: blendPV.setValue(blend);
413:
414: // /////////////////////////////////////////////////////////////////
415: //
416: // Test the output coverage
417: //
418: //
419: // /////////////////////////////////////////////////////////////////
420: testCoverage(reader, new GeneralParameterValue[] {
421: roiThreshold, inTransp, blendPV, outTransp }, title);
422: }
423:
424: /**
425: * Tests the creation of a {@link GridCoverage2D} using the provided
426: * {@link ImageMosaicReader} as well as the provided {@link ParameterValue}.
427: *
428: * @param reader
429: * to use for creating a {@link GridCoverage2D}.
430: * @param value
431: * that control the actions to take for creating a
432: * {@link GridCoverage2D}.
433: * @param title
434: * to print out as the head of the frame in case we visualize it.
435: * @throws IOException
436: */
437: private void testCoverage(final ImageMosaicReader reader,
438: GeneralParameterValue[] values, String title)
439: throws IOException {
440: // /////////////////////////////////////////////////////////////////
441: //
442: // Test the coverage
443: //
444: //
445: // /////////////////////////////////////////////////////////////////
446: AbstractCoverage coverage = (AbstractCoverage) reader
447: .read(values);
448: assertNotNull(coverage);
449: if (TestData.isInteractiveTest())
450: show(((GridCoverage2D) coverage).getRenderedImage(), title);
451: else
452: ((GridCoverage2D) coverage).getRenderedImage().getData();
453: }
454:
455: /**
456: * Shows the provided {@link RenderedImage} ina {@link JFrame} using the
457: * provided <code>title</code> as the frame's title.
458: *
459: * @param image
460: * to show.
461: * @param title
462: * to use.
463: */
464: static void show(RenderedImage image, String title) {
465: final JFrame jf = new JFrame(title);
466: jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
467: jf.getContentPane().add(
468: new ScrollingImagePanel(image, 800, 800));
469: SwingUtilities.invokeLater(new Runnable() {
470:
471: public void run() {
472: jf.pack();
473: jf.setVisible(true);
474:
475: }
476: });
477:
478: }
479:
480: /**
481: * returns an {@link AbstractGridCoverage2DReader} for the provided
482: * {@link URL} and for the providede {@link AbstractGridFormat}.
483: *
484: * @param testURL
485: * points to a valid object to create an
486: * {@link AbstractGridCoverage2DReader} for.
487: * @param format
488: * to use for instantiating such a reader.
489: * @return a suitable {@link ImageMosaicReader}.
490: */
491: private ImageMosaicReader getReader(URL testURL,
492: final AbstractGridFormat format) {
493: final ImageMosaicReader reader = (ImageMosaicReader) format
494: .getReader(testURL);
495: assertNotNull(reader);
496: return reader;
497: }
498:
499: /**
500: * Tries to get an {@link AbstractGridFormat} for the provided URL.
501: *
502: * @param testURL
503: * points to a shapefile that is the index of a certain mosaic.
504: * @return a suitable {@link AbstractGridFormat}.
505: */
506: private AbstractGridFormat getFormat(URL testURL) {
507:
508: // /////////////////////////////////////////////////////////////////
509: //
510: // Get a reader
511: //
512: //
513: // /////////////////////////////////////////////////////////////////
514: final AbstractGridFormat format = (AbstractGridFormat) GridFormatFinder
515: .findFormat(testURL);
516: assertNotNull(format);
517: assertFalse("UknownFormat", format instanceof UnknownFormat);
518: return format;
519: }
520:
521: /**
522: * Testes {@link ImageMosaicReader} asking to crop the lower left quarter of
523: * the input coverage.
524: *
525: * @param title
526: * to use when showing image.
527: *
528: * @throws IOException
529: * @throws MismatchedDimensionException
530: * @throws FactoryException
531: */
532: private void imageMosaicCropTest(URL testURL, String title)
533: throws IOException, MismatchedDimensionException,
534: FactoryException {
535:
536: // /////////////////////////////////////////////////////////////////
537: //
538: // Get the resources as needed.
539: //
540: //
541: // /////////////////////////////////////////////////////////////////
542: assertNotNull(testURL);
543: final AbstractGridFormat format = getFormat(testURL);
544: final ImageMosaicReader reader = getReader(testURL, format);
545:
546: //
547: // /////////////////////////////////////////////////////////////////
548: //
549: // crop
550: //
551: //
552: // /////////////////////////////////////////////////////////////////
553: final ParameterValue gg = (ParameterValue) ImageMosaicFormat.READ_GRIDGEOMETRY2D
554: .createValue();
555: final GeneralEnvelope oldEnvelope = reader
556: .getOriginalEnvelope();
557: final GeneralEnvelope cropEnvelope = new GeneralEnvelope(
558: new double[] {
559: oldEnvelope.getLowerCorner().getOrdinate(0)
560: + oldEnvelope.getLength(0) / 2,
561: oldEnvelope.getLowerCorner().getOrdinate(1)
562: + oldEnvelope.getLength(1) / 2 },
563: new double[] {
564: oldEnvelope.getUpperCorner().getOrdinate(0),
565: oldEnvelope.getUpperCorner().getOrdinate(1) });
566: cropEnvelope.setCoordinateReferenceSystem(reader.getCrs());
567: gg.setValue(new GridGeometry2D(new GeneralGridRange(
568: new Rectangle(0, 0, 600, 300)), cropEnvelope));
569: final ParameterValue outTransp = (ParameterValue) ImageMosaicFormat.OUTPUT_TRANSPARENT_COLOR
570: .createValue();
571: outTransp.setValue(Color.black);
572:
573: // /////////////////////////////////////////////////////////////////
574: //
575: // Show the coverage
576: //
577: //
578: // /////////////////////////////////////////////////////////////////
579: testCoverage(reader, new GeneralParameterValue[] { gg,
580: outTransp }, title);
581:
582: }
583:
584: /**
585: * @param args
586: */
587: public static void main(String[] args) {
588: TestRunner.run(ImageMosaicReaderTest.suite());
589:
590: }
591:
592: protected void setUp() throws Exception {
593: super .setUp();
594: JAI.getDefaultInstance().getTileCache().setMemoryCapacity(
595: 256 * 1024 * 1024);
596: JAI.getDefaultInstance().getTileScheduler().setParallelism(5);
597: JAI.getDefaultInstance().getTileScheduler().setPriority(5);
598: JAI.getDefaultInstance().getTileScheduler()
599: .setPrefetchParallelism(5);
600: JAI.getDefaultInstance().getTileScheduler()
601: .setPrefetchPriority(5);
602:
603: rgbURL = TestData.url(this , "rgb/mosaic.shp");
604: rgbAURL = TestData.url(this , "rgba/modis.shp");
605: indexURL = TestData.url(this , "index/modis.shp");
606: indexAlphaURL = TestData.url(this , "index_alpha/modis.shp");
607: grayURL = TestData.url(this , "gray/dof.shp");
608: index_unique_paletteAlphaURL = TestData.url(this ,
609: "index_alpha_unique_palette/dof.shp");
610: //
611: // morandini = new File("C:\\work\\data\\m\\m.shp").toURL();
612:
613: interactive = TestData.isInteractiveTest();
614:
615: }
616:
617: }
|