Index: /trunk/src/org/openstreetmap/josm/gui/layer/AbstractTileSourceLayer.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/layer/AbstractTileSourceLayer.java	(revision 11845)
+++ /trunk/src/org/openstreetmap/josm/gui/layer/AbstractTileSourceLayer.java	(revision 11846)
@@ -27,5 +27,4 @@
 import java.net.MalformedURLException;
 import java.net.URL;
-import java.text.MessageFormat;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
@@ -64,7 +63,5 @@
 import org.openstreetmap.gui.jmapviewer.MemoryTileCache;
 import org.openstreetmap.gui.jmapviewer.OsmTileLoader;
-import org.openstreetmap.gui.jmapviewer.Projected;
 import org.openstreetmap.gui.jmapviewer.Tile;
-import org.openstreetmap.gui.jmapviewer.TileAnchor;
 import org.openstreetmap.gui.jmapviewer.TileRange;
 import org.openstreetmap.gui.jmapviewer.TileXY;
@@ -99,4 +96,5 @@
 import org.openstreetmap.josm.gui.dialogs.LayerListPopup;
 import org.openstreetmap.josm.gui.layer.imagery.ImageryFilterSettings.FilterChangeListener;
+import org.openstreetmap.josm.gui.layer.imagery.TileAnchor;
 import org.openstreetmap.josm.gui.layer.imagery.TileCoordinateConverter;
 import org.openstreetmap.josm.gui.layer.imagery.TilePosition;
@@ -1087,12 +1085,8 @@
             boolean miss = false;
             BufferedImage img = null;
-            TileAnchor anchorImage = null;
             if (!tile.isLoaded() || tile.hasError()) {
                 miss = true;
             } else {
-                synchronized (tile) {
-                    img = getLoadedTileImage(tile);
-                    anchorImage = tile.getAnchor();
-                }
+                img = getLoadedTileImage(tile);
                 if (img == null) {
                     miss = true;
@@ -1103,4 +1097,7 @@
                 return;
             }
+            TileAnchor anchorImage = new TileAnchor(
+                    new Point.Double(0, 0),
+                    new Point.Double(img.getWidth(), img.getHeight()));
             img = applyImageProcessors((BufferedImage) img);
             TileAnchor anchorScreen = coordinateConverter.getScreenAnchorForTile(tile);
@@ -1131,12 +1128,8 @@
             boolean miss = false;
             BufferedImage img = null;
-            TileAnchor anchorImage = null;
             if (!tile.isLoaded() || tile.hasError()) {
                 miss = true;
             } else {
-               synchronized (tile) {
-                    img = getLoadedTileImage(tile);
-                    anchorImage = tile.getAnchor();
-                }
+                img = getLoadedTileImage(tile);
                 if (img == null) {
                     miss = true;
@@ -1147,4 +1140,7 @@
                 continue;
             }
+            TileAnchor anchorImage = new TileAnchor(
+                    new Point.Double(0, 0),
+                    new Point.Double(img.getWidth(), img.getHeight()));
 
             // applying all filters to this layer
Index: /trunk/src/org/openstreetmap/josm/gui/layer/imagery/TileAnchor.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/layer/imagery/TileAnchor.java	(revision 11846)
+++ /trunk/src/org/openstreetmap/josm/gui/layer/imagery/TileAnchor.java	(revision 11846)
@@ -0,0 +1,77 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.layer.imagery;
+
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Point2D;
+import org.openstreetmap.gui.jmapviewer.interfaces.IProjected;
+
+/**
+ * Class that fixes the position of a tile in a given coordinate space.
+ *
+ * This is done by storing the coordinates of the tile origin and the opposite
+ * tile corner.
+ * <p>
+ * It may represent a reprojected tile, i.e. the tile is rotated / deformed in an
+ * arbitrary way. In general, the tile origin cannot be expected to be the
+ * upper left corner of the rectangle that is spanned by the 2 points.
+ * <p>
+ * The coordinate space may be
+ * <ul>
+ *   <li>pixel coordinates of the image file</li>
+ *   <li>projected coordinates (east / north)</li>
+ *   <li>screen pixel coordinates</li>
+ * </ul>
+ */
+public class TileAnchor {
+
+    protected final Point2D tileOrigin, nextTileOrigin;
+
+    /**
+     * Create a new tile anchor.
+     * @param tileOrigin position of the tile origin
+     * @param nextTileOrigin position of the opposite tile corner, i.e. the
+     * origin of the tile with index (x+1,y+1), when current tile has index (x,y)
+     */
+    public TileAnchor(Point2D tileOrigin, Point2D nextTileOrigin) {
+        this.tileOrigin = tileOrigin;
+        this.nextTileOrigin = nextTileOrigin;
+    }
+
+    public TileAnchor(IProjected tileOrigin, IProjected nextTileOrigin) {
+        this.tileOrigin = new Point2D.Double(tileOrigin.getEast(), tileOrigin.getNorth());
+        this.nextTileOrigin = new Point2D.Double(nextTileOrigin.getEast(), nextTileOrigin.getNorth());
+    }
+
+    public Point2D getTileOrigin() {
+        return tileOrigin;
+    }
+
+    public Point2D getNextTileOrigin() {
+        return nextTileOrigin;
+    }
+
+    @Override
+    public String toString() {
+        return "TileAnchor{" + tileOrigin.toString() + "; " + nextTileOrigin.toString() + "}";
+    }
+
+    /**
+     * Create a transformation that converts points from this coordinate space
+     * to another coordinate space.
+     * @param other tile anchor of the tile in the target coordinate space
+     * @return affine transformation from this coordinate space to the target
+     * coordinate space
+     */
+    public AffineTransform convert(TileAnchor other) {
+        Point2D src1 = this.getTileOrigin();
+        Point2D src2 = this.getNextTileOrigin();
+        Point2D dest1 = other.getTileOrigin();
+        Point2D dest2 = other.getNextTileOrigin();
+
+        double scaleX = (dest2.getX() - dest1.getX()) / (src2.getX() - src1.getX());
+        double scaleY = (dest2.getY() - dest1.getY()) / (src2.getY() - src1.getY());
+        double offsetX0 = dest1.getX() - scaleX * src1.getX();
+        double offsetY0 = dest1.getY() - scaleY * src1.getY();
+        return new AffineTransform(scaleX, 0, 0, scaleY, offsetX0, offsetY0);
+    }
+}
Index: /trunk/src/org/openstreetmap/josm/gui/layer/imagery/TileCoordinateConverter.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/layer/imagery/TileCoordinateConverter.java	(revision 11845)
+++ /trunk/src/org/openstreetmap/josm/gui/layer/imagery/TileCoordinateConverter.java	(revision 11846)
@@ -8,5 +8,4 @@
 
 import org.openstreetmap.gui.jmapviewer.Tile;
-import org.openstreetmap.gui.jmapviewer.TileAnchor;
 import org.openstreetmap.gui.jmapviewer.TileXY;
 import org.openstreetmap.gui.jmapviewer.interfaces.ICoordinate;
