org.geotools.utils.imagepyramid.PyramidLayerBuilder.java Source code

Java tutorial

Introduction

Here is the source code for org.geotools.utils.imagepyramid.PyramidLayerBuilder.java

Source

/*
 *    GeoTools - The Open Source Java GIS Toolkit
 *    http://geotools.org
 * 
 *    (C) 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.utils.imagepyramid;

import java.awt.Rectangle;
import java.awt.geom.Rectangle2D;
import java.io.File;
import java.io.IOException;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.imageio.ImageWriteParam;
import javax.media.jai.Interpolation;
import javax.media.jai.InterpolationNearest;

import org.apache.commons.cli2.Option;
import org.apache.commons.cli2.validation.InvalidArgumentException;
import org.apache.commons.cli2.validation.Validator;
import org.geotools.coverage.grid.GridCoverage2D;
import org.geotools.coverage.grid.GridEnvelope2D;
import org.geotools.coverage.grid.GridGeometry2D;
import org.geotools.coverage.grid.io.AbstractGridFormat;
import org.geotools.coverage.grid.io.OverviewPolicy;
import org.geotools.coverage.grid.io.imageio.GeoToolsWriteParams;
import org.geotools.coverage.processing.CoverageProcessor;
import org.geotools.factory.Hints;
import org.geotools.gce.geotiff.GeoTiffWriter;
import org.geotools.gce.imagemosaic.ImageMosaicFormat;
import org.geotools.gce.imagemosaic.ImageMosaicReader;
import org.geotools.geometry.GeneralEnvelope;
import org.geotools.utils.CoverageToolsConstants;
import org.geotools.utils.progress.BaseArgumentsManager;
import org.geotools.utils.progress.ExceptionEvent;
import org.geotools.utils.progress.ProcessingEvent;
import org.geotools.utils.progress.ProcessingEventListener;
import org.opengis.coverage.grid.GridEnvelope;
import org.opengis.parameter.GeneralParameterValue;
import org.opengis.parameter.ParameterValue;
import org.opengis.parameter.ParameterValueGroup;

/**
 * <p>
 * Usage:<br/> <code>PyramidLayerBuilder -h -v -s -t -f -a -o -p -c</code>
 * </p>
 * 
 * <pre>
 *                                                                                                                                            
 *                         where:                                                                                                                   
 *                          -h : Prints a nice command line Help                                                                                    
 *                          -v : Prints the tools Version                                                                                           
 *                          -s : Is the path where the raster(s) is(are) located                                                                    
 *                          -t : Is the tile dimensions as a couple width,height in pixels (e.g. 512,512)                                           
 *                          -f : Represents the scale factor. If you want a raster which is 1/2 resolution                                          
 *                               of the original, f should be 2                                                                                     
 *                          -a : Represents the Scaling algorithm to use. You can choose among one of the following                                 
 *                               nn, bil, avg, filt                                                                                                 
 *                          -o : Represents the output format. It can be one of the following                                                       
 *                               tiff, tif, gtiff, gtif, png, jpeg                                                                                  
 *                          -p : Is the Thread Priority, a number between 1 and 10 -&gt; 1 [LOW] - 5 [MED] - 10 [HIGH]                              
 *                          -c : Represents the JAI TileCache dimension. This is an optional parameter which allows                                 
 *                               you to tune the tool performances.                                                                                 
 * </pre>
 * 
 * <p>
 * Example of usage:<br/>
 * <code>PyramidLayerBuilder -t "512,512" -s "/usr/home/tmp/tiled/world.200412.3x21600x21600.a1_ref.shp" -f 2 -a nn -c 512</code>
 * </p>
 * 
 * @author Simone Giannecchini, GeoSolutions
 * @author Alessio Fabiani. GeoSolutions
 *
 *
 *
 *
 * @source $URL$
 * @version 0.3
 * 
 */
public class PyramidLayerBuilder extends BaseArgumentsManager implements Runnable, ProcessingEventListener {

    /** Static immutable map for scaling algorithms. */
    private static Set<String> scalingAlgorithms;
    static {
        scalingAlgorithms = new HashSet<String>();
        scalingAlgorithms.add("nn");
        scalingAlgorithms.add("bil");
        scalingAlgorithms.add("avg");
        scalingAlgorithms.add("filt");
    }

    /** Static immutable ap for scaling algorithms. */
    private static Set<String> outputFormats;
    static {
        outputFormats = new HashSet<String>();
        outputFormats.add("tiff");
        outputFormats.add("tif");
        outputFormats.add("gtiff");
        outputFormats.add("gtif");
        outputFormats.add("png");
        outputFormats.add("jpeg");

    }

    /** Default Logger * */
    private final static Logger LOGGER = org.geotools.util.logging.Logging
            .getLogger(PyramidLayerBuilder.class.toString());

    /** Program Version */
    private final static String VERSION = "0.3";

    private final static String NAME = "PyramidLayerBuilder";

    private Option inputLocationOpt;

    private Option outputLocationOpt;

    private Option tileDimOpt;

    private Option scaleAlgorithmOpt;

    private Option outFormatOpt;

    private double tileW;

    private double tileH;

    private File inputLocation;

    private File outputLocation;

    private String scaleAlgorithm;

    private String outputFormat;

    private Option scaleFactorOpt;

    private int scaleFactor;

    private Option compressionRatioOpt;

    private Option compressionTypeOpt;

    private Option internalTileDimOpt;

    private int internalTileWidth = CoverageToolsConstants.DEFAULT_INTERNAL_TILE_WIDTH;

    private int internalTileHeight = CoverageToolsConstants.DEFAULT_INTERNAL_TILE_HEIGHT;

    private String compressionScheme = CoverageToolsConstants.DEFAULT_COMPRESSION_SCHEME;

    private double compressionRatio = CoverageToolsConstants.DEFAULT_COMPRESSION_RATIO;

    public PyramidLayerBuilder() {
        super(NAME, VERSION);
        // /////////////////////////////////////////////////////////////////////
        // Options for the command line
        // /////////////////////////////////////////////////////////////////////
        inputLocationOpt = optionBuilder.withShortName("s").withLongName("source_directory").withArgument(
                argumentBuilder.withName("source").withMinimum(1).withMaximum(1).withValidator(new Validator() {

                    public void validate(List args) throws InvalidArgumentException {
                        final int size = args.size();
                        if (size > 1)
                            throw new InvalidArgumentException("Only one location can be chosen");
                        final File source = new File((String) args.get(0));
                        if (!source.isFile() || !source.exists())
                            throw new InvalidArgumentException(new StringBuilder("The provided source is invalid! ")

                                    .toString());
                    }

                }).create()).withDescription("path where files are located").withRequired(true).create();

        outputLocationOpt = optionBuilder.withShortName("d").withLongName("dest_directory")
                .withArgument(argumentBuilder.withName("destination").withMinimum(0).withMaximum(1).create())
                .withDescription("output directory, if none is provided, the \"tiled\" directory will be used")
                .withRequired(false).create();

        tileDimOpt = optionBuilder.withShortName("t").withLongName("tiled_dimension")
                .withArgument(argumentBuilder.withName("t").withMinimum(1).withMaximum(1).create())
                .withDescription("tile dimensions as a couple width,height in pixels").withRequired(true).create();

        scaleFactorOpt = optionBuilder.withShortName("f").withLongName("scale_factor").withArgument(
                argumentBuilder.withName("f").withMinimum(1).withMaximum(1).withValidator(new Validator() {

                    public void validate(List args) throws InvalidArgumentException {
                        final int size = args.size();
                        if (size > 1)
                            throw new InvalidArgumentException(
                                    "Only one scaling algorithm at a time can be chosen");
                        int factor = Integer.parseInt((String) args.get(0));
                        if (factor <= 0)
                            throw new InvalidArgumentException(
                                    new StringBuilder("The provided scale factor is negative! ")

                                            .toString());
                        if (factor == 1) {
                            LOGGER.warning("The scale factor is 1!");
                            System.exit(0);
                        }
                    }

                }).create()).withDescription("integer scale factor").withRequired(true).create();

        scaleAlgorithmOpt = optionBuilder.withShortName("a").withLongName("scaling_algorithm").withArgument(
                argumentBuilder.withName("a").withMinimum(0).withMaximum(1).withValidator(new Validator() {

                    public void validate(List args) throws InvalidArgumentException {
                        final int size = args.size();
                        if (size > 1)
                            throw new InvalidArgumentException(
                                    "Only one scaling algorithm at a time can be chosen");
                        if (!scalingAlgorithms.contains(args.get(0)))
                            throw new InvalidArgumentException(new StringBuilder("The output format ")
                                    .append(args.get(0)).append(" is not permitted").toString());

                    }
                }).create())
                .withDescription(
                        "name of the scaling algorithm, eeither one of average (a), filtered    (f), bilinear (bil), nearest neigbhor (nn)")
                .withRequired(false).create();

        outFormatOpt = optionBuilder.withShortName("o").withLongName("out_format")
                .withArgument(
                        argumentBuilder.withName("o").withMinimum(0).withMaximum(1).withDescription("output format")
                                // .withDefault("gtiff")
                                .withValidator(new Validator() {

                                    public void validate(List args) throws InvalidArgumentException {
                                        final int size = args.size();
                                        if (size > 1)
                                            throw new InvalidArgumentException(
                                                    "Only one output format at a time can be specified");
                                        if (!outputFormats.contains(args.get(0)))
                                            throw new InvalidArgumentException(
                                                    new StringBuilder("The output format ").append(args.get(0))
                                                            .append(" is not permitted").toString());

                                    }
                                }).create())
                .withDescription("output format").withRequired(false).create();

        compressionTypeOpt = optionBuilder.withShortName("z").withLongName("compressionType")
                .withDescription("compression type.").withArgument(argumentBuilder.withName("compressionType")
                        .withMinimum(0).withMaximum(1).withValidator(new Validator() {

                            public void validate(List args) throws InvalidArgumentException {
                                final int size = args.size();
                                if (size > 1)
                                    throw new InvalidArgumentException(
                                            "Only one scaling algorithm at a time can be chosen");

                            }
                        }).create())
                .withRequired(false).create();

        compressionRatioOpt = optionBuilder.withShortName("r").withLongName("compressionRatio")
                .withDescription("compression ratio.").withArgument(argumentBuilder.withName("compressionRatio")
                        .withMinimum(0).withMaximum(1).withValidator(new Validator() {

                            public void validate(List args) throws InvalidArgumentException {
                                final int size = args.size();
                                if (size > 1)
                                    throw new InvalidArgumentException(
                                            "Only one scaling algorithm at a time can be chosen");
                                final String val = (String) args.get(0);

                                final double value = Double.parseDouble(val);
                                if (value <= 0 || value > 1)
                                    throw new InvalidArgumentException("Invalid compressio ratio");

                            }
                        }).create())
                .withRequired(false).create();

        internalTileDimOpt = optionBuilder.withShortName("it").withLongName("internal_tile_dimension")
                .withArgument(argumentBuilder.withName("it").withMinimum(0).withMaximum(1).create())
                .withDescription("Internal width and height of each tile we generate").withRequired(false).create();

        addOption(compressionTypeOpt);
        addOption(compressionRatioOpt);
        addOption(inputLocationOpt);
        addOption(tileDimOpt);
        addOption(scaleFactorOpt);
        addOption(scaleAlgorithmOpt);
        addOption(internalTileDimOpt);

        // /////////////////////////////////////////////////////////////////////
        //
        // Help Formatter
        //
        // /////////////////////////////////////////////////////////////////////
        finishInitialization();
    }

    /**
     * 
     * @param args
     * @throws IOException
     * @throws IllegalArgumentException
     * @throws InterruptedException
     */
    public static void main(String[] args) throws IllegalArgumentException, IOException, InterruptedException {

        final PyramidLayerBuilder pyramidBuilder = new PyramidLayerBuilder();
        pyramidBuilder.addProcessingEventListener(pyramidBuilder);
        if (pyramidBuilder.parseArgs(args)) {
            final Thread t = new Thread(pyramidBuilder, "PyramidBuilder");
            t.setPriority(pyramidBuilder.getPriority());
            t.start();
            try {
                t.join();
            } catch (InterruptedException e) {
                LOGGER.log(Level.SEVERE, e.getLocalizedMessage(), e);
            }

        } else
            LOGGER.fine("Exiting...");

    }

    public boolean parseArgs(String[] args) {
        if (!super.parseArgs(args))
            return false;

        // ////////////////////////////////////////////////////////////////
        //
        // parsing command line parameters and setting up
        // Mosaic Index Builder options
        //
        // ////////////////////////////////////////////////////////////////
        inputLocation = new File((String) getOptionValue(inputLocationOpt));

        // tile dim
        final String tileDim = (String) getOptionValue(tileDimOpt);
        final String[] pairs = tileDim.split(",");
        tileW = Integer.parseInt(pairs[0]);
        tileH = Integer.parseInt(pairs[1]);

        // //
        //
        // scale factor
        //
        // //
        final String scaleF = (String) getOptionValue(scaleFactorOpt);
        scaleFactor = Integer.parseInt(scaleF);

        // output files' directory
        if (hasOption(outputLocationOpt))
            outputLocation = new File((String) getOptionValue(outputLocationOpt));
        else
            outputLocation = new File(inputLocation.getParentFile(), String.valueOf(scaleFactor));

        // //
        //
        // scaling algorithm
        //
        // //
        scaleAlgorithm = (String) getOptionValue(scaleAlgorithmOpt);
        if (scaleAlgorithm == null)
            scaleAlgorithm = "nn";

        // //

        // //
        //
        // output format
        //
        // //
        outputFormat = (String) getOptionValue(outFormatOpt);

        return true;

    }

    public void run() {

        // /////////////////////////////////////////////////////////////////////
        //
        //
        // PARSING INPUT PARAMETERS
        // 
        // 
        // /////////////////////////////////////////////////////////////////////
        StringBuilder message = new StringBuilder("Requested scale factor is ").append(scaleFactor);
        if (LOGGER.isLoggable(Level.FINE))
            LOGGER.fine(message.toString());
        fireEvent(message.toString(), 0);

        // /////////////////////////////////////////////////////////////////////
        //
        //
        // Opening the base mosaic
        // 
        // 
        // /////////////////////////////////////////////////////////////////////
        // mosaic reader
        message = new StringBuilder("Acquiring a mosaic reader to mosaic ").append(inputLocation);
        if (LOGGER.isLoggable(Level.FINE))
            LOGGER.fine(message.toString());
        fireEvent(message.toString(), 0);

        ImageMosaicReader inReader = null;
        try {
            inReader = new ImageMosaicReader(inputLocation,
                    new Hints(Hints.OVERVIEW_POLICY, OverviewPolicy.IGNORE));
        } catch (IOException e) {
            LOGGER.log(Level.SEVERE, e.getLocalizedMessage(), e);
            fireException(e);
            return;
        }

        // /////////////////////////////////////////////////////////////////////
        //
        //
        // Preparing all the params
        // 
        // 
        // /////////////////////////////////////////////////////////////////////
        // output files' directory
        if (!outputLocation.exists())
            outputLocation.mkdir();

        // getting envelope and other information about dimension
        final GeneralEnvelope envelope = inReader.getOriginalEnvelope();
        message = new StringBuilder("Original envelope is ").append(envelope.toString());
        if (LOGGER.isLoggable(Level.FINE))
            LOGGER.fine(message.toString());
        fireEvent(message.toString(), 0);

        final GridEnvelope range = inReader.getOriginalGridRange();
        message = new StringBuilder("Original range is ").append(range.toString());
        if (LOGGER.isLoggable(Level.FINE))
            LOGGER.fine(message.toString());
        fireEvent(message.toString(), 0);

        // new number of rows and columns
        final double newWidth = (range.getSpan(0) * 1.0) / scaleFactor;
        final double newHeight = (range.getSpan(1) * 1.0) / scaleFactor;
        if (tileW > newWidth)
            tileW = newWidth;
        if (tileH > newHeight)
            tileH = newHeight;

        message = new StringBuilder("New dimension is (W,H)==(").append(newWidth).append(",").append(newHeight)
                .append(")");
        if (LOGGER.isLoggable(Level.FINE))
            LOGGER.fine(message.toString());
        fireEvent(message.toString(), 0);

        int newCols = (int) (newWidth / tileW);
        int newRows = (int) (newHeight / tileH);
        final boolean hasRemainingColum = (newWidth % tileW) != 0;
        final boolean hasRemainingRow = (newHeight % tileH) != 0;
        message = new StringBuilder("New matrix dimension is (cols,rows)==(").append(newCols).append(",")
                .append(newRows).append(")");
        if (LOGGER.isLoggable(Level.FINE))
            LOGGER.fine(message.toString());
        fireEvent(message.toString(), 0);

        final double minx = envelope.getMinimum(0);
        final double miny = envelope.getMinimum(1);
        final double maxx = envelope.getMaximum(0);
        final double maxy = envelope.getMaximum(1);

        double _maxx = 0.0;
        double _maxy = 0.0;
        double _minx = 0.0;
        double _miny = 0.0;

        // ///////////////////////////////////////////////////////////////////
        //
        // MAIN LOOP
        //
        //
        // ///////////////////////////////////////////////////////////////////
        newRows += hasRemainingRow ? 1 : 0;
        newCols += hasRemainingColum ? 1 : 0;
        final double totalNumberOfFile = newRows * newCols;

        // getting resolution of each tile
        final double tileGeoWidth = envelope.getSpan(0) / newCols;
        final double tileGeoHeight = envelope.getSpan(1) / newRows;

        final int uppers[] = range.getHigh().getCoordinateValues();
        uppers[0]++;
        uppers[1]++;
        final double newRange[] = new double[] { uppers[0] / newCols, uppers[1] / newRows };
        final CoverageProcessor processor = CoverageProcessor.getInstance();
        for (int i = 0; i < newRows; i++)
            for (int j = 0; j < newCols; j++) {

                // //
                //
                // computing the bbox for this tile
                //
                // //
                _maxx = minx + (j + 1) * tileGeoWidth;
                _minx = minx + (j) * tileGeoWidth;
                _maxy = miny + (i + 1) * tileGeoHeight;
                _miny = miny + (i) * tileGeoHeight;
                if (_maxx > maxx)
                    _maxx = maxx;
                if (_maxy > maxy)
                    _maxy = maxy;

                // //
                //
                // creating the output file
                //
                // //
                final File fileOut = new File(outputLocation, new StringBuilder("mosaic").append("_")
                        .append(Integer.toString(i * newCols + j)).append(".").append("tiff").toString());
                if (fileOut.exists())
                    fileOut.delete();

                message = new StringBuilder("Preparing tile (col,row)==(").append(j).append(",").append(i)
                        .append(") to file ").append(fileOut);
                if (LOGGER.isLoggable(Level.FINE))
                    LOGGER.fine(message.toString());
                fireEvent(message.toString(), (j + i * newCols) / totalNumberOfFile);

                // //
                //
                // building gridgeometry for the read operation
                //
                // //
                final ParameterValue<GridGeometry2D> gg = ImageMosaicFormat.READ_GRIDGEOMETRY2D.createValue();
                final GeneralEnvelope cropEnvelope = new GeneralEnvelope(new double[] { _minx, _miny },
                        new double[] { _maxx, _maxy });
                cropEnvelope.setCoordinateReferenceSystem(inReader.getCrs());
                //we need to supply the requeste grid range but we use a fake one since we are using the ignore overviews switch 
                gg.setValue(new GridGeometry2D(new GridEnvelope2D(new Rectangle(0, 0, 800, 800)), cropEnvelope));
                message = new StringBuilder("Reading with grid envelope ").append(cropEnvelope.toString());
                if (LOGGER.isLoggable(Level.FINE))
                    LOGGER.fine(message.toString());
                fireEvent(message.toString(), (j + i * newCols) / totalNumberOfFile);

                // //
                //
                // read the needed part and then crop to be sure that we have what we need
                //
                // //
                GridCoverage2D gc;
                try {
                    gc = (GridCoverage2D) inReader.read(new GeneralParameterValue[] { gg });

                } catch (IOException e) {
                    LOGGER.log(Level.SEVERE, e.getLocalizedMessage(), e);
                    fireEvent(e.getLocalizedMessage(), 0);
                    return;
                }

                ParameterValueGroup param = processor.getOperation("CoverageCrop").getParameters();
                param.parameter("Source").setValue(gc);
                param.parameter("Envelope").setValue(cropEnvelope);
                param.parameter("ConserveEnvelope").setValue(Boolean.TRUE);
                final GridCoverage2D cropped = (GridCoverage2D) processor.doOperation(param);

                // //
                //
                // Adjusting the resolution in order to be the same as for all the others coverage
                //
                // //
                final GridEnvelope2D newGridrange = new GridEnvelope2D(
                        new Rectangle2D.Double(0.0, 0.0, newRange[0], newRange[1]).getBounds());
                final GridGeometry2D scaledGridGeometry = new GridGeometry2D(newGridrange, cropEnvelope);
                param = processor.getOperation("Resample").getParameters();
                param.parameter("Source").setValue(cropped);
                param.parameter("CoordinateReferenceSystem").setValue(inReader.getCrs());
                param.parameter("GridGeometry").setValue(scaledGridGeometry);
                param.parameter("InterpolationType")
                        .setValue(Interpolation.getInstance(Interpolation.INTERP_NEAREST));
                gc = (GridCoverage2D) processor.doOperation(param);

                message = new StringBuilder("Scaling...");
                if (LOGGER.isLoggable(Level.FINE))
                    LOGGER.fine(message.toString());
                fireEvent(message.toString(), 0);

                if (scaleAlgorithm.equalsIgnoreCase("nn")) {
                    param = processor.getOperation("Scale").getParameters();
                    param.parameter("Source").setValue(gc);
                    param.parameter("xScale").setValue(new Float(1.0 / scaleFactor));
                    param.parameter("yScale").setValue(new Float(1.0 / scaleFactor));
                    param.parameter("xTrans").setValue(new Float(0));
                    param.parameter("yTrans").setValue(new Float(0));
                    param.parameter("Interpolation")
                            .setValue(Interpolation.getInstance(Interpolation.INTERP_BILINEAR));
                    gc = (GridCoverage2D) CoverageToolsConstants.SCALE_FACTORY.doOperation(param, new Hints());
                } else if (scaleAlgorithm.equalsIgnoreCase("filt")) {
                    // scaling
                    param = CoverageToolsConstants.FILTERED_SUBSAMPLE_FACTORY.getParameters();
                    param.parameter("source").setValue(gc);
                    param.parameter("scaleX").setValue(new Integer((int) scaleFactor));
                    param.parameter("scaleY").setValue(new Integer((int) scaleFactor));
                    param.parameter("qsFilterArray")
                            .setValue(new float[] { 0.5F, 1.0F / 3.0F, 0.0F, -1.0F / 12.0F });
                    param.parameter("Interpolation").setValue(new InterpolationNearest());
                    gc = (GridCoverage2D) CoverageToolsConstants.FILTERED_SUBSAMPLE_FACTORY.doOperation(param,
                            new Hints());
                } else if (scaleAlgorithm.equalsIgnoreCase("bil")) {
                    param = processor.getOperation("Scale").getParameters();
                    param.parameter("Source").setValue(gc);
                    param.parameter("xScale").setValue(new Float(1.0 / scaleFactor));
                    param.parameter("yScale").setValue(new Float(1.0 / scaleFactor));
                    param.parameter("xTrans").setValue(new Float(0));
                    param.parameter("yTrans").setValue(new Float(0));
                    param.parameter("Interpolation")
                            .setValue(Interpolation.getInstance(Interpolation.INTERP_BILINEAR));
                    gc = (GridCoverage2D) CoverageToolsConstants.SCALE_FACTORY.doOperation(param, new Hints());
                } else if (scaleAlgorithm.equalsIgnoreCase("avg")) {
                    param = processor.getOperation("SubsampleAverage").getParameters();
                    param.parameter("Source").setValue(gc);
                    param.parameter("scaleX").setValue(new Double(1.0 / scaleFactor));
                    param.parameter("scaleY").setValue(new Double(1.0 / scaleFactor));
                    param.parameter("Interpolation").setValue(scaleFactor);
                    gc = (GridCoverage2D) CoverageToolsConstants.SUBSAMPLE_AVERAGE_FACTORY.doOperation(param,
                            new Hints());
                } else
                    throw new IllegalArgumentException("The provided scale algorithm is not availaible");

                // //
                //
                // Writing out this coverage
                //
                // //
                message = new StringBuilder("Writing out...");
                if (LOGGER.isLoggable(Level.FINE))
                    LOGGER.fine(message.toString());
                fireEvent(message.toString(), (j + i * newCols) / totalNumberOfFile);

                try {

                    final GeoTiffWriter writerWI = new GeoTiffWriter(fileOut);
                    final GeoToolsWriteParams wp = ((AbstractGridFormat) writerWI.getFormat())
                            .getDefaultImageIOWriteParameters();
                    if (this.compressionScheme != null) {
                        wp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
                        wp.setCompressionType(this.compressionScheme);
                        wp.setCompressionQuality((float) this.compressionRatio);
                    }
                    wp.setTilingMode(ImageWriteParam.MODE_EXPLICIT);
                    wp.setTiling(internalTileWidth, internalTileHeight, 0, 0);
                    writerWI.write(gc, null);
                    writerWI.dispose();

                } catch (IOException e) {
                    LOGGER.log(Level.SEVERE, e.getLocalizedMessage(), e);
                    fireEvent(e.getLocalizedMessage(), 0);
                    return;
                }

            }

        message = new StringBuilder("Done...");
        if (LOGGER.isLoggable(Level.FINE))
            LOGGER.fine(message.toString());
        fireEvent(message.toString(), 100);

    }

    public void getNotification(ProcessingEvent event) {
        LOGGER.info(new StringBuilder("Progress is at ").append(event.getPercentage()).append("\n")
                .append("attached message is: ").append(event.getMessage()).toString());
    }

    public void exceptionOccurred(ExceptionEvent event) {
        LOGGER.log(Level.SEVERE, "An error occurred during processing", event.getException());
    }

    public void setInputLocation(File inputLocation) {
        this.inputLocation = inputLocation;
    }

    public void setOutputLocation(File outputLocation) {
        this.outputLocation = outputLocation;
    }

    /**
     * @return the outputFormat
     */
    public String getOutputFormat() {
        return outputFormat;
    }

    /**
     * @param outputFormat
     *            the outputFormat to set
     */
    public void setOutputFormat(String outputFormat) {
        this.outputFormat = outputFormat;
    }

    /**
     * @return the scaleAlgorithm
     */
    public String getScaleAlgorithm() {
        return scaleAlgorithm;
    }

    /**
     * @param scaleAlgorithm
     *            the scaleAlgorithm to set
     */
    public void setScaleAlgorithm(String scaleAlgorithm) {
        this.scaleAlgorithm = scaleAlgorithm;
    }

    /**
     * @return the scaleFactor
     */
    public int getScaleFactor() {
        return scaleFactor;
    }

    /**
     * @param scaleFactor
     *            the scaleFactor to set
     */
    public void setScaleFactor(int scaleFactor) {
        this.scaleFactor = scaleFactor;
    }

    public File getInputLocation() {
        return inputLocation;
    }

    public File getOutputLocation() {
        return outputLocation;
    }

    /**
     * @return the tileH
     */
    public double getTileHeight() {
        return tileH;
    }

    /**
     * @param tileH
     *            the tileH to set
     */
    public void setTileHeight(int tileH) {
        this.tileH = tileH;
    }

    /**
     * @return the tileW
     */
    public double getTileWidth() {
        return tileW;
    }

    /**
     * @param tileW
     *            the tileW to set
     */
    public void setTileWidth(int tileW) {
        this.tileW = tileW;
    }

    public double getCompressionRatio() {
        return compressionRatio;
    }

    public String getCompressionScheme() {
        return compressionScheme;
    }

    public void setCompressionRatio(double compressionRatio) {
        this.compressionRatio = compressionRatio;
    }

    public void setCompressionScheme(String compressionScheme) {
        this.compressionScheme = compressionScheme;
    }

    public int getInternalTileHeight() {
        return internalTileHeight;
    }

    public int getInternalTileWidth() {
        return internalTileWidth;
    }

    public void setInternalTileHeight(int internalTileHeight) {
        this.internalTileHeight = internalTileHeight;
    }

    public void setInternalTileWidth(int internalTileWidth) {
        this.internalTileWidth = internalTileWidth;
    }

}