/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2006-2008, Open Source Geospatial Foundation (OSGeo) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ package org.geotools.gce.imagemosaic; import it.geosolutions.imageio.plugins.jp2ecw.JP2GDALEcwImageReaderSpi; import it.geosolutions.imageio.plugins.jp2kakadu.JP2GDALKakaduImageReaderSpi; import it.geosolutions.imageio.plugins.jp2mrsid.JP2GDALMrSidImageReaderSpi; import it.geosolutions.imageio.utilities.ImageIOUtilities; import java.awt.RenderingHints; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Collections; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import javax.imageio.spi.ImageReaderSpi; import org.geotools.coverage.grid.io.GridFormatFactorySpi; import org.geotools.coverageio.gdal.jp2ecw.JP2ECWFormatFactory; import org.geotools.coverageio.gdal.jp2kak.JP2KFormatFactory; import org.geotools.coverageio.gdal.jp2mrsid.JP2MrSIDFormatFactory; import com.sun.media.imageioimpl.common.PackageUtil; import com.sun.media.imageioimpl.plugins.jpeg2000.J2KImageReaderCodecLibSpi; import com.sun.media.imageioimpl.plugins.jpeg2000.J2KImageReaderSpi; import com.sun.media.imageioimpl.plugins.tiff.TIFFImageReaderSpi; /** * Implementation of the GridCoverageFormat service provider interface for * mosaic of georeferenced images. * * @author Simone Giannecchini, GeoSolutions S.A.S. * @since 2.3 */ public final class ImageMosaicFormatFactory implements GridFormatFactorySpi { /** Logger. */ private final static Logger LOGGER = org.geotools.util.logging.Logging.getLogger(ImageMosaicFormatFactory.class); private static final String KAKADU_SPI = "it.geosolutions.imageio.plugins.jp2k.JP2KKakaduImageReaderSpi"; static{ replaceTIFF(); if(JP2KAK()){ replaceJP2KAK(); } else{ if(JP2ECW()){ replaceECW(); } if(JP2MRSID()){ replaceMRSID(); } if(JP2GDALKAK()){ replaceGDALKAK(); } } } /** * Tells me if this plugin will work on not given the actual installation. * * <p> * Dependecies are mostly from JAI and ImageIO so if they are installed you * should not have many problems. * * @return False if something's missing, true otherwise. */ public boolean isAvailable() { boolean available = true; // if these classes are here, then the runtine environment has // access to JAI and the JAI ImageI/O toolbox. try { Class.forName("javax.media.jai.JAI"); Class.forName("com.sun.media.jai.operator.ImageReadDescriptor"); } catch (ClassNotFoundException cnf) { available = false; } return available; } private static boolean JP2KAK() { try{ @SuppressWarnings("unused") Class<?> cl = Class.forName(KAKADU_SPI); Class<?> utilityClass = Class.forName("it.geosolutions.util.KakaduUtilities"); final Method method = utilityClass.getDeclaredMethod("isKakaduAvailable", (Class[])null); if (method != null){ Boolean isAvailable = (Boolean) method.invoke(null, null); return isAvailable.booleanValue(); } } catch (ClassNotFoundException e) { if (LOGGER.isLoggable(Level.FINE)) LOGGER.log(Level.FINE, "Unable to load kakadu JPEG2000 reader spi",e); } catch (SecurityException e) { if (LOGGER.isLoggable(Level.FINE)) LOGGER.log(Level.FINE, "Unable to load kakadu JPEG2000 reader spi",e); } catch (NoSuchMethodException e) { if (LOGGER.isLoggable(Level.FINE)) LOGGER.log(Level.FINE, "Unable to load kakadu JPEG2000 reader spi",e); } catch (IllegalArgumentException e) { if (LOGGER.isLoggable(Level.FINE)) LOGGER.log(Level.FINE, "Unable to load kakadu JPEG2000 reader spi",e); } catch (IllegalAccessException e) { if (LOGGER.isLoggable(Level.FINE)) LOGGER.log(Level.FINE, "Unable to load kakadu JPEG2000 reader spi",e); } catch (InvocationTargetException e) { if (LOGGER.isLoggable(Level.FINE)) LOGGER.log(Level.FINE, "Unable to load kakadu JPEG2000 reader spi",e); } return false; } private static void replaceJP2KAK() { try{ Class.forName(KAKADU_SPI); // imageio kakJP2 reader final String imageioJ2KImageReaderCodecName=J2KImageReaderCodecLibSpi.class.getName(); if(PackageUtil.isCodecLibAvailable()){ boolean succeeded=ImageIOUtilities.replaceProvider(ImageReaderSpi.class, KAKADU_SPI, imageioJ2KImageReaderCodecName, "JPEG 2000"); if(!succeeded) if (LOGGER.isLoggable(Level.WARNING)) LOGGER.warning("Unable to set ordering between jp2 readers spi-"+KAKADU_SPI+":"+imageioJ2KImageReaderCodecName); } // imageio kakJP2 reader final String imageioJ2KImageReaderName=J2KImageReaderSpi.class.getName(); final boolean succeeded=ImageIOUtilities.replaceProvider(ImageReaderSpi.class, KAKADU_SPI, imageioJ2KImageReaderName, "JPEG 2000"); if(!succeeded) if (LOGGER.isLoggable(Level.FINE)) LOGGER.warning("Unable to set ordering between jp2 readers spi-"+KAKADU_SPI+":"+imageioJ2KImageReaderName); } catch (ClassNotFoundException e) { if (LOGGER.isLoggable(Level.WARNING)) LOGGER.log(Level.WARNING, "Unable to load specific JPEG2000 reader spi",e); } } private static void replaceTIFF() { try{ //check if our tiff plugin is in the path final String customTiffName=it.geosolutions.imageioimpl.plugins.tiff.TIFFImageReaderSpi.class.getName(); Class.forName(customTiffName); // imageio tiff reader final String imageioTiffName=TIFFImageReaderSpi.class.getName(); final boolean succeeded=ImageIOUtilities.replaceProvider(ImageReaderSpi.class, customTiffName, imageioTiffName, "tiff"); if(!succeeded) if (LOGGER.isLoggable(Level.FINE)) LOGGER.warning("Unable to set ordering between tiff readers spi"); } catch (ClassNotFoundException e) { if (LOGGER.isLoggable(Level.WARNING)) LOGGER.log(Level.WARNING,"Unable to load specific TIFF reader spi",e); } } private static boolean JP2GDALKAK() { return new JP2KFormatFactory().isAvailable(); } private static void replaceGDALKAK() { try{ //check if our kakJP2 plugin is in the path final String kakJP2=JP2GDALKakaduImageReaderSpi.class.getName(); Class.forName(kakJP2); // imageio kakJP2 reader final String imageioJ2KImageReaderCodecName=J2KImageReaderCodecLibSpi.class.getName(); if(PackageUtil.isCodecLibAvailable()){ boolean succeeded=ImageIOUtilities.replaceProvider(ImageReaderSpi.class, kakJP2, imageioJ2KImageReaderCodecName, "JPEG 2000"); if(!succeeded) if (LOGGER.isLoggable(Level.FINE)) LOGGER.warning("Unable to set ordering between jp2 readers spi-"+kakJP2+":"+imageioJ2KImageReaderCodecName); } // imageio kakJP2 reader final String imageioJ2KImageReaderName=J2KImageReaderSpi.class.getName(); final boolean succeeded=ImageIOUtilities.replaceProvider(ImageReaderSpi.class, kakJP2, imageioJ2KImageReaderName, "JPEG 2000"); if(!succeeded) if (LOGGER.isLoggable(Level.FINE)) LOGGER.warning("Unable to set ordering between jp2 readers spi-"+kakJP2+":"+imageioJ2KImageReaderName); } catch (ClassNotFoundException e) { if (LOGGER.isLoggable(Level.WARNING)) LOGGER.log(Level.WARNING, "Unable to load specific JPEG2000 reader spi",e); } } private static void replaceMRSID() { try{ //check if our mrsidJP2 plugin is in the path final String mrsidJP2=JP2GDALMrSidImageReaderSpi.class.getName(); Class.forName(mrsidJP2); // imageio tiff reader final String imageioJ2KImageReaderCodecName=J2KImageReaderCodecLibSpi.class.getName(); if(PackageUtil.isCodecLibAvailable()){ boolean succeeded=ImageIOUtilities.replaceProvider(ImageReaderSpi.class, mrsidJP2, imageioJ2KImageReaderCodecName, "JPEG 2000"); if(!succeeded) if (LOGGER.isLoggable(Level.FINE)) LOGGER.warning("Unable to set ordering between jp2 readers spi-"+mrsidJP2+":"+imageioJ2KImageReaderCodecName); } // imageio mrsidJP2 reader final String imageioJ2KImageReaderName=J2KImageReaderSpi.class.getName(); final boolean succeeded=ImageIOUtilities.replaceProvider(ImageReaderSpi.class, mrsidJP2, imageioJ2KImageReaderName, "JPEG 2000"); if(!succeeded) if (LOGGER.isLoggable(Level.FINE)) LOGGER.warning("Unable to set ordering between jp2 readers spi-"+mrsidJP2+":"+imageioJ2KImageReaderName); } catch (ClassNotFoundException e) { if (LOGGER.isLoggable(Level.WARNING)) LOGGER.log(Level.WARNING, "Unable to load specific JPEG2000 reader spi",e); } } private static boolean JP2MRSID() { return new JP2MrSIDFormatFactory().isAvailable(); } private static void replaceECW() { try{ //check if our ecwJP2 plugin is in the path final String ecwJP2=JP2GDALEcwImageReaderSpi.class.getName(); Class.forName(ecwJP2); // imageio ecwJP2 reader final String imageioJ2KImageReaderCodecName=J2KImageReaderCodecLibSpi.class.getName(); if(PackageUtil.isCodecLibAvailable()){ boolean succeeded=ImageIOUtilities.replaceProvider(ImageReaderSpi.class, ecwJP2, imageioJ2KImageReaderCodecName, "JPEG 2000"); if(!succeeded) if (LOGGER.isLoggable(Level.FINE)) LOGGER.warning("Unable to set ordering between jp2 readers spi-"+ecwJP2+":"+imageioJ2KImageReaderCodecName); } // imageio ecwJP2 reader final String imageioJ2KImageReaderName=J2KImageReaderSpi.class.getName(); final boolean succeeded=ImageIOUtilities.replaceProvider(ImageReaderSpi.class, ecwJP2, imageioJ2KImageReaderName, "JPEG 2000"); if(!succeeded) if (LOGGER.isLoggable(Level.FINE)) LOGGER.warning("Unable to set ordering between jp2 readers spi-"+ecwJP2+":"+imageioJ2KImageReaderName); } catch (ClassNotFoundException e) { if (LOGGER.isLoggable(Level.WARNING)) LOGGER.log(Level.WARNING, "Unable to load specific JPEG2000 reader spi",e); } } private static boolean JP2ECW() { return new JP2ECWFormatFactory().isAvailable(); } /** * @see GridFormatFactorySpi#createFormat(). */ public ImageMosaicFormat createFormat() { return new ImageMosaicFormat(); } /** * Returns the implementation hints. The default implementation returns an * empty map. * * @return An empty map. */ public Map<RenderingHints.Key, ?> getImplementationHints() { return Collections.emptyMap(); } }