001    //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_testing/src/org/deegree/tools/raster/Text2Tiff.java $
002    /*----------------------------------------------------------------------------
003     This file is part of deegree, http://deegree.org/
004     Copyright (C) 2001-2009 by:
005       Department of Geography, University of Bonn
006     and
007       lat/lon GmbH
008    
009     This library is free software; you can redistribute it and/or modify it under
010     the terms of the GNU Lesser General Public License as published by the Free
011     Software Foundation; either version 2.1 of the License, or (at your option)
012     any later version.
013     This library is distributed in the hope that it will be useful, but WITHOUT
014     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
015     FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
016     details.
017     You should have received a copy of the GNU Lesser General Public License
018     along with this library; if not, write to the Free Software Foundation, Inc.,
019     59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020    
021     Contact information:
022    
023     lat/lon GmbH
024     Aennchenstr. 19, 53177 Bonn
025     Germany
026     http://lat-lon.de/
027    
028     Department of Geography, University of Bonn
029     Prof. Dr. Klaus Greve
030     Postfach 1147, 53001 Bonn
031     Germany
032     http://www.geographie.uni-bonn.de/deegree/
033    
034     e-mail: info@deegree.org
035    ----------------------------------------------------------------------------*/
036    package org.deegree.tools.raster;
037    
038    import java.awt.color.ColorSpace;
039    import java.awt.image.BufferedImage;
040    import java.awt.image.ColorModel;
041    import java.awt.image.ComponentColorModel;
042    import java.awt.image.DataBuffer;
043    import java.awt.image.Raster;
044    import java.awt.image.WritableRaster;
045    import java.io.BufferedReader;
046    import java.io.File;
047    import java.io.FileOutputStream;
048    import java.io.FileReader;
049    import java.io.IOException;
050    import java.io.PrintStream;
051    import java.util.ArrayList;
052    import java.util.Arrays;
053    import java.util.Hashtable;
054    import java.util.List;
055    import java.util.StringTokenizer;
056    
057    import org.deegree.datatypes.values.Interval;
058    import org.deegree.datatypes.values.TypedLiteral;
059    import org.deegree.datatypes.values.Values;
060    import org.deegree.framework.util.ConvenienceFileFilter;
061    import org.deegree.framework.util.ImageUtils;
062    import org.deegree.io.quadtree.IndexException;
063    import org.deegree.io.quadtree.MemPointQuadtree;
064    import org.deegree.io.quadtree.Quadtree;
065    import org.deegree.model.coverage.grid.WorldFile;
066    import org.deegree.model.spatialschema.Envelope;
067    import org.deegree.model.spatialschema.GeometryFactory;
068    import org.deegree.model.spatialschema.Point;
069    import org.deegree.processing.raster.interpolation.DataTuple;
070    import org.deegree.processing.raster.interpolation.InterpolationException;
071    import org.deegree.processing.raster.interpolation.InverseDistanceToPower;
072    
073    /**
074     * This class converts geodata and special values from a simple text file format to a .tiff file
075     * format. The values are written as 32 bit float values. The <code>main</code> method should be
076     * used to utilise this class as a command line tool.
077     *
078     *
079     * @author <a href="mailto:schmitz@lat-lon.de">Andreas Schmitz</a>
080     * @author last edited by: $Author: mschneider $
081     *
082     * @version $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18. Jun 2009) $
083     */
084    public class Text2Tiff {
085    
086        // parameters
087        private int columnNumber = 0;
088    
089        private double resolution = 0;
090    
091        private String columnName = null;
092    
093        private List<String> inputFilenames = new ArrayList<String>();
094    
095        private String outputFilename = null;
096    
097        private boolean readHeader = false;
098    
099        private boolean oracle = false;
100    
101        private Envelope boundingBox = null;
102    
103        private boolean interpolate = false;
104    
105        private boolean use32Bits = false;
106    
107        // data
108        private BufferedReader in;
109    
110        private Raster raster;
111    
112        private Quadtree quadtree;
113    
114        private BufferedImage image;
115    
116        private int imageWidth;
117    
118        private int imageHeight;
119    
120        private DataBuffer buffer;
121    
122        private float offset = 0;
123    
124        // interpolating options
125        private double interpolatePower = 2;
126    
127        private int interpolateMinData = 5;
128    
129        private int interpolateMaxData = 20;
130    
131        private double interpolateNoValue = 0;
132    
133        private double interpolateRadiusX = 2;
134    
135        private double interpolateRadiusY = 2;
136    
137        private double interpolateRadiusIncreaseX = 0;
138    
139        private double interpolateRadiusIncreaseY = 0;
140    
141        private Values ignoreValues = null;
142    
143        /**
144         * The only constructor, called usually by the main method with command line arguments.
145         *
146         * @param args
147         */
148        public Text2Tiff( String[] args ) {
149            if ( args.length < 3 ) {
150                printUsage( "Not enough arguments." );
151            }
152    
153            parseArgs( args );
154    
155            // check for consistency
156            if ( ( columnName != null ) && !readHeader ) {
157                printUsage( "If a column name is given, I have to read the header!" );
158            }
159    
160            if ( inputFilenames.size() == 0 ) {
161                printUsage( "No input filename given." );
162            }
163    
164            if ( outputFilename == null ) {
165                printUsage( "No output filename given." );
166            }
167    
168            if ( columnName == null && columnNumber == 0 ) {
169                printUsage( "No column specified." );
170            }
171    
172            if ( !readHeader ) {
173                --columnNumber;
174            }
175        }
176    
177        private void parseArgs( String[] args ) {
178            List<Interval> intervals = new ArrayList<Interval>();
179    
180            // parse options
181            try {
182                for ( int i = 0; i < ( args.length - 1 ); ++i ) {
183                    if ( args[i].equals( "--image-type" ) ) {
184                        use32Bits = args[i + 1].equals( "32" );
185                        ++i;
186                    } else if ( args[i].equals( "--offset" ) ) {
187                        offset = Float.parseFloat( args[i + 1] );
188                        ++i;
189                    } else if ( args[i].equals( "--image-width" ) ) {
190                        imageWidth = Integer.parseInt( args[i + 1] );
191                        ++i;
192                    } else if ( args[i].equals( "--image-height" ) ) {
193                        imageHeight = Integer.parseInt( args[i + 1] );
194                        ++i;
195                    } else if ( args[i].equals( "-c" ) || args[i].equals( "--column-number" ) ) {
196                        columnNumber = Integer.parseInt( args[i + 1] );
197                        ++i;
198                    } else if ( args[i].equals( "-h" ) || args[i].equals( "--no-read-header" ) ) {
199                        readHeader = false;
200                    } else if ( args[i].equals( "-o" ) || args[i].equals( "--oracle" ) ) {
201                        oracle = true;
202                    } else if ( args[i].equals( "+h" ) || args[i].equals( "--read-header" ) ) {
203                        readHeader = true;
204                    } else if ( args[i].equals( "-cn" ) || args[i].equals( "--column-name" ) ) {
205                        columnName = args[i + 1];
206                        ++i;
207                    } else if ( args[i].equals( "-r" ) || args[i].equals( "--resolution" ) ) {
208                        resolution = Double.parseDouble( args[i + 1] );
209                        ++i;
210                    } else if ( args[i].equals( "-i" ) || args[i].equals( "--interpolate" ) ) {
211                        interpolate = true;
212                    } else if ( args[i].equals( "--interpolate-power" ) ) {
213                        interpolatePower = Double.parseDouble( args[i + 1] );
214                        ++i;
215                    } else if ( args[i].equals( "--interpolate-min-data" ) ) {
216                        interpolateMinData = Integer.parseInt( args[i + 1] );
217                        ++i;
218                    } else if ( args[i].equals( "--interpolate-max-data" ) ) {
219                        interpolateMaxData = Integer.parseInt( args[i + 1] );
220                        ++i;
221                    } else if ( args[i].equals( "--interpolate-no-value" ) ) {
222                        interpolateNoValue = Double.parseDouble( args[i + 1] );
223                        ++i;
224                    } else if ( args[i].equals( "--interpolate-radius-x" ) ) {
225                        interpolateRadiusX = Double.parseDouble( args[i + 1] );
226                        ++i;
227                    } else if ( args[i].equals( "--interpolate-radius-y" ) ) {
228                        interpolateRadiusY = Double.parseDouble( args[i + 1] );
229                        ++i;
230                    } else if ( args[i].equals( "--interpolate-radius-increase-x" ) ) {
231                        interpolateRadiusIncreaseX = Double.parseDouble( args[i + 1] );
232                        ++i;
233                    } else if ( args[i].equals( "--interpolate-radius-increase-y" ) ) {
234                        interpolateRadiusIncreaseY = Double.parseDouble( args[i + 1] );
235                        ++i;
236                    } else if ( args[i].equals( "--interpolate-ignore-range" ) ) {
237                        TypedLiteral min = new TypedLiteral( args[i + 1], null );
238                        TypedLiteral max = new TypedLiteral( args[i + 2], null );
239                        Interval interval = new Interval( min, max, null, null, null );
240                        intervals.add( interval );
241                        i += 2;
242                    } else if ( args[i].equals( "--help" ) ) {
243                        printUsage( null );
244                    } else if ( args[i].equals( "-help" ) ) {
245                        printUsage( null );
246                    } else {
247                        File file = new File( args[i] );
248                        if ( file.isDirectory() ) {
249                            File[] files = file.listFiles( new ConvenienceFileFilter( false, "XYZ,TXT" ) );
250                            for ( int j = 0; j < files.length; j++ ) {
251                                inputFilenames.add( files[j].getAbsolutePath() );
252                            }
253                        } else {
254                            inputFilenames.add( args[i] );
255                        }
256                    }
257    
258                }
259            } catch ( NumberFormatException nfe ) {
260                printUsage( "Illegal argument, number expected." );
261            }
262    
263            // get file names
264            outputFilename = args[args.length - 1];
265            if ( intervals.size() != 0 ) {
266                ignoreValues = new Values( intervals.toArray( new Interval[intervals.size()] ), null, null );
267            }
268        }
269    
270        // reads the first line
271        private void readHeader()
272                                throws IOException {
273            if ( !readHeader ) {
274                return;
275            }
276    
277            String s = in.readLine();
278    
279            columnNumber = 0;
280    
281            // get the right index for the column
282            if ( columnName != null ) {
283                StringTokenizer tok = new StringTokenizer( s );
284                while ( tok.hasMoreTokens() ) {
285                    String t = tok.nextToken();
286                    if ( t.equals( columnName ) ) {
287                        break;
288                    }
289                    ++columnNumber;
290                }
291            } else {
292                --columnNumber;
293            }
294        }
295    
296        // reads all data into the array lists
297        private ArrayList<DataTuple> readValues( String filename )
298                                throws IOException, NumberFormatException {
299    
300            readHeader();
301    
302            File file = new File( filename );
303            int size = (int) ( file.length() / 30 );
304    
305            ArrayList<DataTuple> values = new ArrayList<DataTuple>( size );
306            BufferedReader in = new BufferedReader( new FileReader( filename ) );
307            int counter = 0;
308            while ( in.ready() ) {
309                StringTokenizer tokenizer = new StringTokenizer( in.readLine() );
310                int idx = 0;
311                double x = 0;
312                double y = 0;
313                while ( tokenizer.hasMoreTokens() ) {
314                    if ( idx == 0 ) {
315                        x = Double.parseDouble( tokenizer.nextToken() );
316                    } else if ( idx == 1 ) {
317                        y = Double.parseDouble( tokenizer.nextToken() );
318                    } else if ( idx == columnNumber ) {
319                        values.add( new DataTuple( x, y, Double.parseDouble( tokenizer.nextToken() ) ) );
320                        break;
321                    } else
322                        tokenizer.nextToken();
323                    ++idx;
324                }
325                if ( ++counter % 10000 == 0 ) {
326                    System.out.print( "Read " + counter / 1000 + " thousand lines.\r" );
327                }
328            }
329            System.out.println();
330            in.close();
331    
332            return values;
333        }
334    
335        // calculate resolution and bbox
336        private void preprocessFiles()
337                                throws IOException {
338            double minx = Double.MAX_VALUE;
339            double miny = Double.MAX_VALUE;
340            double maxx = Double.MIN_VALUE;
341            double maxy = Double.MIN_VALUE;
342            boolean calcResolution = ( resolution == 0 );
343            if ( imageWidth != 0 && imageHeight != 0 ) {
344                calcResolution = false;
345            }
346    
347            if ( calcResolution ) {
348                resolution = Double.MAX_VALUE;
349            }
350    
351            for ( String filename : inputFilenames ) {
352                System.out.println( "Reading file " + filename );
353                ArrayList<DataTuple> values = readValues( filename );
354    
355                // Collections.sort( values );
356    
357                double[] ys = null;
358                DataTuple prev = null;
359                double cur;
360                if ( calcResolution ) {
361                    ys = new double[values.size()];
362                    prev = values.get( 0 );
363                    cur = 0;
364                }
365    
366                for ( int i = 0; i < values.size(); ++i ) {
367                    DataTuple tuple = values.get( i );
368    
369                    if ( maxx < tuple.x ) {
370                        maxx = tuple.x;
371                    }
372                    if ( maxy < tuple.y ) {
373                        maxy = tuple.y;
374                    }
375                    if ( minx > tuple.x ) {
376                        minx = tuple.x;
377                    }
378                    if ( miny > tuple.y ) {
379                        miny = tuple.y;
380                    }
381    
382                    if ( calcResolution ) {
383                        cur = Math.abs( tuple.x - prev.x );
384                        if ( ( cur != 0 ) && ( resolution > cur ) ) {
385                            resolution = cur;
386                        }
387                        ys[i] = tuple.y;
388                        prev = tuple;
389                    }
390                }
391    
392                if ( calcResolution ) {
393                    Arrays.sort( ys );
394    
395                    for ( int i = 0; i < ys.length - 1; ++i ) {
396                        cur = Math.abs( ys[i] - ys[i + 1] );
397                        if ( cur != 0 && cur < resolution ) {
398                            resolution = cur;
399                        }
400                    }
401                }
402            }
403    
404            System.out.println( "Covered area:" );
405            System.out.println( minx + " - " + maxx );
406            System.out.println( miny + " - " + maxy );
407    
408            boundingBox = GeometryFactory.createEnvelope( minx, miny, maxx, maxy, null );
409    
410            if ( !calcResolution && resolution == 0 ) {
411                resolution = Math.abs( ( maxy - miny ) / ( imageHeight ) );
412                double h = Math.abs( ( maxx - minx ) / ( imageWidth ) );
413                if ( h < resolution ) {
414                    resolution = h;
415                }
416            }
417            if ( imageWidth == 0 && imageHeight == 0 ) {
418                imageWidth = (int) ( boundingBox.getWidth() / resolution ) + 1;
419                imageHeight = (int) ( boundingBox.getHeight() / resolution ) + 1;
420            }
421    
422            System.gc();
423    
424            System.out.println( "Resolution: " + resolution );
425    
426        }
427    
428        // creates the buffered image with the right size
429        private void createImage() {
430    
431            ColorModel ccm;
432    
433            if ( use32Bits ) {
434                image = new BufferedImage( imageWidth, imageHeight, BufferedImage.TYPE_INT_ARGB );
435            } else {
436                ccm = new ComponentColorModel( ColorSpace.getInstance( ColorSpace.CS_GRAY ), null, false, false,
437                                               BufferedImage.OPAQUE, DataBuffer.TYPE_USHORT );
438                WritableRaster wr = ccm.createCompatibleWritableRaster( imageWidth, imageHeight );
439    
440                image = new BufferedImage( ccm, wr, false, new Hashtable<Object, Object>() );
441            }
442    
443            raster = image.getData();
444    
445            buffer = raster.getDataBuffer();
446    
447        }
448    
449        // calculates the index of the desired position (in regard to a DataBuffer of a Raster)
450        private int calculatePosition( double x, double y ) {
451    
452            double tmp = ( x - boundingBox.getMin().getX() ) / resolution;
453    
454            double ypos = imageHeight - ( ( y - boundingBox.getMin().getY() ) / resolution ) - 1;
455            return (int) Math.round( tmp + ( ypos * imageWidth ) );
456    
457        }
458    
459        // inserts all values into the image
460        private void insertValue( double x, double y, double val ) {
461    
462            int pos = Math.abs( calculatePosition( x, y ) );
463            if ( use32Bits ) {
464                buffer.setElem( pos, Float.floatToIntBits( ( (float) val ) + offset ) );
465            } else {
466                buffer.setElem( pos, (int) Math.round( ( ( val + offset ) * 10 ) ) );
467            }
468    
469        }
470    
471        // creates the worldfile, depends on minimum values (call after createImage)
472        private void writeWorldfile()
473                                throws IOException {
474            if ( oracle ) {
475                PrintStream out = new PrintStream( new FileOutputStream( outputFilename + ".tfw" ) );
476                out.println( resolution );
477                out.println( "0.0" );
478                out.println( "0.0" );
479                out.println( -resolution );
480                if ( oracle ) {
481                    out.println( boundingBox.getMin().getX() - resolution / 2 );
482                } else {
483                    out.println( boundingBox.getMin().getX() );
484                }
485                if ( oracle ) {
486                    out.println( boundingBox.getMax().getY() + resolution / 2 );
487                } else {
488                    out.println( boundingBox.getMax().getY() );
489                }
490                out.println();
491            } else {
492                WorldFile wf = new WorldFile( resolution, -resolution, 0, 0, boundingBox );
493                WorldFile.writeWorldFile( wf, outputFilename );
494            }
495        }
496    
497        private void buildQuadtree()
498                                throws IOException, IndexException {
499            for ( String filename : inputFilenames ) {
500                readHeader();
501    
502                BufferedReader in = new BufferedReader( new FileReader( filename ) );
503                int counter = 0;
504                while ( in.ready() ) {
505                    StringTokenizer tokenizer = new StringTokenizer( in.readLine() );
506                    int idx = 0;
507                    double x = 0;
508                    double y = 0;
509                    while ( tokenizer.hasMoreTokens() ) {
510                        if ( idx == 0 ) {
511                            x = Double.parseDouble( tokenizer.nextToken() );
512                        } else if ( idx == 1 ) {
513                            y = Double.parseDouble( tokenizer.nextToken() );
514                        } else if ( idx == columnNumber ) {
515                            Point point = GeometryFactory.createPoint( x, y, null );
516                            quadtree.insert( new DataTuple( x, y, Double.parseDouble( tokenizer.nextToken() ) ), point );
517                            break;
518                        } else
519                            tokenizer.nextToken();
520                        ++idx;
521                    }
522                    if ( ++counter % 10000 == 0 ) {
523                        System.out.print( "Read " + counter / 1000 + " thousand lines.\r" );
524                    }
525                }
526                in.close();
527                System.out.println();
528    
529            }
530    
531        }
532    
533        /**
534         * This method executes all steps that are required to transform the text file into a tiff file.
535         *
536         */
537        private void transform() {
538            try {
539                preprocessFiles();
540    
541                quadtree = new MemPointQuadtree( boundingBox );
542    
543                buildQuadtree();
544    
545                createImage();
546    
547                interpolate();
548    
549                image.setData( raster );
550    
551                System.out.println( "Writing output files..." );
552                ImageUtils.saveImage( image, new File( outputFilename + ".tif" ), 1 );
553                writeWorldfile();
554                System.out.println( "Done." );
555                // testOutput();
556            } catch ( IOException ioe ) {
557                System.out.println( "Could not read or write a file, reason:" );
558                ioe.printStackTrace();
559                System.exit( 0 );
560            } catch ( NumberFormatException nfe ) {
561                System.out.println( "A number could not be parsed correctly. Reason: " );
562                nfe.printStackTrace();
563                System.exit( 0 );
564            } catch ( InterpolationException e ) {
565                System.out.println( "Could not interpolate missing values. Reason: " );
566                e.printStackTrace();
567                System.exit( 0 );
568            } catch ( IndexException e ) {
569                System.out.println( "Could not build Quadtree. Reason: " );
570                e.printStackTrace();
571                System.exit( 0 );
572            }
573        }
574    
575        private void interpolate()
576                                throws InterpolationException {
577    
578            InverseDistanceToPower interpolator = new InverseDistanceToPower( quadtree, ignoreValues, interpolateRadiusX,
579                                                                              interpolateRadiusY, 0, interpolateMinData,
580                                                                              interpolateMaxData, interpolateNoValue,
581                                                                              interpolateRadiusIncreaseX,
582                                                                              interpolateRadiusIncreaseY, interpolatePower );
583    
584            double minx = boundingBox.getMin().getX();
585            double miny = boundingBox.getMin().getY();
586    
587            int count = imageWidth * imageHeight;
588    
589            int counter = 0;
590    
591            int interpolatedCounter = 0;
592    
593            for ( int xipos = 0; xipos < imageWidth; ++xipos ) {
594                for ( int yipos = 0; yipos < imageHeight; ++yipos ) {
595                    double xpos = minx + resolution * xipos;
596                    double ypos = miny + resolution * yipos;
597    
598                    Envelope env = GeometryFactory.createEnvelope( xpos - 0.01, ypos - 0.01, xpos + 0.01, ypos + 0.01, null );
599    
600                    try {
601                        List<?> list = quadtree.query( env );
602                        double val = 0;
603                        if ( list.size() == 0 ) {
604                            if ( interpolate ) {
605                                val = interpolator.calcInterpolatedValue( xpos, ypos, interpolateRadiusX,
606                                                                          interpolateRadiusY );
607                                ++interpolatedCounter;
608                            }
609                        } else {
610                            val = ( (DataTuple) list.get( 0 ) ).value;
611                        }
612    
613                        insertValue( xpos, ypos, val );
614    
615                    } catch ( IndexException e ) {
616                        throw new InterpolationException( "Could not interpolate.", e );
617                    }
618    
619                    if ( ++counter % 1000 == 0 ) {
620                        System.out.print( counter + "/" + count + "\r" );
621                    }
622                }
623            }
624    
625            System.out.println( counter + '/' + count + ", interpolated " + interpolatedCounter + " values" );
626        }
627    
628        /**
629         * Prints out an error message and general usage information of the tool.
630         *
631         * @param error
632         *            an error message
633         */
634        public void printUsage( String error ) {
635            if ( error != null ) {
636                System.out.println( "Error: " + error );
637                System.out.println();
638            }
639            System.out.println( "java Text2Tiff <options> <inputfile[s]> <outputfile>" );
640            System.out.println( "Options:" );
641            System.out.println();
642            System.out.println( "    --help, -help:" );
643            System.out.println( "              print this message" );
644            System.out.println( "    --read-header, +h:" );
645            System.out.println( "    --no-read-header, -h:" );
646            System.out.println( "              Do/Do not read a header line in the input file. If enabled," );
647            System.out.println( "              one can specify column names instead of column numbers as" );
648            System.out.println( "              seen below. Default is no." );
649            System.out.println( "    --column-number n, -c n:" );
650            System.out.println( "              Use the column number n as input column. Must be specified" );
651            System.out.println( "              if column name below is not given. Counting starts with one," );
652            System.out.println( "              so '3' means actually the third column, not the fourth." );
653            System.out.println( "    --column-name n, -cn n:" );
654            System.out.println( "              Use the column named n as input column. Must be specified" );
655            System.out.println( "              if no column number is given." );
656            System.out.println( "    --oracle, -o:" );
657            System.out.println( "              Write the worldfile as Oracle expects it, using the outer" );
658            System.out.println( "              bounds of the bbox and not the point centers. Default is no." );
659            System.out.println( "    --image-type n:" );
660            System.out.println( "              n can be either 16 or 32. If n is 16, an image of type USHORT" );
661            System.out.println( "              will be created, and the values will be stored as shorts," );
662            System.out.println( "              multiplied by 10. If n is 32, the float values will be" );
663            System.out.println( "              stored in an image of type integer, as can be seen in" );
664            System.out.println( "              Java's Float.floatToIntBits() method. Default is 16." );
665            System.out.println( "    --image-width n:" );
666            System.out.println( "    --image-height n:" );
667            System.out.println( "              If set, an image of this size will be created. If not set" );
668            System.out.println( "              (default), the size will be determined by the resolution" );
669            System.out.println( "              either determined automatically or set by hand." );
670            System.out.println( "    --offset n:" );
671            System.out.println( "              use this as offset value for the result tiff. If result tiff" );
672            System.out.println( "              shall be a 16Bit tiff first offset will be added to value" );
673            System.out.println( "              before it will be multiplyed by 10" );
674            System.out.println( "    --resolution n, -r n:" );
675            System.out.println( "              Set geo resolution to n. If omitted, the resolution will be" );
676            System.out.println( "              set to the smallest value found in the input data." );
677            System.out.println( "    --interpolate, i:" );
678            System.out.println( "              Interpolate missing values. By default, no interpolation" );
679            System.out.println( "              will be performed." );
680            System.out.println( "    --interpolate-power n:" );
681            System.out.println( "              Interpolate using n as power. Default is " + interpolatePower + "." );
682            System.out.println( "    --interpolate-min-data n:" );
683            System.out.println( "              Interpolate only in the presence of n values within the search" );
684            System.out.println( "              radius. Default is " + interpolateMinData + "." );
685            System.out.println( "    --interpolate-max-data n:" );
686            System.out.println( "              Interpolate using a maximum of n values from within the search" );
687            System.out.println( "              radius. If more values are found, the n nearest will be used." );
688            System.out.println( "              Default is " + interpolateMaxData + "." );
689            System.out.println( "    --interpolate-no-value n:" );
690            System.out.println( "              The value to be used if insufficient data is in the search" );
691            System.out.println( "              radius. See also the radius-increase options below. Default" );
692            System.out.println( "              is " + interpolateNoValue + "." );
693            System.out.println( "    --interpolate-radius-x n:" );
694            System.out.println( "              Interpolate using a search radius of n in the x direction." );
695            System.out.println( "              Default is " + interpolateRadiusX + "." );
696            System.out.println( "    --interpolate-radius-y n:" );
697            System.out.println( "              Interpolate using a search radius of n in the y direction." );
698            System.out.println( "              Default is " + interpolateRadiusY + "." );
699            System.out.println( "    --interpolate-radius-increase-x n:" );
700            System.out.println( "              Automatically increase the x search radius by n if less than" );
701            System.out.println( "              --i-min-data values are found. If specified and not 0, the" );
702            System.out.println( "              value --i-no-value will be ignored. Default is 0." );
703            System.out.println( "    --interpolate-radius-increase-y n:" );
704            System.out.println( "              Automatically increase the y search radius by n if less than" );
705            System.out.println( "              --i-min-data values are found. If specified and not 0, the" );
706            System.out.println( "              value --i-no-value will be ignored. Default is 0." );
707            System.out.println( "    --interpolate-ignore-range min max:" );
708            System.out.println( "              Adds a new range of values to be ignored while interpolating." );
709            System.out.println();
710            System.out.println( ".tif/.tfw will be appended to the <outputfile> parameter." );
711            System.out.println();
712    
713            if ( error == null ) {
714                System.exit( 0 );
715            } else {
716                System.exit( 1 );
717            }
718        }
719    
720        /**
721         * This method is used from the command line.
722         *
723         * @param args
724         *            the command line arguments.
725         */
726        public static void main( String[] args ) {
727            new Text2Tiff( args ).transform();
728        }
729    
730    }