0001: package it.geosolutions.utils.imagepyramid;
0002:
0003: import it.geosolutions.utils.progress.ExceptionEvent;
0004: import it.geosolutions.utils.progress.ProcessingEvent;
0005: import it.geosolutions.utils.progress.ProcessingEventListener;
0006: import it.geosolutions.utils.progress.ProgressManager;
0007:
0008: import java.awt.Rectangle;
0009: import java.awt.geom.Rectangle2D;
0010: import java.io.File;
0011: import java.io.IOException;
0012: import java.util.ArrayList;
0013: import java.util.List;
0014: import java.util.logging.Level;
0015: import java.util.logging.Logger;
0016:
0017: import javax.media.jai.Interpolation;
0018: import javax.media.jai.InterpolationBilinear;
0019: import javax.media.jai.InterpolationNearest;
0020: import javax.media.jai.JAI;
0021:
0022: import org.apache.commons.cli2.option.DefaultOption;
0023: import org.apache.commons.cli2.option.GroupImpl;
0024: import org.apache.commons.cli2.util.HelpFormatter;
0025: import org.apache.commons.cli2.validation.InvalidArgumentException;
0026: import org.apache.commons.cli2.validation.Validator;
0027: import org.geotools.coverage.grid.GeneralGridRange;
0028: import org.geotools.coverage.grid.GridCoverage2D;
0029: import org.geotools.coverage.grid.GridGeometry2D;
0030: import org.geotools.coverage.processing.DefaultProcessor;
0031: import org.geotools.coverage.processing.operation.FilteredSubsample;
0032: import org.geotools.coverage.processing.operation.Scale;
0033: import org.geotools.coverage.processing.operation.SubsampleAverage;
0034: import org.geotools.factory.Hints;
0035: import org.geotools.gce.geotiff.GeoTiffWriter;
0036: import org.geotools.gce.imagemosaic.ImageMosaicFormat;
0037: import org.geotools.gce.imagemosaic.ImageMosaicReader;
0038: import org.geotools.geometry.GeneralEnvelope;
0039: import org.opengis.parameter.GeneralParameterValue;
0040: import org.opengis.parameter.ParameterValue;
0041: import org.opengis.parameter.ParameterValueGroup;
0042:
0043: /**
0044: * <p>
0045: * Usage:<br/> <code>PyramidLayerBuilder -h -v -s -t -f -a -o -p -c</code>
0046: * </p>
0047: *
0048: * <pre>
0049: *
0050: * where:
0051: * -h : Prints a nice command line Help
0052: * -v : Prints the tools Version
0053: * -s : Is the path where the raster(s) is(are) located
0054: * -t : Is the tile dimensions as a couple width,height in pixels (e.g. 512,512)
0055: * -f : Represents the scale factor. If you want a raster which is 1/2 resolution
0056: * of the original, f should be 2
0057: * -a : Represents the Scaling algorithm to use. You can choose among one of the following
0058: * nn, bil, avg, filt
0059: * -o : Represents the output format. It can be one of the following
0060: * tiff, tif, gtiff, gtif, png, jpeg
0061: * -p : Is the Thread Priority, a number between 1 and 10 -> 1 [LOW] - 5 [MED] - 10 [HIGH]
0062: * -c : Represents the JAI TileCache dimension. This is an optional parameter which allows
0063: * you to tune the tool performances.
0064: * </pre>
0065: *
0066: * <p>
0067: * Example of usage:<br/>
0068: * <code>PyramidLayerBuilder -t "512,512" -s "/usr/home/tmp/tiled/world.200412.3x21600x21600.a1_ref.shp" -f 2 -a nn -c 512</code>
0069: * </p>
0070: *
0071: * @author Simone Giannecchini
0072: * @author Alessio Fabiani
0073: * @version 0.2
0074: *
0075: */
0076: public class PyramidLayerBuilder extends ProgressManager implements
0077: Runnable, ProcessingEventListener {
0078:
0079: /** Static immutable ap for scaling algorithms. */
0080: private static List scalingAlgorithms;
0081: static {
0082: scalingAlgorithms = new ArrayList(4);
0083: scalingAlgorithms.add("nn");
0084: scalingAlgorithms.add("bil");
0085: scalingAlgorithms.add("avg");
0086: scalingAlgorithms.add("filt");
0087: }
0088:
0089: /** Static immutable ap for scaling algorithms. */
0090: private static List outputFormats;
0091: static {
0092: outputFormats = new ArrayList(6);
0093: outputFormats.add("tiff");
0094: outputFormats.add("tif");
0095: outputFormats.add("gtiff");
0096: outputFormats.add("gtif");
0097: outputFormats.add("png");
0098: outputFormats.add("jpeg");
0099:
0100: }
0101:
0102: /** Default Logger * */
0103: private final static Logger LOGGER = org.geotools.util.logging.Logging
0104: .getLogger(PyramidLayerBuilder.class.toString());
0105:
0106: /** Program Version */
0107: private final static String versionNumber = "0.2";
0108:
0109: private final static Hints LENIENT_HINT = new Hints(
0110: Hints.LENIENT_DATUM_SHIFT, Boolean.TRUE);
0111:
0112: private final static FilteredSubsample filteredSubsampleFactory = new FilteredSubsample();
0113:
0114: private static final SubsampleAverage subsampleAvgFactory = new SubsampleAverage();
0115:
0116: private static final Scale scaleFactory = new Scale();
0117:
0118: private DefaultOption inputLocationOpt;
0119:
0120: private DefaultOption outputLocationOpt;
0121:
0122: private DefaultOption tileDimOpt;
0123:
0124: private DefaultOption scaleAlgorithmOpt;
0125:
0126: private DefaultOption tileCacheSizeOpt;
0127:
0128: private DefaultOption outFormatOpt;
0129:
0130: private double tileW;
0131:
0132: private double tileH;
0133:
0134: private File inputLocation;
0135:
0136: private File outputLocation;
0137:
0138: private String scaleAlgorithm;
0139:
0140: private String outputFormat;
0141:
0142: private int tileCacheSize;
0143:
0144: private DefaultOption scaleFactorOpt;
0145:
0146: private int scaleFactor;
0147:
0148: public PyramidLayerBuilder() {
0149: // /////////////////////////////////////////////////////////////////////
0150: // Options for the command line
0151: // /////////////////////////////////////////////////////////////////////
0152: helpOpt = optionBuilder.withShortName("h").withShortName("?")
0153: .withLongName("helpOpt").withDescription(
0154: "print this message.").withRequired(false)
0155: .create();
0156:
0157: versionOpt = optionBuilder.withShortName("v").withLongName(
0158: "versionOpt").withDescription("print the versionOpt.")
0159: .withRequired(false).create();
0160:
0161: inputLocationOpt = optionBuilder.withShortName("s")
0162: .withLongName("source_directory").withArgument(
0163: arguments.withName("source").withMinimum(1)
0164: .withMaximum(1).withValidator(
0165: new Validator() {
0166:
0167: public void validate(
0168: List args)
0169: throws InvalidArgumentException {
0170: final int size = args
0171: .size();
0172: if (size > 1)
0173: throw new InvalidArgumentException(
0174: "Only one location can be chosen");
0175: final File source = new File(
0176: (String) args
0177: .get(0));
0178: if (!source.isFile()
0179: || !source
0180: .exists())
0181: throw new InvalidArgumentException(
0182: new StringBuffer(
0183: "The provided source is invalid! ")
0184:
0185: .toString());
0186: }
0187:
0188: }).create()).withDescription(
0189: "path where files are located").withRequired(
0190: true).create();
0191:
0192: outputLocationOpt = optionBuilder
0193: .withShortName("d")
0194: .withLongName("dest_directory")
0195: .withArgument(
0196: arguments.withName("destination")
0197: .withMinimum(0).withMaximum(1).create())
0198: .withDescription(
0199: "output directory, if none is provided, the \"tiled\" directory will be used")
0200: .withRequired(false).create();
0201:
0202: tileDimOpt = optionBuilder.withShortName("t").withLongName(
0203: "tiled_dimension").withArgument(
0204: arguments.withName("t").withMinimum(1).withMaximum(1)
0205: .create()).withDescription(
0206: "tile dimensions as a couple width,height in pixels")
0207: .withRequired(true).create();
0208:
0209: scaleFactorOpt = optionBuilder.withShortName("f").withLongName(
0210: "scale_factor").withArgument(
0211: arguments.withName("f").withMinimum(1).withMaximum(1)
0212: .withValidator(new Validator() {
0213:
0214: public void validate(List args)
0215: throws InvalidArgumentException {
0216: final int size = args.size();
0217: if (size > 1)
0218: throw new InvalidArgumentException(
0219: "Only one scaling algorithm at a time can be chosen");
0220: int factor = Integer
0221: .parseInt((String) args.get(0));
0222: if (factor <= 0)
0223: throw new InvalidArgumentException(
0224: new StringBuffer(
0225: "The provided scale factor is negative! ")
0226:
0227: .toString());
0228: if (factor == 1) {
0229: LOGGER
0230: .warning("The scale factor is 1!");
0231: System.exit(0);
0232: }
0233: }
0234:
0235: }).create()).withDescription(
0236: "integer scale factor").withRequired(true).create();
0237:
0238: scaleAlgorithmOpt = optionBuilder
0239: .withShortName("a")
0240: .withLongName("scaling_algorithm")
0241: .withArgument(
0242: arguments.withName("a").withMinimum(0)
0243: .withMaximum(1).withValidator(
0244: new Validator() {
0245:
0246: public void validate(
0247: List args)
0248: throws InvalidArgumentException {
0249: final int size = args
0250: .size();
0251: if (size > 1)
0252: throw new InvalidArgumentException(
0253: "Only one scaling algorithm at a time can be chosen");
0254: if (!scalingAlgorithms
0255: .contains(args
0256: .get(0)))
0257: throw new InvalidArgumentException(
0258: new StringBuffer(
0259: "The output format ")
0260: .append(
0261: args
0262: .get(0))
0263: .append(
0264: " is not permitted")
0265: .toString());
0266:
0267: }
0268: }).create())
0269: .withDescription(
0270: "name of the scaling algorithm, eeither one of average (a), filtered (f), bilinear (bil), nearest neigbhor (nn)")
0271: .withRequired(false).create();
0272:
0273: priorityOpt = optionBuilder.withShortName("p").withLongName(
0274: "thread_priority").withArgument(
0275: arguments.withName("thread_priority").withMinimum(0)
0276: .withMaximum(1).create()).withDescription(
0277: "priority for the underlying thread").withRequired(
0278: false).create();
0279:
0280: outFormatOpt = optionBuilder
0281: .withShortName("o")
0282: .withLongName("out_format")
0283: .withArgument(
0284: arguments.withName("o").withMinimum(0)
0285: .withMaximum(1).withDescription(
0286: "output format")
0287: // .withDefault("gtiff")
0288: .withValidator(new Validator() {
0289:
0290: public void validate(List args)
0291: throws InvalidArgumentException {
0292: final int size = args.size();
0293: if (size > 1)
0294: throw new InvalidArgumentException(
0295: "Only one output format at a time can be specified");
0296: if (!outputFormats
0297: .contains(args.get(0)))
0298: throw new InvalidArgumentException(
0299: new StringBuffer(
0300: "The output format ")
0301: .append(
0302: args
0303: .get(0))
0304: .append(
0305: " is not permitted")
0306: .toString());
0307:
0308: }
0309: }).create()).withDescription(
0310: "output format")
0311: .withRequired(false).create();
0312:
0313: tileCacheSizeOpt = optionBuilder.withShortName("c")
0314: .withLongName("cache_size").withArgument(
0315: arguments.withName("c").withMinimum(0)
0316: .withMaximum(1).create())
0317: .withDescription("tile cache sized")
0318: .withRequired(false).create();
0319:
0320: cmdOpts.add(inputLocationOpt);
0321: cmdOpts.add(tileDimOpt);
0322: cmdOpts.add(scaleFactorOpt);
0323: cmdOpts.add(scaleAlgorithmOpt);
0324: cmdOpts.add(outFormatOpt);
0325: cmdOpts.add(priorityOpt);
0326: cmdOpts.add(tileCacheSizeOpt);
0327: cmdOpts.add(versionOpt);
0328: cmdOpts.add(helpOpt);
0329:
0330: optionsGroup = new GroupImpl(cmdOpts, "Options",
0331: "All the options", 0, 9);
0332:
0333: // /////////////////////////////////////////////////////////////////////
0334: //
0335: // Help Formatter
0336: //
0337: // /////////////////////////////////////////////////////////////////////
0338: final HelpFormatter cmdHlp = new HelpFormatter("| ", " ",
0339: " |", 75);
0340: cmdHlp.setShellCommand("PyramidLayerBuilder");
0341: cmdHlp.setHeader("Help");
0342: cmdHlp
0343: .setFooter(new StringBuffer(
0344: "PyramidLayerBuilder - GeoSolutions S.a.s (C) 2006 - v ")
0345: .append(PyramidLayerBuilder.versionNumber)
0346: .toString());
0347: cmdHlp
0348: .setDivider("|-------------------------------------------------------------------------|");
0349:
0350: cmdParser.setGroup(optionsGroup);
0351: cmdParser.setHelpOption(helpOpt);
0352: cmdParser.setHelpFormatter(cmdHlp);
0353: }
0354:
0355: /**
0356: *
0357: * @param args
0358: * @throws IOException
0359: * @throws IllegalArgumentException
0360: * @throws InterruptedException
0361: */
0362: public static void main(String[] args)
0363: throws IllegalArgumentException, IOException,
0364: InterruptedException {
0365:
0366: final PyramidLayerBuilder pyramidBuilder = new PyramidLayerBuilder();
0367: pyramidBuilder.addProcessingEventListener(pyramidBuilder);
0368: if (pyramidBuilder.parseArgs(args)) {
0369: final Thread t = new Thread(pyramidBuilder,
0370: "PyramidBuilder");
0371: t.setPriority(pyramidBuilder.priority);
0372: t.start();
0373: try {
0374: t.join();
0375: } catch (InterruptedException e) {
0376: LOGGER.log(Level.SEVERE, e.getLocalizedMessage(), e);
0377: }
0378:
0379: } else
0380: LOGGER.fine("Exiting...");
0381:
0382: }
0383:
0384: private boolean parseArgs(String[] args) {
0385: cmdLine = cmdParser.parseAndHelp(args);
0386: if (cmdLine != null && cmdLine.hasOption(versionOpt)) {
0387: LOGGER.fine(new StringBuffer(
0388: "PyramidBuilder - GeoSolutions S.a.s (C) 2006 - v")
0389: .append(PyramidLayerBuilder.versionNumber)
0390: .toString());
0391: System.exit(1);
0392:
0393: } else if (cmdLine != null) {
0394: // ////////////////////////////////////////////////////////////////
0395: //
0396: // parsing command line parameters and setting up
0397: // Mosaic Index Builder options
0398: //
0399: // ////////////////////////////////////////////////////////////////
0400: inputLocation = new File((String) cmdLine
0401: .getValue(inputLocationOpt));
0402:
0403: // tile dim
0404: final String tileDim = (String) cmdLine
0405: .getValue(tileDimOpt);
0406: final String[] pairs = tileDim.split(",");
0407: tileW = Integer.parseInt(pairs[0]);
0408: tileH = Integer.parseInt(pairs[1]);
0409:
0410: // //
0411: //
0412: // scale factor
0413: //
0414: // //
0415: final String scaleF = (String) cmdLine
0416: .getValue(scaleFactorOpt);
0417: scaleFactor = Integer.parseInt(scaleF);
0418:
0419: // output files' directory
0420: if (cmdLine.hasOption(outputLocationOpt))
0421: outputLocation = new File((String) cmdLine
0422: .getValue(outputLocationOpt));
0423: else
0424: outputLocation = new File(
0425: inputLocation.getParentFile(), String
0426: .valueOf(scaleFactor));
0427:
0428: // //
0429: //
0430: // scaling algorithm
0431: //
0432: // //
0433: scaleAlgorithm = (String) cmdLine
0434: .getValue(scaleAlgorithmOpt);
0435: if (scaleAlgorithm == null)
0436: scaleAlgorithm = "nn";
0437:
0438: // //
0439:
0440: // //
0441: //
0442: // output format
0443: //
0444: // //
0445: outputFormat = (String) cmdLine.getValue(outFormatOpt);
0446:
0447: // //
0448: //
0449: // Thread priority
0450: //
0451: // //
0452: // index name
0453: if (cmdLine.hasOption(priorityOpt))
0454: priority = Integer.parseInt((String) cmdLine
0455: .getValue(priorityOpt));
0456:
0457: // //
0458: //
0459: // Tile cache size
0460: //
0461: // //
0462: // index name
0463: if (cmdLine.hasOption(tileCacheSizeOpt)) {
0464: tileCacheSize = Integer.parseInt((String) cmdLine
0465: .getValue(tileCacheSizeOpt));
0466: JAI.getDefaultInstance().getTileCache()
0467: .setMemoryCapacity(tileCacheSize * 1024 * 1024);
0468: }
0469: return true;
0470:
0471: }
0472: return false;
0473:
0474: }
0475:
0476: public void run() {
0477:
0478: // /////////////////////////////////////////////////////////////////////
0479: //
0480: //
0481: // PARSING INPUT PARAMETERS
0482: //
0483: //
0484: // /////////////////////////////////////////////////////////////////////
0485: StringBuffer message = new StringBuffer(
0486: "Requested scale factor is ").append(scaleFactor);
0487: if (LOGGER.isLoggable(Level.FINE))
0488: LOGGER.fine(message.toString());
0489: fireEvent(message.toString(), 0);
0490:
0491: // /////////////////////////////////////////////////////////////////////
0492: //
0493: //
0494: // Opening the base mosaic
0495: //
0496: //
0497: // /////////////////////////////////////////////////////////////////////
0498: // mosaic reader
0499: message = new StringBuffer(
0500: "Acquiring a mosaic reader to mosaic ")
0501: .append(inputLocation);
0502: if (LOGGER.isLoggable(Level.FINE))
0503: LOGGER.fine(message.toString());
0504: fireEvent(message.toString(), 0);
0505:
0506: ImageMosaicReader inReader = null;
0507: try {
0508: inReader = new ImageMosaicReader(inputLocation, new Hints(
0509: Hints.IGNORE_COVERAGE_OVERVIEW, Boolean.TRUE));
0510: } catch (IOException e) {
0511: LOGGER.log(Level.SEVERE, e.getLocalizedMessage(), e);
0512: fireException(e);
0513: return;
0514: }
0515:
0516: // /////////////////////////////////////////////////////////////////////
0517: //
0518: //
0519: // Preparing all the params
0520: //
0521: //
0522: // /////////////////////////////////////////////////////////////////////
0523: // output files' directory
0524: if (!outputLocation.exists())
0525: outputLocation.mkdir();
0526:
0527: // getting envelope and other information about dimension
0528: final GeneralEnvelope envelope = inReader.getOriginalEnvelope();
0529:
0530: message = new StringBuffer("Original envelope is ")
0531: .append(envelope.toString());
0532: if (LOGGER.isLoggable(Level.FINE))
0533: LOGGER.fine(message.toString());
0534: fireEvent(message.toString(), 0);
0535:
0536: final GeneralGridRange range = inReader.getOriginalGridRange();
0537:
0538: message = new StringBuffer("Original range is ").append(range
0539: .toString());
0540: if (LOGGER.isLoggable(Level.FINE))
0541: LOGGER.fine(message.toString());
0542: fireEvent(message.toString(), 0);
0543:
0544: // new number fo rows and columns
0545: final double newWidth = (range.getLength(0) * 1.0)
0546: / scaleFactor;
0547: final double newHeight = (range.getLength(1) * 1.0)
0548: / scaleFactor;
0549: if (tileW > newWidth)
0550: tileW = newWidth;
0551: if (tileH > newHeight)
0552: tileH = newHeight;
0553:
0554: message = new StringBuffer("New dimension is (W,H)==(").append(
0555: newWidth).append(",").append(newHeight).append(")");
0556: if (LOGGER.isLoggable(Level.FINE))
0557: LOGGER.fine(message.toString());
0558: fireEvent(message.toString(), 0);
0559:
0560: int newCols = (int) Math.floor(newWidth / tileW);
0561: int newRows = (int) Math.floor(newHeight / tileH);
0562: final boolean hasRemainingColum = (newWidth % tileW) != 0;
0563: final boolean hasRemainingRow = (newHeight % tileH) != 0;
0564: final double remainingWidth = hasRemainingColum ? newWidth
0565: - tileW * (newCols) : tileW;
0566: final double remainingHeight = hasRemainingRow ? newHeight
0567: - tileH * (newRows) : tileH;
0568:
0569: message = new StringBuffer(
0570: "New matrix dimension is (cols,rows)==(").append(
0571: newCols).append(",").append(newRows).append(")");
0572: if (LOGGER.isLoggable(Level.FINE))
0573: LOGGER.fine(message.toString());
0574: fireEvent(message.toString(), 0);
0575:
0576: final double minx = envelope.getMinimum(0);
0577: final double miny = envelope.getMinimum(1);
0578: final double maxx = envelope.getMaximum(0);
0579: final double maxy = envelope.getMaximum(1);
0580:
0581: double _maxx = 0.0;
0582: double _maxy = 0.0;
0583: double _minx = 0.0;
0584: double _miny = 0.0;
0585: GridCoverage2D gc = null;
0586: File fileOut;
0587: GeoTiffWriter writerWI;
0588: ParameterValue gg;
0589: GeneralEnvelope cropEnvelope;
0590:
0591: // prescale algortihm
0592: int preScaleSteps = 0;
0593: int tempScale = scaleFactor;
0594: while ((tempScale /= 2) > 0) {
0595: preScaleSteps++;
0596: }
0597: boolean doPrescaleSteps = false;
0598: // we need to be carefufl to NOT exhaust the scale steps with the
0599: // prescaling
0600:
0601: if (Math.pow(2, preScaleSteps) == scaleFactor) {
0602: preScaleSteps--;
0603: }
0604: double finalScale = scaleFactor / Math.pow(2, preScaleSteps);
0605:
0606: // preparing parameters for the subsampling operation
0607: final DefaultProcessor processor = new DefaultProcessor(
0608: LENIENT_HINT);
0609: Interpolation interpolation = null;
0610: ParameterValueGroup subsamplingParams = null;
0611: if (scaleAlgorithm.equalsIgnoreCase("nn")) {
0612: subsamplingParams = processor.getOperation("Scale")
0613: .getParameters();
0614: interpolation = new InterpolationNearest();
0615: doPrescaleSteps = true;
0616: } else if (scaleAlgorithm.equalsIgnoreCase("filt")) {
0617: subsamplingParams = processor.getOperation(
0618: "FilteredSubsample").getParameters();
0619: interpolation = new InterpolationNearest();
0620: doPrescaleSteps = scaleFactor % 2 == 0;
0621: if (!doPrescaleSteps)
0622: finalScale = scaleFactor;
0623: } else if (scaleAlgorithm.equalsIgnoreCase("bil")) {
0624: subsamplingParams = processor.getOperation("Scale")
0625: .getParameters();
0626: interpolation = new InterpolationBilinear();
0627: doPrescaleSteps = true;
0628: } else if (scaleAlgorithm.equalsIgnoreCase("avg")) {
0629: subsamplingParams = processor.getOperation(
0630: "SubsampleAverage").getParameters();
0631: interpolation = new InterpolationNearest();
0632: doPrescaleSteps = scaleFactor % 2 == 0;
0633: if (!doPrescaleSteps)
0634: finalScale = scaleFactor;
0635: } else {
0636: throw new IllegalArgumentException(
0637: "The provided scale algorithm is not availaible");
0638:
0639: }
0640:
0641: // ///////////////////////////////////////////////////////////////////
0642: //
0643: // MAIN LOOP
0644: //
0645: //
0646: // ///////////////////////////////////////////////////////////////////
0647: newRows += hasRemainingRow ? 1 : 0;
0648: newCols += hasRemainingColum ? 1 : 0;
0649: final double totalNumberOfFile = newRows * newCols;
0650:
0651: // getting resolution of each tile
0652: final double tileGeoWidth = envelope.getLength(0) / newCols;
0653: final double tileGeoHeight = envelope.getLength(1) / newRows;
0654:
0655: final int uppers[] = range.getUppers();
0656: final double newRange[] = new double[] { uppers[0] / newCols,
0657: uppers[1] / newRows };
0658:
0659: for (int i = 0; i < newRows; i++)
0660: for (int j = 0; j < newCols; j++) {
0661:
0662: // //
0663: //
0664: // computing the bbox for this tile
0665: //
0666: // //
0667: _maxx = minx + (j + 1) * tileGeoWidth;
0668: _minx = minx + (j) * tileGeoWidth;
0669: _maxy = miny + (i + 1) * tileGeoHeight;
0670: _miny = miny + (i) * tileGeoHeight;
0671: if (_maxx > maxx)
0672: _maxx = maxx;
0673: if (_maxy > maxy)
0674: _maxy = maxy;
0675:
0676: fileOut = new File(outputLocation, new StringBuffer(
0677: "mosaic").append("_").append(
0678: Integer.toString(i * newCols + j)).append(".")
0679: .append("tiff").toString());
0680: if (fileOut.exists())
0681: fileOut.delete();
0682:
0683: message = new StringBuffer(
0684: "Preparing tile (col,row)==(").append(j)
0685: .append(",").append(i).append(") to file ")
0686: .append(fileOut);
0687: if (LOGGER.isLoggable(Level.FINE))
0688: LOGGER.fine(message.toString());
0689: fireEvent(message.toString(), (j + i * newCols)
0690: / totalNumberOfFile);
0691:
0692: // //
0693: //
0694: // building gridgeometry for the read operation
0695: //
0696: // //
0697: gg = (ParameterValue) ImageMosaicFormat.READ_GRIDGEOMETRY2D
0698: .createValue();
0699: cropEnvelope = new GeneralEnvelope(new double[] {
0700: _minx, _miny }, new double[] { _maxx, _maxy });
0701: cropEnvelope.setCoordinateReferenceSystem(inReader
0702: .getCrs());
0703: gg.setValue(new GridGeometry2D(new GeneralGridRange(
0704: new Rectangle(0, 0, 800, 800)), cropEnvelope));
0705:
0706: message = new StringBuffer(
0707: "Reading with grid envelope ")
0708: .append(cropEnvelope.toString());
0709: if (LOGGER.isLoggable(Level.FINE))
0710: LOGGER.fine(message.toString());
0711: fireEvent(message.toString(), (j + i * newCols)
0712: / totalNumberOfFile);
0713:
0714: try {
0715: gc = (GridCoverage2D) inReader
0716: .read(new GeneralParameterValue[] { gg });
0717:
0718: } catch (IOException e) {
0719: LOGGER
0720: .log(Level.SEVERE, e.getLocalizedMessage(),
0721: e);
0722: fireEvent(e.getLocalizedMessage(), 0);
0723: return;
0724: }
0725:
0726: ParameterValueGroup param;
0727:
0728: param = processor.getOperation("CoverageCrop")
0729: .getParameters();
0730: param.parameter("Source").setValue(gc);
0731: param.parameter("Envelope").setValue(cropEnvelope);
0732:
0733: GridCoverage2D cropped = (GridCoverage2D) processor
0734: .doOperation(param);
0735:
0736: // //
0737: // Adjusting the resolution
0738: // //
0739: final GeneralGridRange newGridrange = new GeneralGridRange(
0740: new Rectangle2D.Double(0.0, 0.0, newRange[0],
0741: newRange[1]).getBounds());
0742: final GridGeometry2D scaledGridGeometry = new GridGeometry2D(
0743: newGridrange, cropEnvelope);
0744: param = processor.getOperation("Resample")
0745: .getParameters();
0746: param.parameter("Source").setValue(cropped);
0747: param.parameter("CoordinateReferenceSystem").setValue(
0748: inReader.getCrs());
0749: param.parameter("GridGeometry").setValue(
0750: scaledGridGeometry);
0751: param
0752: .parameter("InterpolationType")
0753: .setValue(
0754: Interpolation
0755: .getInstance(Interpolation.INTERP_NEAREST));
0756:
0757: gc = (GridCoverage2D) processor.doOperation(param);
0758:
0759: // //
0760: //
0761: // rescaling to the needed res
0762: //
0763: // //
0764: // pre scaling
0765: if (doPrescaleSteps && LOGGER.isLoggable(Level.FINE)) {
0766: message = new StringBuffer("Pre scaling...");
0767: if (LOGGER.isLoggable(Level.FINE))
0768: LOGGER.fine(message.toString());
0769: fireEvent(message.toString(), (j + i * newCols)
0770: / totalNumberOfFile);
0771: }
0772:
0773: for (int k = 0; k < preScaleSteps && doPrescaleSteps; k++) {
0774:
0775: param = filteredSubsampleFactory.getParameters();
0776: param.parameter("source").setValue(gc);
0777: param.parameter("scaleX").setValue(new Integer(2));
0778: param.parameter("scaleY").setValue(new Integer(2));
0779: param.parameter("qsFilterArray").setValue(
0780: new float[] { 1 });
0781: param.parameter("Interpolation").setValue(
0782: new InterpolationBilinear());
0783: gc = (GridCoverage2D) filteredSubsampleFactory
0784: .doOperation(param, null);
0785: }
0786:
0787: message = new StringBuffer("Scaling...");
0788: if (LOGGER.isLoggable(Level.FINE))
0789: LOGGER.fine(message.toString());
0790: fireEvent(message.toString(), 0);
0791:
0792: if (scaleAlgorithm.equalsIgnoreCase("nn")) {
0793: param = processor.getOperation("Scale")
0794: .getParameters();
0795: param.parameter("Source").setValue(gc);
0796: param.parameter("xScale").setValue(
0797: new Float(1 / finalScale));
0798: param.parameter("yScale").setValue(
0799: new Float(1 / finalScale));
0800: param.parameter("xTrans").setValue(new Float(0));
0801: param.parameter("yTrans").setValue(new Float(0));
0802: param
0803: .parameter("Interpolation")
0804: .setValue(
0805: Interpolation
0806: .getInstance(Interpolation.INTERP_BILINEAR));
0807: gc = (GridCoverage2D) scaleFactory.doOperation(
0808: param, null);
0809: } else if (scaleAlgorithm.equalsIgnoreCase("filt")) {
0810: // scaling
0811: param = (ParameterValueGroup) subsamplingParams
0812: .clone();
0813: param.parameter("source").setValue(gc);
0814: param.parameter("scaleX").setValue(
0815: new Integer((int) finalScale));
0816: param.parameter("scaleY").setValue(
0817: new Integer((int) finalScale));
0818: param.parameter("qsFilterArray").setValue(
0819: new float[] { 0.5F, 1.0F / 3.0F, 0.0F,
0820: -1.0F / 12.0F });
0821: param.parameter("Interpolation").setValue(
0822: new InterpolationNearest());
0823:
0824: gc = (GridCoverage2D) filteredSubsampleFactory
0825: .doOperation(param, null);
0826: } else if (scaleAlgorithm.equalsIgnoreCase("bil")) {
0827: param = processor.getOperation("Scale")
0828: .getParameters();
0829: param.parameter("Source").setValue(gc);
0830: param.parameter("xScale").setValue(
0831: new Float(1 / finalScale));
0832: param.parameter("yScale").setValue(
0833: new Float(1 / finalScale));
0834: param.parameter("xTrans").setValue(new Float(0));
0835: param.parameter("yTrans").setValue(new Float(0));
0836: param
0837: .parameter("Interpolation")
0838: .setValue(
0839: Interpolation
0840: .getInstance(Interpolation.INTERP_BILINEAR));
0841: gc = (GridCoverage2D) scaleFactory.doOperation(
0842: param, null);
0843: } else if (scaleAlgorithm.equalsIgnoreCase("avg")) {
0844: param = processor.getOperation("SubsampleAverage")
0845: .getParameters();
0846: param.parameter("Source").setValue(gc);
0847: param.parameter("scaleX").setValue(
0848: new Double(1 / finalScale));
0849: param.parameter("scaleY").setValue(
0850: new Double(1 / finalScale));
0851: param.parameter("Interpolation").setValue(
0852: interpolation);
0853: gc = (GridCoverage2D) subsampleAvgFactory
0854: .doOperation(param, null);
0855: } else {
0856: throw new IllegalArgumentException(
0857: "The provided scale algorithm is not availaible");
0858:
0859: }
0860:
0861: // //
0862: //
0863: // Writing out this coveragess
0864: //
0865: // //
0866: message = new StringBuffer("Writing out...");
0867: if (LOGGER.isLoggable(Level.FINE))
0868: LOGGER.fine(message.toString());
0869: fireEvent(message.toString(), (j + i * newCols)
0870: / totalNumberOfFile);
0871:
0872: try {
0873:
0874: writerWI = new GeoTiffWriter(fileOut);
0875: writerWI.write(gc, null);
0876:
0877: } catch (IOException e) {
0878: LOGGER
0879: .log(Level.SEVERE, e.getLocalizedMessage(),
0880: e);
0881: fireEvent(e.getLocalizedMessage(), 0);
0882: return;
0883: }
0884:
0885: }
0886:
0887: message = new StringBuffer("Done...");
0888: if (LOGGER.isLoggable(Level.FINE))
0889: LOGGER.fine(message.toString());
0890: fireEvent(message.toString(), 100);
0891:
0892: }
0893:
0894: public void getNotification(ProcessingEvent event) {
0895: LOGGER.info(new StringBuffer("Progress is at ").append(
0896: event.getPercentage()).append("\n").append(
0897: "attached message is: ").append(event.getMessage())
0898: .toString());
0899: }
0900:
0901: public void exceptionOccurred(ExceptionEvent event) {
0902: LOGGER.log(Level.SEVERE, "An error occurred during processing",
0903: event.getException());
0904: }
0905:
0906: public final void setInputLocation(File inputLocation) {
0907: this .inputLocation = inputLocation;
0908: }
0909:
0910: public final void setOutputLocation(File outputLocation) {
0911: this .outputLocation = outputLocation;
0912: }
0913:
0914: /**
0915: * @return the outputFormat
0916: */
0917: public final String getOutputFormat() {
0918: return outputFormat;
0919: }
0920:
0921: /**
0922: * @param outputFormat
0923: * the outputFormat to set
0924: */
0925: public final void setOutputFormat(String outputFormat) {
0926: this .outputFormat = outputFormat;
0927: }
0928:
0929: /**
0930: * @return the scaleAlgorithm
0931: */
0932: public final String getScaleAlgorithm() {
0933: return scaleAlgorithm;
0934: }
0935:
0936: /**
0937: * @param scaleAlgorithm
0938: * the scaleAlgorithm to set
0939: */
0940: public final void setScaleAlgorithm(String scaleAlgorithm) {
0941: this .scaleAlgorithm = scaleAlgorithm;
0942: }
0943:
0944: /**
0945: * @return the scaleFactor
0946: */
0947: public final int getScaleFactor() {
0948: return scaleFactor;
0949: }
0950:
0951: /**
0952: * @param scaleFactor
0953: * the scaleFactor to set
0954: */
0955: public final void setScaleFactor(int scaleFactor) {
0956: this .scaleFactor = scaleFactor;
0957: }
0958:
0959: public File getInputLocation() {
0960: return inputLocation;
0961: }
0962:
0963: public File getOutputLocation() {
0964: return outputLocation;
0965: }
0966:
0967: /**
0968: * @return the tileCacheSize
0969: */
0970: public final int getTileCacheSize() {
0971: return tileCacheSize;
0972: }
0973:
0974: /**
0975: * @param tileCacheSize
0976: * the tileCacheSize to set
0977: */
0978: public final void setTileCacheSize(int tileCacheSize) {
0979: this .tileCacheSize = tileCacheSize;
0980: }
0981:
0982: /**
0983: * @return the tileH
0984: */
0985: public final double getTileH() {
0986: return tileH;
0987: }
0988:
0989: /**
0990: * @param tileH
0991: * the tileH to set
0992: */
0993: public final void setTileH(int tileH) {
0994: this .tileH = tileH;
0995: }
0996:
0997: /**
0998: * @return the tileW
0999: */
1000: public final double getTileW() {
1001: return tileW;
1002: }
1003:
1004: /**
1005: * @param tileW
1006: * the tileW to set
1007: */
1008: public final void setTileW(int tileW) {
1009: this.tileW = tileW;
1010: }
1011:
1012: }
|