/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2001-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.referencing.operation.transform; import java.awt.geom.Point2D; import java.awt.image.RasterFormatException; import javax.media.jai.Warp; import org.opengis.referencing.operation.MathTransform2D; import org.opengis.referencing.operation.TransformException; import org.geotools.resources.i18n.Errors; import org.geotools.resources.i18n.ErrorKeys; /** * Wraps an arbitrary {@link MathTransform2D} into an image warp operation. * This warp operation is used by {@link org.geotools.coverage.processing.operation.Resample} * when no standard warp operation has been found applicable. * * @since 2.1 * @source $URL$ * @version $Id$ * @author Martin Desruisseaux (IRD) */ final class WarpAdapter extends Warp { /** * For cross-version compatibility. */ private static final long serialVersionUID = -8679060848877065181L; /** * The coverage name. Used for formatting error message. */ private final CharSequence name; /** * The <strong>inverse</strong> of the transform to apply for projecting an image. * This transform maps destination pixels to source pixels. */ private final MathTransform2D inverse; /** * Constructs a new {@code WarpAdapter} using the given transform. * * @param name The coverage name. Used for formatting error message. * @param inverse The <strong>inverse</strong> of the transformation to apply for projecting * an image. This inverse transform maps destination pixels to source pixels. */ public WarpAdapter(final CharSequence name, final MathTransform2D inverse) { this.name = name; this.inverse = inverse; } /** * Returns the transform from image's destination pixels to source pixels. */ public MathTransform2D getTransform() { return inverse; } /** * Computes the source pixel positions for a given rectangular * destination region, subsampled with an integral period. */ public float[] warpSparseRect(final int xmin, final int ymin, final int width, final int height, final int periodX, final int periodY, float[] destRect) { if (periodX < 1) throw new IllegalArgumentException(String.valueOf(periodX)); if (periodY < 1) throw new IllegalArgumentException(String.valueOf(periodY)); final int xmax = xmin + width; final int ymax = ymin + height; final int count = ((width+(periodX-1))/periodX) * ((height+(periodY-1))/periodY); if (destRect == null) { destRect = new float[2*count]; } int index = 0; for (int y=ymin; y<ymax; y+=periodY) { for (int x=xmin; x<xmax; x+=periodX) { destRect[index++] = x + 0.5f; destRect[index++] = y + 0.5f; } } try { inverse.transform(destRect, 0, destRect, 0, count); } catch (TransformException exception) { // At least one transformation failed. In Geotools MapProjection // implementation, unprojected coordinates are set to (NaN,NaN). RasterFormatException e = new RasterFormatException(Errors.format( ErrorKeys.CANT_REPROJECT_$1, name)); e.initCause(exception); throw e; } while (--index >= 0) { destRect[index] -= 0.5f; } return destRect; } /** * Computes the source point corresponding to the supplied point. * * @param destPt The position in destination image coordinates * to map to source image coordinates. */ @Override public Point2D mapDestPoint(final Point2D destPt) { Point2D result = new Point2D.Double(destPt.getX()+0.5, destPt.getY()+0.5); try { result = inverse.transform(result, result); } catch (TransformException exception) { throw new IllegalArgumentException(Errors.format( ErrorKeys.BAD_PARAMETER_$2, "destPt", destPt), exception); } result.setLocation(result.getX()-0.5, result.getY()-0.5); return result; } /** * Computes the destination point corresponding to the supplied point. * * @param sourcePt The position in source image coordinates * to map to destination image coordinates. */ @Override public Point2D mapSourcePoint(final Point2D sourcePt) { Point2D result = new Point2D.Double(sourcePt.getX()+0.5, sourcePt.getY()+0.5); try { result = inverse.inverse().transform(result, result); } catch (TransformException exception) { throw new IllegalArgumentException(Errors.format( ErrorKeys.BAD_PARAMETER_$2, "sourcePt", sourcePt), exception); } result.setLocation(result.getX()-0.5, result.getY()-0.5); return result; } }