/*
* $Id: TFW.java,v 1.1 2007-02-27 12:45:29 eugen Exp $
*
* Copyright (C) 2002 by Brockmann Consult (info@brockmann-consult.de)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation. This program is distributed in the hope it will
* be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package com.bc.util.geom;
import java.awt.geom.AffineTransform;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.io.StreamTokenizer;
import java.text.ParseException;
/**
* <p>TIFF World File (TFW) format is supported by ArcView, ArcInfo, MapInfo, and many other programs--such as SMS. TIFF
* World files are normal TIFF files with an accompanying .twf metadata file. Despite the fact that TWF files are
* relatively common, the definition of the .twf file has remained obscure.
* <p/>
* <p>The TFW file contains information about the origin (insertion point) of the image and individual cell size. There
* is no information on image dimensions (number of rows or columns), units, projection or datum. This additional
* information must be obtained from the supplied supplementary information, image description or image supplier, in
* order to create an accompanying .IF file to correctly georeference the image. Typically, a MapInfo or ESRI image file
* will be stored in a projection such as NAD27 and California State Plane Zone 6.
* <p/>
* <p>A TFW file normally contains the following information:
* <p/>
* <p>Line Number Sample Value Meaning <br>Line 1 +6.00 Cell size in the X direction <br>Line 2 -0.00 Rotation in the X
* direction <br>Line 3 -0.00 Rotation in the Y direction <br>Line 4 -6.00 Cell size in the Y direction <br>Line 5
* 1709053.00 Easting value of insertion point X <br>Line 6 807714.00 Northing value of insertion point Y
* <p/>
* <p>Note that sign of the cell size in Y (line 4) defines if the image insertion point is the upper left or lower left
* corner. A positive means the "Y" values are increasing upwards and therefore, the registration must be starting at
* the bottom or lower left corner. A negative sign means that the insertion point is the upper left. The insertion
* point coordinates relate to the map corner of the image in its defined projection itself.
* <p/>
* <p>A sample TWF file is shown below:
* <p/>
* <p>2.5 pixel x size (meters) <br>-0.0 rotation factor <br>-0.0 rotation factor <br>-2.5 pixel y size (meters)
* <br>75000 image min x (meters) (NW <br>-200000 image max y (meters) Corner) <br>Normally an image will be supplied
* with a .tif and .twf file pair (e.g., RIVER.TIF and RIVER.TFW).
* <p/>
* <p>Note that SMS will perform a coordinate transformation of the image. Select Edit | Coordinate Conversions. Note
* that if only the TIFF image is loaded, then you will not be able to "find" the image. So, it is best that you draw a
* box around the image to see it.
* <p/>
* <p>Also, both the DEM and TFW files will need to be in the same coordinate system (or individually converted) for
* them to match up in SMS.
*/
public class TFW {
private AffineTransform _transform;
public TFW(double scaleX,
double shearY,
double shearX,
double scaleY,
double translateX,
double translateY) {
this(new double[]{scaleX, shearY, shearX, scaleY, translateX, translateY});
}
public TFW(double[] flatmatrix) {
_transform = new AffineTransform(flatmatrix);
}
public double getScaleX() {
return _transform.getScaleX();
}
public double getScaleY() {
return _transform.getScaleY();
}
public double getShearX() {
return _transform.getShearX();
}
public double getShearY() {
return _transform.getShearY();
}
public double getTranslateX() {
return _transform.getTranslateX();
}
public double getTranslateY() {
return _transform.getTranslateY();
}
public static TFW load(final File file) throws ParseException,
IOException {
final FileReader reader = new FileReader(file);
try {
return load(reader);
} finally {
reader.close();
}
}
public static TFW load(Reader reader) throws IOException,
ParseException {
final StreamTokenizer st = new StreamTokenizer(reader);
final double[] flatmatrix = new double[6];
for (int i = 0; i < flatmatrix.length; i++) {
st.nextToken();
if (st.ttype == StreamTokenizer.TT_NUMBER) {
flatmatrix[i] = st.nval;
} else {
throw new ParseException("number expected", st.lineno());
}
}
st.nextToken();
if (st.ttype != StreamTokenizer.TT_EOF) {
throw new ParseException("no more tokens expected", st.lineno());
}
return new TFW(flatmatrix);
}
}