/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2002-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.data; import java.awt.geom.AffineTransform; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.util.logging.Level; import java.util.logging.Logger; import org.geotools.referencing.operation.matrix.AffineTransform2D; import org.geotools.referencing.operation.transform.IdentityTransform; import org.geotools.referencing.operation.transform.ProjectiveTransform; import org.geotools.resources.i18n.ErrorKeys; import org.geotools.resources.i18n.Errors; import org.opengis.referencing.operation.MathTransform; /** * This class is responsible for creating a world file from a * {@link MathTransform} or {@link AffineTransform}. * * <p> * The content of a world file describes an affine transformation which was used * by the ESRI software to map from the rater world to the spatial world (what we usually call a * grid to world transform). * * <p> * Specifically a world file should be as follows: * * scalex * shearx * sheary * scaley * upperleftx * upperlefty * * * which translates into the following affine transformation. * * | : | * | scalex shearx : translatex| * | : | * | sheary scaley : transaltey| * |----------------------------| * | 0 0 : 1 | * | : | * * <p> * Note that a world file usually takes as reference the centre of the pixel. * * @author Simone Giannecchini, GeoSolutions * * * * @source $URL$ */ public class WorldFileWriter { /** * Default buffer size we wil luse to write out. */ public static final int DEFAULT_BUFFER_SIZE = 4096; private static AffineTransform checkTransform(AffineTransform transform) { if(transform==null) throw new IllegalArgumentException(Errors.format(ErrorKeys.NULL_ARGUMENT_$1,"transform")); return transform; } private static MathTransform checkMathTransform(MathTransform transform) { if(transform==null) throw new IllegalArgumentException(Errors.format(ErrorKeys.NULL_ARGUMENT_$1,"transform")); return transform; } /** * Logger for this class. */ private final static Logger LOGGER = org.geotools.util.logging.Logging .getLogger("org.geotools.data.data"); /** * Constructor. * * @param outLocation where to create the world file. * @param transform the transformation that we want to write out. * @throws IOException in case something bad happens. */ public WorldFileWriter(final File outLocation, final AffineTransform transform) throws IOException { this(outLocation, ProjectiveTransform.create(checkTransform(transform)),DEFAULT_BUFFER_SIZE); } /** * Constructor. * * @param outLocation where to create the world file. * @param transform the transformation that we want to write out. * @param buffSize size of the buffer to use. * @throws IOException in case something bad happens. */ public WorldFileWriter(final File outLocation, final AffineTransform transform, final int buffSize) throws IOException { this(outLocation, ProjectiveTransform.create(checkTransform(transform)),buffSize); } /** * Constructor. * * @param outLocation where to create the world file. * @param transform the transformation that we want to write out. * @throws IOException in case something bad happens. */ public WorldFileWriter(final OutputStream outLocation, final AffineTransform transform) throws IOException { this(outLocation, ProjectiveTransform.create(checkTransform(transform))); } /** * Constructor. * * @param outLocation where to create the world file. * @param transform the transformation that we want to write out. * @param buffSize size of the buffer to use. * @throws IOException in case something bad happens. */ public WorldFileWriter(final OutputStream outLocation, final AffineTransform transform, final int buffSize) throws IOException { this(outLocation, ProjectiveTransform.create(checkTransform(transform)),buffSize); } /** * Constructor. * * <p> * Note that the {@link MathTransform} must be a 2D affine transform. * * @param outLocation where to create the world file. * @param transform the transformation that we want to write out. * @throws IOException in case something bad happens. */ public WorldFileWriter(final OutputStream outLocation, final MathTransform transform) throws IOException { this(outLocation, transform, DEFAULT_BUFFER_SIZE); } /** * Constructor. * * <p> * Note that the {@link MathTransform} must be a 2D affine transform. * * @param outLocation where to create the world file. * @param transform the transformation that we want to write out. * @param buffSize size of the buffer to use. * @throws IOException in case something bad happens. */ public WorldFileWriter(final OutputStream outLocation, final MathTransform transform, final int buffSize) throws IOException { if(outLocation==null) throw new NullPointerException(Errors.format(ErrorKeys.NULL_ARGUMENT_$1,"outLocation")); if(transform.getSourceDimensions()!=2||transform.getTargetDimensions()!=2) throw new IllegalArgumentException(Errors.format(ErrorKeys.MISMATCHED_DIMENSION_$3,"transform",transform.getSourceDimensions(),2)); if(buffSize<=0) throw new IllegalArgumentException(Errors.format(ErrorKeys.ILLEGAL_ARGUMENT_$2,"buffSize",buffSize)); write( new BufferedWriter( new OutputStreamWriter(outLocation), buffSize), transform); } /** * Write the provided transformation to the provided output. * * @param writer to use for writing the transformation. * @param transform is the transformation that we want to write out. * @throws IOException in case something bad happens. */ private void write(BufferedWriter writer, MathTransform transform){ try { if ((transform instanceof IdentityTransform)) { writer.write("1"); writer.newLine(); writer.write("0"); writer.newLine(); writer.write("0"); writer.newLine(); writer.write("1"); writer.newLine(); writer.write("0"); writer.newLine(); writer.write("0"); close(writer); return; } if ((transform instanceof AffineTransform2D)) { final AffineTransform2D affine = (AffineTransform2D) transform; writer.write(Double.toString(affine.getScaleX())); writer.newLine(); writer.write(Double.toString(affine.getShearX())); writer.newLine(); writer.write(Double.toString(affine.getShearY())); writer.newLine(); writer.write(Double.toString(affine.getScaleY())); writer.newLine(); writer.write(Double.toString(affine.getTranslateX())); writer.newLine(); writer.write(Double.toString(affine.getTranslateY())); close(writer); return; } assert false:transform; } catch (IOException e) { if(LOGGER.isLoggable(Level.SEVERE)) LOGGER.log(Level.SEVERE,e.getLocalizedMessage(),e); } finally { close(writer); } } private void close(BufferedWriter writer) { try{ if(writer!=null) writer.close(); }catch (Throwable t) { if(LOGGER.isLoggable(Level.FINE)) LOGGER.log(Level.FINE,t.getLocalizedMessage(),t); } } /** * * Constructor. * * <p> * Note that the {@link MathTransform} must be a 2D affine transform. * * @param outLocation where to create the world file. * @param transform the transformation that we want to write out. * @param buffSize size of the buffer to use. * @throws IOException in case something bad happens. */ public WorldFileWriter(final File outLocation, final MathTransform transform, int buffSize) throws IOException { if (outLocation == null) throw new NullPointerException(Errors.format(ErrorKeys.NULL_ARGUMENT_$1,"outLocation")); checkMathTransform(transform); if(transform.getSourceDimensions()!=2||transform.getTargetDimensions()!=2) throw new IllegalArgumentException(Errors.format(ErrorKeys.MISMATCHED_DIMENSION_$3,"transform",transform.getSourceDimensions(),2)); if( !outLocation.canWrite() || !outLocation.isFile() ) throw new IllegalArgumentException(Errors.format(ErrorKeys.FILE_DOES_NOT_EXIST_$1,outLocation)); // create a writer write( new BufferedWriter(new FileWriter( outLocation), buffSize), transform); } /** * * Constructor. * * <p> * Note that the {@link MathTransform} must be a 2D affine transform. * * @param outLocation where to create the world file. * @param transform the transformation that we want to write out. * @throws IOException in case something bad happens. */ public WorldFileWriter(final File outLocation, final MathTransform transform) throws IOException { this(outLocation, transform, DEFAULT_BUFFER_SIZE); } }