Index: /applications/editors/josm/plugins/piclayer/build.xml
===================================================================
--- /applications/editors/josm/plugins/piclayer/build.xml	(revision 27119)
+++ /applications/editors/josm/plugins/piclayer/build.xml	(revision 27120)
@@ -22,5 +22,5 @@
 -->
 <project name="PicLayer" default="dist" basedir=".">
-    <property name="commit.message" value="applied #J5852 (patch by Petschge) - new shear option"/>
+    <property name="commit.message" value="PicLayer rewritten - lots changed"/>
     <property name="plugin.main.version" value="4549"/>
     <!--
Index: /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/ActionVisibilityChangeMenu.java
===================================================================
--- /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/ActionVisibilityChangeMenu.java	(revision 27120)
+++ /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/ActionVisibilityChangeMenu.java	(revision 27120)
@@ -0,0 +1,49 @@
+package org.openstreetmap.josm.plugins.piclayer;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.event.ActionEvent;
+
+import javax.swing.AbstractAction;
+import javax.swing.JCheckBoxMenuItem;
+import javax.swing.JMenu;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.gui.IconToggleButton;
+
+enum PicActions {MOVE_PICTURE, MOVE_POINT, TRANSFORM_POINT, SCALEX, SCALEY, SCALEXY, SHEAR, ROTATE}
+
+@SuppressWarnings("serial")
+public class ActionVisibilityChangeMenu extends JMenu {
+	public ActionVisibilityChangeMenu() {
+		super(tr("Change visibility of controls"));
+
+		add(new SwitchVisibilityMenuItem("Move Picture", "piclayer.actionvisibility.move", PicLayerPlugin.movePictureButton, true));
+		add(new SwitchVisibilityMenuItem("Move Point", "piclayer.actionvisibility.movepoint", PicLayerPlugin.movePointButton, true));
+		add(new SwitchVisibilityMenuItem("Transform Point", "piclayer.actionvisibility.transformpoint", PicLayerPlugin.transformPointButton, true));
+		add(new SwitchVisibilityMenuItem("Rotate", "piclayer.actionvisibility.rotate", PicLayerPlugin.rotatePictureButton, false));
+		add(new SwitchVisibilityMenuItem("Scale X", "piclayer.actionvisibility.scalex", PicLayerPlugin.scalexPictureButton, false));
+		add(new SwitchVisibilityMenuItem("Scale Y", "piclayer.actionvisibility.scaley", PicLayerPlugin.scaleyPictureButton, false));
+		add(new SwitchVisibilityMenuItem("Scale", "piclayer.actionvisibility.scale", PicLayerPlugin.scalexyPictureButton, false));
+		add(new SwitchVisibilityMenuItem("Shear", "piclayer.actionvisibility.shear", PicLayerPlugin.shearPictureButton, false));
+	}
+}
+
+@SuppressWarnings("serial")
+class SwitchVisibilityMenuItem extends JCheckBoxMenuItem {
+	public SwitchVisibilityMenuItem(String name, final String key, final IconToggleButton button, final boolean def) {
+		super();
+		setSelected(Main.pref.getBoolean(key, def));
+		button.setVisible(isSelected());
+		setAction(new AbstractAction() {
+			@Override
+			public void actionPerformed(ActionEvent e) {
+				boolean val = !Main.pref.getBoolean(key, def);
+				Main.pref.put(key, val);
+				SwitchVisibilityMenuItem.this.setSelected(val);
+				button.setVisible(val);
+			}
+		});
+		setText(name);
+	}
+}
Index: plications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/CalibrationFileFilter.java
===================================================================
--- /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/CalibrationFileFilter.java	(revision 27119)
+++ 	(revision )
@@ -1,50 +1,0 @@
-/***************************************************************************
- *   Copyright (C) 2009 by Tomasz Stelmach                                 *
- *   http://www.stelmach-online.net/                                       *
- *                                                                         *
- *   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; either version 2 of the License, or     *
- *   (at your option) any later version.                                   *
- *                                                                         *
- *   This program 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 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 org.openstreetmap.josm.plugins.piclayer;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.io.File;
-
-import javax.swing.filechooser.FileFilter;
-
-/**
- * Filter for the file dialog. Allows only calibration files.
- */
-public class CalibrationFileFilter extends FileFilter {
-
-    // Extension used by calibration files
-    public static final String EXTENSION = ".cal";
-
-    @Override
-    public boolean accept(File f) {
-        String ext3 = ( f.getName().length() > 4 ) ?  f.getName().substring( f.getName().length() - 4 ).toLowerCase() : "";
-
-        // TODO: check what is supported by Java :)
-        return ( f.isDirectory()
-            ||  ext3.equals( EXTENSION )
-            );
-    }
-
-    @Override
-    public String getDescription() {
-        return tr("Calibration Files")+ " (*" + EXTENSION + ")";
-    }
-}
Index: plications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/LoadPictureCalibrationAction.java
===================================================================
--- /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/LoadPictureCalibrationAction.java	(revision 27119)
+++ 	(revision )
@@ -1,84 +1,0 @@
-/***************************************************************************
- *   Copyright (C) 2009 by Tomasz Stelmach                                 *
- *   http://www.stelmach-online.net/                                       *
- *                                                                         *
- *   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; either version 2 of the License, or     *
- *   (at your option) any later version.                                   *
- *                                                                         *
- *   This program 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 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 org.openstreetmap.josm.plugins.piclayer;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.awt.event.ActionEvent;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.Properties;
-
-import javax.swing.JFileChooser;
-import javax.swing.JOptionPane;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.actions.JosmAction;
-
-/**
- * Action to load the calibration file.
- * 
- */
-public class LoadPictureCalibrationAction extends JosmAction {
-
-    // Owner layer of the action
-    PicLayerAbstract m_owner = null;
-    
-    // Persistent FileChooser instance to remember last directory
-    JFileChooser m_filechooser = null;
-
-    /**
-     * Constructor
-     */
-    public LoadPictureCalibrationAction( PicLayerAbstract owner ) {
-        super(tr("Load Picture Calibration..."), null, tr("Loads calibration data from a file"), null, false);
-        // Remember the owner...
-        m_owner = owner;
-    }
-
-    /**
-     * Action handler
-     */
-    public void actionPerformed(ActionEvent arg0) {
-        // Save dialog
-        JFileChooser fc = new JFileChooser();
-        fc.setAcceptAllFileFilterUsed( false );
-        fc.setFileFilter( new CalibrationFileFilter() );
-        fc.setSelectedFile( new File(m_owner.getPicLayerName() + CalibrationFileFilter.EXTENSION));
-        int result = fc.showOpenDialog(Main.parent );
-
-        if ( result == JFileChooser.APPROVE_OPTION ) {
-                    
-            // Load 
-            try {
-                m_owner.loadCalibration(new FileInputStream(fc.getSelectedFile()));
-            } catch (Exception e) {
-                // Error
-                e.printStackTrace();
-                JOptionPane.showMessageDialog(Main.parent , tr("Loading file failed: {0}", e.getMessage()));
-            }
-        }
-    }
-    
-}
Index: plications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/MovePictureAction.java
===================================================================
--- /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/MovePictureAction.java	(revision 27119)
+++ 	(revision )
@@ -1,106 +1,0 @@
-/***************************************************************************
- *   Copyright (C) 2009 by Tomasz Stelmach                                 *
- *   http://www.stelmach-online.net/                                       *
- *                                                                         *
- *   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; either version 2 of the License, or     *
- *   (at your option) any later version.                                   *
- *                                                                         *
- *   This program 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 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 org.openstreetmap.josm.plugins.piclayer;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.awt.event.MouseEvent;
-import java.awt.event.MouseListener;
-import java.awt.event.MouseMotionListener;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.actions.mapmode.MapMode;
-import org.openstreetmap.josm.gui.MapFrame;
-import org.openstreetmap.josm.tools.ImageProvider;
-import org.openstreetmap.josm.data.coor.EastNorth;
-
-//TODO: Move/Rotate/Scale/Shear action classes are similar. Do the redesign!
-
-/**
- * This class handles the input during moving the picture.
- */
-public class MovePictureAction extends MapMode implements MouseListener, MouseMotionListener
-{
-    // Action ongoing?
-    private boolean mb_dragging = false;
-
-    // Last mouse position
-    private EastNorth m_prevEastNorth;
-
-    // The layer we're working on
-    private PicLayerAbstract m_currentLayer = null;
-
-    /**
-     * Constructor
-     */
-    public MovePictureAction(MapFrame frame) {
-        super(tr("PicLayer move"), "move", tr("Drag to move the picture"), frame, ImageProvider.getCursor("crosshair", null));
-    }
-
-    @Override
-    public void enterMode() {
-        super.enterMode();
-        Main.map.mapView.addMouseListener(this);
-        Main.map.mapView.addMouseMotionListener(this);
-    }
-
-    @Override
-    public void exitMode() {
-        super.exitMode();
-        Main.map.mapView.removeMouseListener(this);
-        Main.map.mapView.removeMouseMotionListener(this);
-    }
-
-    @Override
-    public void mousePressed(MouseEvent e) {
-
-        // If everything is OK, we start dragging/moving the picture
-        if ( Main.map.mapView.getActiveLayer() instanceof PicLayerAbstract ) {
-            m_currentLayer = (PicLayerAbstract)Main.map.mapView.getActiveLayer();
-
-            if ( m_currentLayer != null && e.getButton() == MouseEvent.BUTTON1 ) {
-                mb_dragging = true;
-                m_prevEastNorth=Main.map.mapView.getEastNorth(e.getX(),e.getY());
-            }
-        }
-    }
-
-    @Override
-    public void mouseDragged(MouseEvent e) {
-        // Picture moving is ongoing
-        if(mb_dragging) {
-            EastNorth eastNorth = Main.map.mapView.getEastNorth(e.getX(),e.getY());
-            m_currentLayer.movePictureBy(
-                eastNorth.east()-m_prevEastNorth.east(),
-                eastNorth.north()-m_prevEastNorth.north()
-            );
-            m_prevEastNorth = eastNorth;
-            Main.map.mapView.repaint();
-        }
-    }
-
-    @Override
-    public void mouseReleased(MouseEvent e) {
-        // Stop moving
-        mb_dragging = false;
-    }
-
-}
Index: plications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/NewLayerFromClipboardAction.java
===================================================================
--- /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/NewLayerFromClipboardAction.java	(revision 27119)
+++ 	(revision )
@@ -1,64 +1,0 @@
-/***************************************************************************
- *   Copyright (C) 2009 by Tomasz Stelmach                                 *
- *   http://www.stelmach-online.net/                                       *
- *                                                                         *
- *   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; either version 2 of the License, or     *
- *   (at your option) any later version.                                   *
- *                                                                         *
- *   This program 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 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 org.openstreetmap.josm.plugins.piclayer;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.awt.event.ActionEvent;
-import java.io.IOException;
-import javax.swing.JOptionPane;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.actions.JosmAction;
-
-/**
- * Action responsible for creation of a new layer based on
- * the content of the clipboard.
- */
-public class NewLayerFromClipboardAction extends JosmAction {
-
-    /**
-     * Constructor...
-     */
-    public NewLayerFromClipboardAction() {
-        super(tr("New picture layer from clipboard"), null, null, null, false);
-    }
-
-    /**
-     * Action handler
-     */
-    public void actionPerformed(ActionEvent arg0) {
-        // Create layer from clipboard
-        PicLayerFromClipboard layer = new PicLayerFromClipboard();
-        // Add layer only if successfully initialized
-        try {
-            layer.initialize();
-        }
-        catch (IOException e) {
-            // Failed
-            System.out.println( "NewLayerFromClipboardAction::actionPerformed - " + e.getMessage() );
-            JOptionPane.showMessageDialog(null, e.getMessage() );
-            return;
-        }
-        // Add layer
-        Main.main.addLayer( layer );
-    }
-}
Index: plications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/NewLayerFromFileAction.java
===================================================================
--- /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/NewLayerFromFileAction.java	(revision 27119)
+++ 	(revision )
@@ -1,140 +1,0 @@
-/***************************************************************************
- *   Copyright (C) 2009 by Tomasz Stelmach                                 *
- *   http://www.stelmach-online.net/                                       *
- *                                                                         *
- *   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; either version 2 of the License, or     *
- *   (at your option) any later version.                                   *
- *                                                                         *
- *   This program 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 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 org.openstreetmap.josm.plugins.piclayer;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.awt.event.ActionEvent;
-import java.io.File;
-import java.io.IOException;
-
-import javax.imageio.ImageIO;
-import javax.swing.JFileChooser;
-import javax.swing.JOptionPane;
-import javax.swing.filechooser.FileFilter;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.actions.JosmAction;
-import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
-import org.openstreetmap.josm.gui.layer.Layer;
-
-/**
- * Action responsible for creation of new layers based on image files.
- */
-public class NewLayerFromFileAction extends JosmAction {
-
-    String m_lastdirprefname = "piclayer.lastdir";
-
-    /**
-     * Provides filtering of only image files.
-     */
-    private class ImageFileFilter extends FileFilter {
-
-        @Override
-        public boolean accept(File f) {
-            if ( f.isDirectory() )
-                return true;
-
-            int dotIdx = f.getName().lastIndexOf('.');
-            if (dotIdx == -1) return false;
-            String fileExtension = f.getName().substring(dotIdx+1);
-            String[] supportedExtensions = ImageIO.getReaderFormatNames();
-
-            if ("zip".equalsIgnoreCase(fileExtension)) return true;
-            // Unfortunately, getReaderFormatNames does not always return ALL extensions in 
-            // both lower and upper case, so we can not do a search in the array
-            for (String e: supportedExtensions)
-                if ( e.toLowerCase().equals(fileExtension) ) {
-                    return true;
-                }
-                    
-            return false;
-        }
-
-
-        @Override
-        public String getDescription() {
-            return tr("Supported image files");
-        }
-
-    }
-
-    /**
-     * Constructor...
-     */
-    public NewLayerFromFileAction() {
-        super(tr("New picture layer from file..."), null, null, null, false);
-    }
-
-    /**
-     * Action handler
-     */
-    public void actionPerformed(ActionEvent arg0) {
-
-        // Choose a file
-        JFileChooser fc = new JFileChooser(Main.pref.get(m_lastdirprefname));
-        fc.setAcceptAllFileFilterUsed( false );
-        fc.setFileFilter( new ImageFileFilter() );
-        fc.setMultiSelectionEnabled(true); 
-        int result = fc.showOpenDialog( Main.parent );
-
-        // Create a layer?
-        if ( result == JFileChooser.APPROVE_OPTION ) {
-            // The first loaded layer will be placed at the top of any other layer of the same class,
-            // or at the bottom of the stack if there is no such layer yet
-            // The next layers we load will be placed one after the other after this first layer
-            int newLayerPos = Main.map.mapView.getAllLayers().size();
-            for(Layer l : Main.map.mapView.getLayersOfType(PicLayerFromFile.class)) {
-                int pos = Main.map.mapView.getLayerPos(l);
-                if (pos < newLayerPos) newLayerPos = pos;
-            }
-
-            for(File file : fc.getSelectedFiles() ) {
-                // TODO: we need a progress bar here, it can take quite some time
-                
-                // Create layer from file
-                PicLayerFromFile layer = new PicLayerFromFile( file );
-                // Add layer only if successfully initialized
-                try {
-                    layer.initialize();
-                }
-                catch (IOException e) {
-                    // Failed
-                    System.out.println( "NewLayerFromFileAction::actionPerformed - " + e.getMessage() );
-                    JOptionPane.showMessageDialog(null, e.getMessage() );
-                    return;
-                }
-                Main.pref.put(m_lastdirprefname, file.getParent());
-        
-                Main.main.addLayer( layer );
-                Main.map.mapView.moveLayer(layer, newLayerPos++);
-                
-                if ( fc.getSelectedFiles().length == 1 && Main.pref.getInteger("piclayer.zoom-on-load", 1) != 0 ) {
-                    // if we are loading a single picture file, zoom on it, so that the user can see something
-                    BoundingXYVisitor v = new BoundingXYVisitor();
-                    layer.visitBoundingBox(v);
-                    Main.map.mapView.recalculateCenterScale(v);
-                }
-
-            }
-        }
-    }
-}
Index: plications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/PicLayerAbstract.java
===================================================================
--- /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/PicLayerAbstract.java	(revision 27119)
+++ 	(revision )
@@ -1,502 +1,0 @@
-/***************************************************************************
- *   Copyright (C) 2009 by Tomasz Stelmach                                 *
- *   http://www.stelmach-online.net/                                       *
- *                                                                         *
- *   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; either version 2 of the License, or     *
- *   (at your option) any later version.                                   *
- *                                                                         *
- *   This program 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 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 org.openstreetmap.josm.plugins.piclayer;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.awt.Color;
-import java.awt.Component;
-import java.awt.Graphics2D;
-import java.awt.Image;
-import java.awt.Toolkit;
-import java.awt.event.ActionEvent;
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.util.List;
-import java.util.Properties;
-
-import javax.swing.AbstractAction;
-import javax.swing.Action;
-import javax.swing.Icon;
-import javax.swing.ImageIcon;
-import javax.swing.JMenu;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.actions.RenameLayerAction;
-import org.openstreetmap.josm.data.Bounds;
-import org.openstreetmap.josm.data.coor.EastNorth;
-import org.openstreetmap.josm.data.coor.LatLon;
-import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
-import org.openstreetmap.josm.gui.MapView;
-import org.openstreetmap.josm.gui.layer.Layer;
-import org.openstreetmap.josm.tools.Utils;
-
-/**
- * Base class for layers showing images. Actually it does all the showing. The
- * subclasses are supposed only to create images in different ways (load from
- * files, copy from clipboard, hack into a spy satellite and download them,
- * anything...)
- */
-public abstract class PicLayerAbstract extends Layer
-{
-    // Counter - just for naming of layers
-    private static int m_counter = 0;
-    // This is the main image to be displayed
-    private Image m_image = null;
-    // Initial position of the image in the real world
-    private EastNorth m_initial_position;
-    // Position of the image in the real world
-    private EastNorth m_position;
-    // Angle of rotation of the image
-    private double m_angle = 0.0;
-    // Scale of the image
-    private double m_scalex = 1.0;
-    private double m_scaley = 1.0;
-    // Shear of the image
-    private double m_shearx = 0.0;
-    private double m_sheary = 0.0;
-    // The scale that was set on the map during image creation
-    private double m_initial_scale = 1.0;
-    // Layer icon
-    private Icon m_layericon = null;
-
-    // Keys for saving in Properties
-    private final String INITIAL_POS_X = "INITIAL_POS_X";
-    private final String INITIAL_POS_Y = "INITIAL_POS_y";
-    private final String POSITION_X = "POSITION_X";
-    private final String POSITION_Y = "POSITION_Y";
-    private final String ANGLE = "ANGLE";
-    private final String INITIAL_SCALE = "INITIAL_SCALE";
-    private final String SCALEX = "SCALEX";
-    private final String SCALEY = "SCALEY";
-    private final String SHEARX = "SHEARX";
-    private final String SHEARY = "SHEARY";
-
-    /**
-     * Constructor
-     */
-    public PicLayerAbstract() {
-        super("PicLayer #" + m_counter);
-
-        //Increase number
-        m_counter++;
-
-        // Load layer icon
-        m_layericon = new ImageIcon(Toolkit.getDefaultToolkit().createImage(PicLayerAbstract.class.getResource("/images/layericon.png")));
-    }
-
-    /**
-     * Initializes the image. Gets the image from a subclass and stores some
-     * initial parameters. Throws exception if something fails.
-     */
-    public void initialize() throws IOException {
-        // First, we initialize the calibration, so that createImage() can rely on it
-        
-        // If the map does not exist - we're screwed. We should not get into this situation in the first place!
-        if ( Main.map != null && Main.map.mapView != null ) {
-            // Geographical position of the image
-            // getCenter() documentation claims it returns a clone, but this is not in line with the code,
-            // which actually returns the same object upon subsequent calls. This messes things up
-            // when we loading several pictures and associated cal's in one go.
-            // So as a workaround, copy the object manually :
-            // TODO: not sure about this code below, probably there is a better way to clone the objects
-            EastNorth center = Main.map.mapView.getCenter();
-            m_initial_position = new EastNorth(center.east(), center.north());
-            m_position = new EastNorth(center.east(), center.north());
-            // Initial scale at which the image was loaded
-            m_initial_scale = Main.map.mapView.getDist100Pixel();
-        } else {
-            throw new IOException(tr("Could not find the map object."));
-        }
-
-        // Create image
-        m_image = createImage();
-        if ( m_image == null ) {
-            throw new IOException(tr("PicLayer failed to load or import the image."));
-        }
-        // Load image completely
-        (new ImageIcon(m_image)).getImage();
-        
-        lookForCalibration();
-    }
-
-    /**
-     * To be overridden by subclasses. Provides an image from an external sources.
-     * Throws exception if something does not work.
-     *
-     * TODO: Replace the IOException by our own exception.
-     */
-    protected abstract Image createImage() throws IOException;
-
-    protected abstract void lookForCalibration() throws IOException;
-    /**
-     * To be overridden by subclasses. Returns the user readable name of the layer.
-     */
-    protected abstract String getPicLayerName();
-
-    @Override
-    public Icon getIcon() {
-        return m_layericon;
-    }
-
-    @Override
-    public Object getInfoComponent() {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Action[] getMenuEntries() {
-        // Main menu
-        return new Action[] {
-                new ResetSubmenuAction(),
-                SeparatorLayerAction.INSTANCE,
-                new SavePictureCalibrationAction(this),
-                new LoadPictureCalibrationAction(this),
-                SeparatorLayerAction.INSTANCE,
-                new RenameLayerAction(null,this)
-        };
-    }
-
-    @Override
-    public String getToolTipText() {
-        return getPicLayerName();
-    }
-
-    @Override
-    public boolean isMergable(Layer arg0) {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    @Override
-    public void mergeFrom(Layer arg0) {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void paint(Graphics2D g2, MapView mv, Bounds bounds) {
-
-        if ( m_image != null) {
-
-            // Position image at the right graphical place
-            EastNorth center = Main.map.mapView.getCenter();
-            EastNorth leftop = Main.map.mapView.getEastNorth( 0, 0 );
-            // Number of pixels for one unit in east north space.
-            // This is the same in x- and y- direction.
-            double pixel_per_en = ( Main.map.mapView.getWidth() / 2.0 ) / ( center.east() - leftop.east() );
-
-            //     This is now the offset in screen pixels
-            double pic_offset_x = (( m_position.east() - leftop.east() ) * pixel_per_en);
-            double pic_offset_y = (( leftop.north() - m_position.north() ) * pixel_per_en);
-
-            Graphics2D g = (Graphics2D)g2.create();
-            // Move
-            g.translate( pic_offset_x, pic_offset_y );
-            // Rotate
-            g.rotate( m_angle * Math.PI / 180.0 );
-            // Scale
-            double scalex = m_scalex * m_initial_scale * pixel_per_en / getMetersPerEasting(m_position) / 100;
-            double scaley = m_scaley * m_initial_scale * pixel_per_en / getMetersPerNorthing(m_position) / 100;
-            g.scale( scalex, scaley );
-            // Shear
-            g.shear(m_shearx, m_sheary);
-
-            // Draw picture
-            g.drawImage( m_image, -m_image.getWidth(null) / 2, -m_image.getHeight(null) / 2, null );
-
-            // Draw additional rectangle for the active pic layer
-            if ( Main.map.mapView.getActiveLayer() == this ) {
-                g.setColor( new Color( 0xFF0000 ) );
-                g.drawRect(
-                    -m_image.getWidth(null) / 2,
-                    -m_image.getHeight(null) / 2,
-                    m_image.getWidth(null),
-                    m_image.getHeight(null)
-                );
-            }
-        } else {
-            // TODO: proper logging
-            System.out.println( "PicLayerAbstract::paint - general drawing error (m_image is null or Graphics not 2D" );
-        }
-    }
-    
-    /**
-     * Returns the distance in meter, that corresponds to one unit in east north
-     * space. For normal projections, it is about 1 (but usually changing with 
-     * latitude).
-     * For EPSG:4326, it is the distance from one meridian of full degree to the 
-     * next (a couple of kilometers).
-     */
-    private double getMetersPerEasting(EastNorth en) {
-        /* Natural scale in east/north units per pixel.
-         * This means, the projection should be able to handle
-         * a shift of that size in east north space without
-         * going out of bounds.
-         * 
-         * Also, this should get us somewhere in the range of meters,
-         * so we get the result at the point 'en' and not some average.
-         */
-        double naturalScale = Main.getProjection().getDefaultZoomInPPD();
-        naturalScale *= 0.01; // make a little smaller
-        
-        LatLon ll1 = Main.getProjection().eastNorth2latlon(
-                new EastNorth(en.east() - naturalScale, en.north()));
-        LatLon ll2 = Main.getProjection().eastNorth2latlon(
-                new EastNorth(en.east() + naturalScale, en.north()));
-        
-        double dist = ll1.greatCircleDistance(ll2) / naturalScale / 2;
-        return dist;
-    }
-
-    /* see getMetersPerEasting */
-    private double getMetersPerNorthing(EastNorth en) {
-        double naturalScale = Main.getProjection().getDefaultZoomInPPD();
-        naturalScale *= 0.01;
-        
-        LatLon ll1 = Main.getProjection().eastNorth2latlon(
-                new EastNorth(en.east(), en.north()- naturalScale));
-        LatLon ll2 = Main.getProjection().eastNorth2latlon(
-                new EastNorth(en.east(), en.north() + naturalScale));
-        
-        double dist = ll1.greatCircleDistance(ll2) / naturalScale / 2;
-        return dist;
-    }
-    
-    /**
-     * Moves the picture. Scaled in EastNorth...
-     */
-    public void movePictureBy( double east, double north ) {
-        m_position = m_position.add( east, north );
-    }
-
-    /**
-     * Scales the picture. scalex and scaley will multiply the current factor
-     */
-    public void scalePictureBy( double scalex, double scaley ) {
-        m_scalex *= scalex;
-        m_scaley *= scaley;
-    }
-
-    /**
-     * Rotates the picture. Scales in angles.
-     */
-    public void rotatePictureBy( double angle ) {
-        m_angle += angle;
-    }
-
-    /**
-     * Shear the picture. shearx and sheary will separately add to the
-     * corresponding current value
-     */
-    public void shearPictureBy( double shearx, double sheary ) {
-        m_shearx += shearx;
-        m_sheary += sheary;
-    }
-
-    /**
-     * Sets the image position to the initial position
-     */
-    public void resetPosition() {
-        m_position = m_initial_position;
-    }
-
-    /**
-     * Sets the image scale to 1.0
-     */
-    public void resetScale() {
-        m_scalex = 1.0;
-        m_scaley = 1.0;
-    }
-
-    /**
-     * Sets the image angle to 0.0
-     */
-    public void resetAngle() {
-        m_angle = 0.0;
-    }
-
-
-    /**
-     * Sets the image to no shear
-     */
-    public void resetShear() {
-        m_shearx = 0.0;
-        m_sheary = 0.0;
-    }
-    @Override
-    /**
-     * Computes the (rough) bounding box.
-     * We ignore the rotation, the resulting bounding box contains any possible
-     * rotation.
-     */
-    public void visitBoundingBox(BoundingXYVisitor arg0) {
-        if ( m_image == null )
-            return;
-        String projcode = Main.getProjection().toCode();
-
-        // TODO: bounding box only supported when coordinates are in meters
-        // The reason for that is that this .cal think makes us a hard time. 
-        // The position is stored as a raw data (can be either in degrees or 
-        // in meters, depending on the projection used at creation), but the 
-        // initial scale is in m/100pix
-        // So for now, we support the bounding box only when everything is in meters
-        if (projcode.equals("EPSG:4326") )
-            return;
-            
-        EastNorth center = m_position;
-        double w = m_image.getWidth(null);
-        double h = m_image.getHeight(null);
-        double diag_pix = Math.sqrt(w*w+h*h);
-        
-        // m_initial_scale is a the scale (unit: m/100pix) at creation time
-        double diag_m = (diag_pix/100) * m_initial_scale;
-        
-        double factor = Math.max(m_scalex, m_scaley);
-        double offset = factor * diag_m / 2.0;
-
-        EastNorth topleft = center.add(-offset, -offset);
-        EastNorth bottomright = center.add(offset, offset);
-        arg0.visit(topleft);
-        arg0.visit(bottomright);
-    }
-
-    /**
-     * Saves the calibration data into properties structure
-     * @param props Properties to save to
-     */
-    public void saveCalibration( Properties props ) {
-        // Save
-        props.put(INITIAL_POS_X, "" + m_initial_position.getX());
-        props.put(INITIAL_POS_Y, "" + m_initial_position.getY());
-        props.put(POSITION_X, "" + m_position.getX());
-        props.put(POSITION_Y, "" + m_position.getY());
-        props.put(INITIAL_SCALE, "" + m_initial_scale);
-        props.put(SCALEX, "" + m_scalex);
-        props.put(SCALEY, "" + m_scaley);
-        props.put(ANGLE, "" + m_angle);
-        props.put(SHEARX, "" + m_shearx);
-        props.put(SHEARY, "" + m_sheary);
-    }
-
-    /**
-     * Loads calibration data from file
-     * @param file The file to read from
-     * @return
-     */
-    public void loadCalibration(InputStream is) throws IOException {
-        Properties props = new Properties();
-        props.load(is);
-        loadCalibration(props);
-    }
-
-    /**
-     * Loads calibration data from properties structure
-     * @param props Properties to load from
-     * @return
-     */
-    public void loadCalibration( Properties props ) {
-        // Load
-            double pos_x = Double.valueOf( props.getProperty(POSITION_X));
-            double pos_y = Double.valueOf( props.getProperty(POSITION_Y));
-            double in_pos_x = Double.valueOf( props.getProperty(INITIAL_POS_X));
-            double in_pos_y = Double.valueOf( props.getProperty(INITIAL_POS_Y));
-            double angle = Double.valueOf( props.getProperty(ANGLE));
-            double in_scale = Double.valueOf( props.getProperty(INITIAL_SCALE));
-            double scale_x = Double.valueOf( props.getProperty(SCALEX));
-            double scale_y = Double.valueOf( props.getProperty(SCALEY));
-            double shear_x = Double.valueOf( props.getProperty(SHEARX));
-            double shear_y = Double.valueOf( props.getProperty(SHEARY));
-            m_position.setLocation(pos_x, pos_y);
-            m_initial_position.setLocation(pos_x, pos_y);
-            m_angle = angle;
-            m_scalex = scale_x;
-            m_scaley = scale_y;
-            m_shearx = shear_x;
-            m_sheary = shear_y;
-            m_initial_scale = in_scale;
-            // Refresh
-            Main.map.mapView.repaint();
-    }
-    
-    public void loadWorldfile(InputStream is) throws IOException {
-        BufferedReader br = null;
-        try {
-            Reader reader = new InputStreamReader(is);
-            br = new BufferedReader(reader);
-            double e[] = new double[6];
-            for (int i=0; i<6; ++i) {
-                String line = br.readLine();
-                e[i] = Double.parseDouble(line);
-            }
-            double sx=e[0], ry=e[1], rx=e[2], sy=e[3], dx=e[4], dy=e[5];
-            int w = m_image.getWidth(null);
-            int h = m_image.getHeight(null);
-            m_position.setLocation(
-                    dx + w/2*sx + h/2*rx, 
-                    dy + w/2*ry + h/2*sy
-            );
-            m_initial_position.setLocation(m_position);
-            m_angle = 0;
-            m_scalex = 100*sx*getMetersPerEasting(m_position);
-            m_scaley = -100*sy*getMetersPerNorthing(m_position);
-            m_shearx = rx / sx;
-            m_sheary = ry / sy;
-            m_initial_scale = 1;
-            Main.map.mapView.repaint();
-        } finally {
-            Utils.close(br);
-        }
-    }
-
-    private class ResetSubmenuAction extends AbstractAction implements LayerAction {
-
-        public ResetSubmenuAction() {
-            super(tr("Reset"));
-        }
-
-        public void actionPerformed(ActionEvent e) {
-        }
-
-        public Component createMenuComponent() {
-            JMenu reset_submenu = new JMenu(this);
-            reset_submenu.add( new ResetPictureAllAction( PicLayerAbstract.this ) );
-            reset_submenu.addSeparator();
-            reset_submenu.add( new ResetPicturePositionAction( PicLayerAbstract.this ) );
-            reset_submenu.add( new ResetPictureAngleAction( PicLayerAbstract.this ) );
-            reset_submenu.add( new ResetPictureScaleAction( PicLayerAbstract.this ) );
-            reset_submenu.add( new ResetPictureShearAction( PicLayerAbstract.this ) );
-            return reset_submenu;
-        }
-
-        public boolean supportLayers(List<Layer> layers) {
-            return layers.size() == 1 && layers.get(0) instanceof PicLayerAbstract;
-        }
-
-    }
-}
Index: plications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/PicLayerFromClipboard.java
===================================================================
--- /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/PicLayerFromClipboard.java	(revision 27119)
+++ 	(revision )
@@ -1,72 +1,0 @@
-/***************************************************************************
- *   Copyright (C) 2009 by Tomasz Stelmach                                 *
- *   http://www.stelmach-online.net/                                       *
- *                                                                         *
- *   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; either version 2 of the License, or     *
- *   (at your option) any later version.                                   *
- *                                                                         *
- *   This program 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 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 org.openstreetmap.josm.plugins.piclayer;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.awt.Image;
-import java.awt.Toolkit;
-import java.awt.datatransfer.DataFlavor;
-import java.awt.datatransfer.Transferable;
-import java.awt.datatransfer.UnsupportedFlavorException;
-import java.io.IOException;
-
-/**
- * Layer displaying a picture copied from the clipboard.
- */
-public class PicLayerFromClipboard extends PicLayerAbstract {
-
-    @Override
-    protected Image createImage() throws IOException {
-        // Return item
-        Image image = null;
-        // Access the clipboard
-        Transferable t = Toolkit.getDefaultToolkit().getSystemClipboard().getContents(null);
-        // Check result
-        if ( t == null ) {
-            throw new IOException(tr("Nothing in clipboard"));
-        }
-
-        // TODO: Why is it so slow?
-        // Try to make it an image data
-        try {
-            if (t.isDataFlavorSupported(DataFlavor.imageFlavor)) {
-                image = (Image)t.getTransferData(DataFlavor.imageFlavor);
-            } else {
-                throw new IOException(tr("The clipboard data is not an image"));
-            }
-        } catch (UnsupportedFlavorException e) {
-            throw new IOException( e.getMessage() );
-        }
-
-        return image;
-    }
-
-    @Override
-    protected String getPicLayerName() {
-        return "Clipboard";
-    }
-
-    @Override
-    protected void lookForCalibration() throws IOException {
-    }
-
-}
Index: plications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/PicLayerFromFile.java
===================================================================
--- /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/PicLayerFromFile.java	(revision 27119)
+++ 	(revision )
@@ -1,281 +1,0 @@
-/***************************************************************************
- *   Copyright (C) 2009 by Tomasz Stelmach                                 *
- *   http://www.stelmach-online.net/                                       *
- *                                                                         *
- *   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; either version 2 of the License, or     *
- *   (at your option) any later version.                                   *
- *                                                                         *
- *   This program 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 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 org.openstreetmap.josm.plugins.piclayer;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import org.openstreetmap.josm.Main;
-
-import java.awt.Image;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Arrays;
-import java.util.Enumeration;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipFile;
-
-import javax.imageio.ImageIO;
-import javax.swing.JOptionPane;
-
-import org.openstreetmap.josm.tools.Utils;
-/**
- * Layer displaying a picture loaded from a file.
- */
-public class PicLayerFromFile extends PicLayerAbstract {
-
-    // File to load from.
-    private File m_file;
-
-    // whether the file is a zip archive
-    private boolean isZip;
-    // if so, what is the name of the image inside the archive?
-    private String imgNameInZip;
-
-    // Tooltip text
-    private String m_tooltiptext;
-
-    public PicLayerFromFile( File file ) {
-        // Remember the file
-        m_file = file;
-
-        if ("zip".equalsIgnoreCase(getFileExtension(file))) {
-            isZip = true;
-        }
-
-        // Generate tooltip text
-        m_tooltiptext = m_file.getAbsolutePath();
-
-        // Set the name of the layer as the base name of the file
-        setName(m_file.getName());
-    }
-
-    @Override
-    protected Image createImage() throws IOException {
-        // Try to load file
-        Image image = null;
-
-        if (isZip) {
-            ZipFile zipFile = null;
-            try
-            {
-                zipFile = new ZipFile(m_file);
-                ZipEntry imgEntry = null;
-                Enumeration<? extends ZipEntry> entries = zipFile.entries();
-                String[] supportedImageExtensions = ImageIO.getReaderFormatNames();
-
-                while_loop:
-                while (entries.hasMoreElements()) {
-                    ZipEntry entry = entries.nextElement();
-                    for (String extension : supportedImageExtensions) {
-                        if (entry.getName().endsWith("." + extension)) {
-                            imgEntry = entry;
-                            break while_loop;
-                        }
-                    }
-                }
-                if (imgEntry != null) {
-                    imgNameInZip = imgEntry.getName();
-                    InputStream is = null;
-                    try {
-                        is = zipFile.getInputStream(imgEntry);
-                        image = ImageIO.read(is);
-                        return image;
-                    } finally {
-                        Utils.close(is);
-                    }
-                }
-                System.err.println("Warning: no image in zip file found");
-                return null;
-            } catch (Exception e) {
-                System.err.println(tr("Warning: failed to handle zip file ''{0}''. Exception was: {1}", m_file.getName(), e.toString()));
-                return null;
-            } finally {
-                if (zipFile != null) {
-                    try {
-                        zipFile.close();
-                    } catch (IOException ex) {
-                    }
-                }
-            }
-        } else {
-            image = ImageIO.read( m_file );
-            return image;
-        }
-    }
-
-    public enum CalibrationType { CAL, WORLDFILE }
-
-    public static class CalData {
-        public String[] imgExt;
-        public String[] calExt;
-        public CalibrationType type;
-
-        public CalData(String[] imgExt, String[] calExt, CalibrationType type) {
-            this.imgExt = imgExt;
-            this.calExt = calExt;
-            this.type = type;
-        }
-    }
-
-    @Override
-    protected void lookForCalibration() throws IOException {
-        // Manage a potential existing calibration file
-
-        String[][] imgExtensions = new String[][] {
-            { ".jpg", ".jpeg" },
-            { ".png" },
-            { ".tif", ".tiff" },
-            { ".bmp" },
-        };
-        String[][] wldExtensions = new String[][] {
-            { ".wld", ".jgw", ".jpgw" },
-            { ".wld", ".pgw", ".pngw" },
-            { ".wld", ".tfw", ".tifw" },
-            { ".wld", ".bmpw", ".bpw"},
-        };
-
-        if (isZip) {
-            ZipFile zipFile = null;
-            try
-            {
-                zipFile = new ZipFile(m_file);
-                String calFileStr = imgNameInZip + CalibrationFileFilter.EXTENSION;
-                ZipEntry calEntry = zipFile.getEntry(calFileStr);
-                if (calEntry != null) {
-                    if (confirmCalibrationLoading(calFileStr)) {
-                        InputStream is = zipFile.getInputStream(calEntry);
-                        loadCalibration(is);
-                        return;
-                    }
-                } else {
-                    int dotIdx = imgNameInZip.lastIndexOf(".");
-                    if (dotIdx == -1) return;
-                    String extension = imgNameInZip.substring(dotIdx);
-                    String namepart = imgNameInZip.substring(0, dotIdx);
-                    for (int i=0; i<imgExtensions.length; ++i) {
-                        if (Arrays.asList(imgExtensions[i]).contains(extension.toLowerCase())) {
-                            for (String wldExtension : wldExtensions[i]) {
-                                String wldName = namepart+wldExtension;
-                                ZipEntry wldEntry = zipFile.getEntry(wldName);
-                                if (wldEntry != null) {
-                                    if (confirmCalibrationLoading(wldName)) {
-                                        InputStream is = zipFile.getInputStream(wldEntry);
-                                        loadWorldfile(is);
-                                        return;
-                                    }
-                                }
-                            }
-                        }
-                    }
-                }
-            } catch (Exception e) {
-                System.err.println(tr("Warning: failed to handle zip file ''{0}''. Exception was: {1}", m_file.getName(), e.toString()));
-                return;
-            } finally {
-                if (zipFile != null) {
-                    try {
-                        zipFile.close();
-                    } catch (IOException ex) {
-                    }
-                }
-            }
-        } else {
-            File calFile = new File(m_file + CalibrationFileFilter.EXTENSION);
-            if (calFile.exists()) {
-                if (confirmCalibrationLoading(calFile.getName())) {
-                    loadCalibration(new FileInputStream(calFile));
-                }
-            } else {
-                int dotIdx = m_file.getName().lastIndexOf(".");
-                if (dotIdx == -1) return;
-                String extension = m_file.getName().substring(dotIdx);
-                String namepart = m_file.getName().substring(0, dotIdx);
-                for (int i=0; i<imgExtensions.length; ++i) {
-                    if (Arrays.asList(imgExtensions[i]).contains(extension.toLowerCase())) {
-                        for (String wldExtension : wldExtensions[i]) {
-                            File wldFile = new File(m_file.getParentFile(), namepart+wldExtension);
-                            if (wldFile.exists()) {
-                                loadWorldfile(new FileInputStream(wldFile));
-                                return;
-                            }
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    protected boolean confirmCalibrationLoading(String fileName) {
-        String prefkey = "piclayer.autoloadcal";
-        String policy = Main.pref.get(prefkey, "");
-        policy = policy.trim().toLowerCase();
-        boolean loadcal = false;
-
-        String msg = tr("A calibration file associated to the picture file was found: {0}\n", fileName);
-        if ( policy.equals("yes") ) {
-            loadcal = true;
-        }
-        else if ( policy.equals("no") ) {
-            loadcal = false;
-        }
-        else if ( policy.equals("ask") ) {
-            msg += "\n" + tr("Set \"{0}\" to yes/no/ask in the preferences\n"+
-                            "to control the autoloading of calibration files.", prefkey);
-            msg += "\n" + tr("Do you want to apply it ?");
-            int answer = JOptionPane.showConfirmDialog(Main.parent, msg, tr("Load calibration file ?"), JOptionPane.YES_NO_OPTION);
-            if (answer == JOptionPane.YES_OPTION) {
-                loadcal = true;
-            }
-        }
-        else {
-            msg += "\n" + tr("It will be applied automatically.");
-            msg += "\n" + tr("Also, from now on, calibration files will always be loaded automatically.");
-            msg += "\n" + tr("Set \"{0}\" to yes/no/ask in the preferences\n"+
-                            "to control the autoloading of calibration files.", prefkey);
-            // TODO: there should be here a yes/no dialog with a checkbox "do not ask again"
-            JOptionPane.showMessageDialog(Main.parent, msg,
-                "Automatic loading of the calibration", JOptionPane.INFORMATION_MESSAGE);
-            Main.pref.put(prefkey, "yes");
-            loadcal = true;
-        }
-        return loadcal;
-    }
-
-    @Override
-    protected String getPicLayerName() {
-        return m_tooltiptext;
-    }
-
-    /**
-     * Get the file extension
-     * @param f the file
-     * @return everything after the last '.'
-     *         the empty string, if there is no extension
-     */
-    public static String getFileExtension(File f) {
-        int dotIdx = f.getName().lastIndexOf('.');
-        if (dotIdx == -1) return "";
-        return f.getName().substring(dotIdx+1);
-    }
-
-}
Index: /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/PicLayerPlugin.java
===================================================================
--- /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/PicLayerPlugin.java	(revision 27119)
+++ /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/PicLayerPlugin.java	(revision 27120)
@@ -25,14 +25,25 @@
 
 import java.awt.event.KeyEvent;
+
 import javax.swing.JMenu;
 
 import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.plugins.Plugin;
-import org.openstreetmap.josm.plugins.PluginInformation;
 import org.openstreetmap.josm.gui.IconToggleButton;
+import org.openstreetmap.josm.gui.MapFrame;
 import org.openstreetmap.josm.gui.MapView;
 import org.openstreetmap.josm.gui.MapView.LayerChangeListener;
 import org.openstreetmap.josm.gui.layer.Layer;
-import org.openstreetmap.josm.gui.MapFrame;
+import org.openstreetmap.josm.plugins.Plugin;
+import org.openstreetmap.josm.plugins.PluginInformation;
+import org.openstreetmap.josm.plugins.piclayer.actions.newlayer.NewLayerFromClipboardAction;
+import org.openstreetmap.josm.plugins.piclayer.actions.newlayer.NewLayerFromFileAction;
+import org.openstreetmap.josm.plugins.piclayer.actions.transform.MovePictureAction;
+import org.openstreetmap.josm.plugins.piclayer.actions.transform.RotatePictureAction;
+import org.openstreetmap.josm.plugins.piclayer.actions.transform.ScaleXPictureAction;
+import org.openstreetmap.josm.plugins.piclayer.actions.transform.ScaleXYPictureAction;
+import org.openstreetmap.josm.plugins.piclayer.actions.transform.ScaleYPictureAction;
+import org.openstreetmap.josm.plugins.piclayer.actions.transform.ShearPictureAction;
+import org.openstreetmap.josm.plugins.piclayer.actions.transform.affine.MovePointAction;
+import org.openstreetmap.josm.plugins.piclayer.actions.transform.affine.TransformPointAction;
 
 /**
@@ -41,18 +52,18 @@
 public class PicLayerPlugin extends Plugin implements LayerChangeListener {
 
-    // Plugin menu
-    private JMenu m_menu = null;
 
     // Toolbar buttons
-    private IconToggleButton m_movePictureButton = null;
-    private IconToggleButton m_rotatePictureButton = null;
-    private IconToggleButton m_scalexPictureButton = null;
-    private IconToggleButton m_scaleyPictureButton = null;
-    private IconToggleButton m_scalexyPictureButton = null;
-    private IconToggleButton m_shearPictureButton = null;
+    static IconToggleButton movePictureButton = null;
+    static IconToggleButton movePointButton = null;
+    static IconToggleButton transformPointButton = null;
+    static IconToggleButton rotatePictureButton = null;
+    static IconToggleButton scalexPictureButton = null;
+    static IconToggleButton scaleyPictureButton = null;
+    static IconToggleButton scalexyPictureButton = null;
+    static IconToggleButton shearPictureButton = null;
 
-    // Menu actions
-    private NewLayerFromFileAction      m_newFromFileAction = null;
-    private NewLayerFromClipboardAction m_newFromClipAction = null;
+    // Plugin menu
+    private JMenu menu = null;
+    private ActionVisibilityChangeMenu actionVisibility;
 
     /**
@@ -64,13 +75,12 @@
         // Create menu entry
         if ( Main.main.menu != null ) {
-            m_menu = Main.main.menu.addMenu(marktr("PicLayer") , KeyEvent.VK_I, Main.main.menu.defaultMenuPos, ht("/Plugin/PicLayer"));
+            menu = Main.main.menu.addMenu(marktr("PicLayer") , KeyEvent.VK_I, Main.main.menu.defaultMenuPos, ht("/Plugin/PicLayer"));
         }
 
         // Add menu items
-        if ( m_menu != null ) {
-            m_menu.add( m_newFromFileAction = new NewLayerFromFileAction() );
-            m_menu.add( m_newFromClipAction = new NewLayerFromClipboardAction() );
-            m_newFromFileAction.setEnabled( false );
-            m_newFromClipAction.setEnabled( false );
+        if ( menu != null ) {
+            menu.add(new NewLayerFromFileAction());
+            menu.add(new NewLayerFromClipboardAction());
+            menu.setEnabled(false);
         }
 
@@ -82,8 +92,12 @@
      * Called when the map is created. Creates the toolbar buttons.
      */
+    @Override
     public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) {
         if(newFrame != null) {
             // Create plugin map modes
             MovePictureAction movePictureAction = new MovePictureAction(newFrame);
+            MovePointAction movePointAction = new MovePointAction(newFrame);
+            TransformPointAction transformPointAction = new TransformPointAction(newFrame);
+
             RotatePictureAction rotatePictureAction = new RotatePictureAction(newFrame);
             ScaleXYPictureAction scaleXYPictureAction = new ScaleXYPictureAction(newFrame);
@@ -92,32 +106,34 @@
             ShearPictureAction shearPictureAction = new ShearPictureAction(newFrame);
             // Create plugin buttons and add them to the toolbar
-            m_movePictureButton = new IconToggleButton(movePictureAction);
-            m_rotatePictureButton = new IconToggleButton(rotatePictureAction);
-            m_scalexyPictureButton = new IconToggleButton(scaleXYPictureAction);
-            m_scalexPictureButton = new IconToggleButton(scaleXPictureAction);
-            m_scaleyPictureButton = new IconToggleButton(scaleYPictureAction);
-            m_shearPictureButton = new IconToggleButton(shearPictureAction);
-            newFrame.addMapMode(m_movePictureButton);
-            newFrame.addMapMode(m_rotatePictureButton);
-            newFrame.addMapMode(m_scalexyPictureButton);
-            newFrame.addMapMode(m_scalexPictureButton);
-            newFrame.addMapMode(m_scaleyPictureButton);
-            newFrame.addMapMode(m_shearPictureButton);
+            movePictureButton = new IconToggleButton(movePictureAction);
+            movePointButton = new IconToggleButton(movePointAction);
+            transformPointButton = new IconToggleButton(transformPointAction);
+            rotatePictureButton = new IconToggleButton(rotatePictureAction);
+            scalexyPictureButton = new IconToggleButton(scaleXYPictureAction);
+            scalexPictureButton = new IconToggleButton(scaleXPictureAction);
+            scaleyPictureButton = new IconToggleButton(scaleYPictureAction);
+            shearPictureButton = new IconToggleButton(shearPictureAction);
+            newFrame.addMapMode(movePictureButton);
+            newFrame.addMapMode(movePointButton);
+            newFrame.addMapMode(transformPointButton);
+            newFrame.addMapMode(rotatePictureButton);
+            newFrame.addMapMode(scalexyPictureButton);
+            newFrame.addMapMode(scalexPictureButton);
+            newFrame.addMapMode(scaleyPictureButton);
+            newFrame.addMapMode(shearPictureButton);
 //            newFrame.toolGroup.add(m_movePictureButton);
 //            newFrame.toolGroup.add(m_rotatePictureButton);
 //            newFrame.toolGroup.add(m_scalePictureButton);
             // Show them by default
-            m_movePictureButton.setVisible(true);
-            m_rotatePictureButton.setVisible(true);
-            m_scalexyPictureButton.setVisible(true);
-            m_scalexPictureButton.setVisible(true);
-            m_scaleyPictureButton.setVisible(true);
-            m_shearPictureButton.setVisible(true);
+
+            if (actionVisibility == null)
+                menu.add(actionVisibility = new ActionVisibilityChangeMenu());
         }
     }
 
-    /**
+	/**
      * The toolbar buttons shall be active only when the PicLayer is active.
      */
+    @Override
     public void activeLayerChange(Layer oldLayer, Layer newLayer) {
     }
@@ -128,7 +144,7 @@
      * one must exist first). User should not be able to load a picture too early.
      */
+    @Override
     public void layerAdded(Layer arg0) {
-        m_newFromFileAction.setEnabled( true );
-        m_newFromClipAction.setEnabled( true );
+        menu.setEnabled(true);
     }
 
@@ -136,8 +152,8 @@
      * When all layers are gone - the menu is gone too.
      */
+    @Override
     public void layerRemoved(Layer arg0) {
         boolean enable = Main.map.mapView.getAllLayers().size() != 0;
-        m_newFromFileAction.setEnabled( enable );
-        m_newFromClipAction.setEnabled( enable );
+        menu.setEnabled(enable);
     }
 };
Index: plications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/ResetPictureAllAction.java
===================================================================
--- /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/ResetPictureAllAction.java	(revision 27119)
+++ 	(revision )
@@ -1,61 +1,0 @@
-/***************************************************************************
- *   Copyright (C) 2009 by Tomasz Stelmach                                 *
- *   http://www.stelmach-online.net/                                       *
- *                                                                         *
- *   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; either version 2 of the License, or     *
- *   (at your option) any later version.                                   *
- *                                                                         *
- *   This program 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 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 org.openstreetmap.josm.plugins.piclayer;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.awt.event.ActionEvent;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.actions.JosmAction;
-
-/**
- * Action for resetting properties of an image.
- * 
- * TODO Four almost identical classes. Refactoring needed.
- */
-public class ResetPictureAllAction extends JosmAction {
-
-    // Owner layer of the action
-    PicLayerAbstract m_owner = null;
-    
-    /**
-     * Constructor
-     */
-    public ResetPictureAllAction( PicLayerAbstract owner ) {
-        super(tr("All"), null, tr("Resets picture calibration"), null, false);
-        // Remember the owner...
-        m_owner = owner;
-    }
-    
-    /**
-     * Action handler
-     */
-    public void actionPerformed(ActionEvent arg0) {
-        // Reset
-        m_owner.resetAngle();
-        m_owner.resetPosition();
-        m_owner.resetScale();
-        m_owner.resetShear();
-        // Redraw
-        Main.map.mapView.repaint();
-    }
-}
Index: plications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/ResetPictureAngleAction.java
===================================================================
--- /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/ResetPictureAngleAction.java	(revision 27119)
+++ 	(revision )
@@ -1,58 +1,0 @@
-/***************************************************************************
- *   Copyright (C) 2009 by Tomasz Stelmach                                 *
- *   http://www.stelmach-online.net/                                       *
- *                                                                         *
- *   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; either version 2 of the License, or     *
- *   (at your option) any later version.                                   *
- *                                                                         *
- *   This program 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 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 org.openstreetmap.josm.plugins.piclayer;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.awt.event.ActionEvent;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.actions.JosmAction;
-
-/**
- * Action for resetting properties of an image.
- * 
- * TODO Four almost identical classes. Refactoring needed.
- */
-public class ResetPictureAngleAction extends JosmAction {
-
-    // Owner layer of the action
-    PicLayerAbstract m_owner = null;
-    
-    /**
-     * Constructor
-     */
-    public ResetPictureAngleAction( PicLayerAbstract owner ) {
-        super(tr("Angle"), null, tr("Resets picture rotation"), null, false);
-        // Remember the owner...
-        m_owner = owner;
-    }
-    
-    /**
-     * Action handler
-     */
-    public void actionPerformed(ActionEvent arg0) {
-        // Reset
-        m_owner.resetAngle();
-        // Redraw
-        Main.map.mapView.repaint();
-    }
-}
Index: plications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/ResetPicturePositionAction.java
===================================================================
--- /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/ResetPicturePositionAction.java	(revision 27119)
+++ 	(revision )
@@ -1,58 +1,0 @@
-/***************************************************************************
- *   Copyright (C) 2009 by Tomasz Stelmach                                 *
- *   http://www.stelmach-online.net/                                       *
- *                                                                         *
- *   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; either version 2 of the License, or     *
- *   (at your option) any later version.                                   *
- *                                                                         *
- *   This program 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 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 org.openstreetmap.josm.plugins.piclayer;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.awt.event.ActionEvent;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.actions.JosmAction;
-
-/**
- * Action for resetting properties of an image.
- * 
- * TODO Four almost identical classes. Refactoring needed.
- */
-public class ResetPicturePositionAction extends JosmAction {
-
-    // Owner layer of the action
-    PicLayerAbstract m_owner = null;
-    
-    /**
-     * Constructor
-     */
-    public ResetPicturePositionAction( PicLayerAbstract owner ) {
-        super(tr("Reset position"), null, tr("Resets picture position"), null, false);
-        // Remember the owner...
-        m_owner = owner;
-    }
-    
-    /**
-     * Action handler
-     */
-    public void actionPerformed(ActionEvent arg0) {
-        // Reset
-        m_owner.resetPosition();
-        // Redraw
-        Main.map.mapView.repaint();
-    }
-}
Index: plications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/ResetPictureScaleAction.java
===================================================================
--- /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/ResetPictureScaleAction.java	(revision 27119)
+++ 	(revision )
@@ -1,58 +1,0 @@
-/***************************************************************************
- *   Copyright (C) 2009 by Tomasz Stelmach                                 *
- *   http://www.stelmach-online.net/                                       *
- *                                                                         *
- *   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; either version 2 of the License, or     *
- *   (at your option) any later version.                                   *
- *                                                                         *
- *   This program 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 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 org.openstreetmap.josm.plugins.piclayer;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.awt.event.ActionEvent;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.actions.JosmAction;
-
-/**
- * Action for resetting properties of an image.
- * 
- * TODO Four almost identical classes. Refactoring needed.
- */
-public class ResetPictureScaleAction extends JosmAction {
-
-    // Owner layer of the action
-    PicLayerAbstract m_owner = null;
-    
-    /**
-     * Constructor
-     */
-    public ResetPictureScaleAction( PicLayerAbstract owner ) {
-        super(tr("Scale"), null, tr("Resets picture scale"), null, false);
-        // Remember the owner...
-        m_owner = owner;
-    }
-    
-    /**
-     * Action handler
-     */
-    public void actionPerformed(ActionEvent arg0) {
-        // Reset
-        m_owner.resetScale();
-        // Redraw
-        Main.map.mapView.repaint();
-    }
-}
Index: plications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/ResetPictureShearAction.java
===================================================================
--- /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/ResetPictureShearAction.java	(revision 27119)
+++ 	(revision )
@@ -1,59 +1,0 @@
-/***************************************************************************
- *   Copyright (C) 2011 by Patrick "Petschge" Kilian, based on code        *
- *   Copyright (C) 2009 by Tomasz Stelmach                                 *
- *   http://www.stelmach-online.net/                                       *
- *                                                                         *
- *   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; either version 2 of the License, or     *
- *   (at your option) any later version.                                   *
- *                                                                         *
- *   This program 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 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 org.openstreetmap.josm.plugins.piclayer;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.awt.event.ActionEvent;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.actions.JosmAction;
-
-/**
- * Action for resetting properties of an image.
- * 
- * TODO Four almost identical classes. Refactoring needed.
- */
-public class ResetPictureShearAction extends JosmAction {
-
-    // Owner layer of the action
-    PicLayerAbstract m_owner = null;
-    
-    /**
-     * Constructor
-     */
-    public ResetPictureShearAction( PicLayerAbstract owner ) {
-        super(tr("Shear"), null, tr("Resets picture shear"), null, false);
-        // Remember the owner...
-        m_owner = owner;
-    }
-    
-    /**
-     * Action handler
-     */
-    public void actionPerformed(ActionEvent arg0) {
-        // Reset
-        m_owner.resetShear();
-        // Redraw
-        Main.map.mapView.repaint();
-    }
-}
Index: plications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/RotatePictureAction.java
===================================================================
--- /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/RotatePictureAction.java	(revision 27119)
+++ 	(revision )
@@ -1,107 +1,0 @@
-/***************************************************************************
- *   Copyright (C) 2009 by Tomasz Stelmach                                 *
- *   http://www.stelmach-online.net/                                       *
- *                                                                         *
- *   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; either version 2 of the License, or     *
- *   (at your option) any later version.                                   *
- *                                                                         *
- *   This program 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 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 org.openstreetmap.josm.plugins.piclayer;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.awt.event.MouseEvent;
-import java.awt.event.MouseListener;
-import java.awt.event.MouseMotionListener;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.actions.mapmode.MapMode;
-import org.openstreetmap.josm.gui.MapFrame;
-import org.openstreetmap.josm.tools.ImageProvider;
-
-//TODO: Move/Rotate/Scale/Shear action classes are similar. Do the redesign!
-
-/**
- * This class handles the input during rotating the picture.
- */
-public class RotatePictureAction extends MapMode implements MouseListener, MouseMotionListener
-{
-    // Action ongoing?
-    private boolean mb_dragging = false;
-
-    // Last mouse position
-    private int m_prevY;
-
-    // Layer we're working on
-    private PicLayerAbstract m_currentLayer = null;
-
-    /**
-     * Constructor
-     */
-    public RotatePictureAction(MapFrame frame) {
-        super(tr("PicLayer rotate"), "rotate", tr("Drag to rotate the picture"), frame, ImageProvider.getCursor("crosshair", null));
-        // TODO Auto-generated constructor stub
-    }
-
-    @Override
-    public void enterMode() {
-        super.enterMode();
-        Main.map.mapView.addMouseListener(this);
-        Main.map.mapView.addMouseMotionListener(this);
-    }
-
-    @Override
-    public void exitMode() {
-        super.exitMode();
-        Main.map.mapView.removeMouseListener(this);
-        Main.map.mapView.removeMouseMotionListener(this);
-    }
-
-    @Override
-    public void mousePressed(MouseEvent e) {
-        // Start rotating
-        if ( Main.map.mapView.getActiveLayer() instanceof PicLayerAbstract ) {
-            m_currentLayer = (PicLayerAbstract)Main.map.mapView.getActiveLayer();
-
-            if ( m_currentLayer != null && e.getButton() == MouseEvent.BUTTON1 ) {
-                mb_dragging = true;
-                m_prevY=e.getY();
-            }
-        }
-    }
-
-    @Override
-    public void mouseDragged(MouseEvent e) {
-        // Rotate the picture
-        if(mb_dragging) {
-            double factor;
-            if ( ( e.getModifiersEx() & e.SHIFT_DOWN_MASK ) != 0 ) {
-                factor = Main.pref.getDouble("piclayer.rotatefactors.high_precision", 100.0);
-            }
-            else {
-                factor = Main.pref.getDouble("piclayer.rotatefactors.low_precision", 10.0 );
-            }            
-            m_currentLayer.rotatePictureBy( ( e.getY() - m_prevY ) / factor );
-            m_prevY = e.getY();
-            Main.map.mapView.repaint();
-        }
-    }
-
-    @Override public void mouseReleased(MouseEvent e) {
-        // End rotating
-        mb_dragging = false;
-    }
-
-}
Index: plications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/SavePictureCalibrationAction.java
===================================================================
--- /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/SavePictureCalibrationAction.java	(revision 27119)
+++ 	(revision )
@@ -1,89 +1,0 @@
-/***************************************************************************
- *   Copyright (C) 2009 by Tomasz Stelmach                                 *
- *   http://www.stelmach-online.net/                                       *
- *                                                                         *
- *   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; either version 2 of the License, or     *
- *   (at your option) any later version.                                   *
- *                                                                         *
- *   This program 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 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 org.openstreetmap.josm.plugins.piclayer;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.awt.event.ActionEvent;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.Properties;
-
-import javax.swing.JFileChooser;
-import javax.swing.JOptionPane;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.actions.JosmAction;
-
-/**
- * Action for resetting properties of an image.
- * 
- * TODO Four almost identical classes. Refactoring needed.
- */
-public class SavePictureCalibrationAction extends JosmAction {
-
-    // Owner layer of the action
-    PicLayerAbstract m_owner = null;
-    
-    /**
-     * Constructor
-     */
-    public SavePictureCalibrationAction( PicLayerAbstract owner ) {
-        super(tr("Save Picture Calibration..."), null, tr("Saves calibration data to a file"), null, false);
-        // Remember the owner...
-        m_owner = owner;
-    }
-    
-    /**
-     * Action handler
-     */
-    public void actionPerformed(ActionEvent arg0) {
-        // Save dialog
-        final JFileChooser fc = new JFileChooser();
-        fc.setAcceptAllFileFilterUsed( false );
-        fc.setFileFilter( new CalibrationFileFilter() );
-        fc.setSelectedFile( new File(m_owner.getPicLayerName() + CalibrationFileFilter.EXTENSION));
-        int result = fc.showSaveDialog( Main.parent );
-
-        if ( result == JFileChooser.APPROVE_OPTION ) {
-            // Check file extension and force it to be valid
-            File file = fc.getSelectedFile();
-            String path = file.getAbsolutePath();
-            if ( path.length() < CalibrationFileFilter.EXTENSION.length()
-                || !path.substring( path.length() - 4 ).equals(CalibrationFileFilter.EXTENSION)) {
-                file = new File( path + CalibrationFileFilter.EXTENSION );
-            }
-                        
-            // Save
-            Properties props = new Properties();
-            m_owner.saveCalibration(props);
-            try {
-                props.store(new FileOutputStream(file), tr("JOSM PicLayer plugin calibration data"));
-            } catch (Exception e) {
-                // Error
-                e.printStackTrace();
-                JOptionPane.showMessageDialog(Main.parent , tr("Saving file failed: {0}", e.getMessage()));
-            }
-        }   
-    }
-}
Index: plications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/ScalePictureActionAbstract.java
===================================================================
--- /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/ScalePictureActionAbstract.java	(revision 27119)
+++ 	(revision )
@@ -1,111 +1,0 @@
-/***************************************************************************
- *   Copyright (C) 2009 by Tomasz Stelmach                                 *
- *   http://www.stelmach-online.net/                                       *
- *                                                                         *
- *   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; either version 2 of the License, or     *
- *   (at your option) any later version.                                   *
- *                                                                         *
- *   This program 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 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 org.openstreetmap.josm.plugins.piclayer;
-
-import java.awt.event.MouseEvent;
-import java.awt.event.MouseListener;
-import java.awt.event.MouseMotionListener;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.actions.mapmode.MapMode;
-import org.openstreetmap.josm.gui.MapFrame;
-import org.openstreetmap.josm.tools.ImageProvider;
-
-// TODO: Move/Rotate/Scale action classes are similar. Do the redesign!
-
-/**
- * This class handles the input during scaling the picture.
- */
-public abstract class ScalePictureActionAbstract extends MapMode implements MouseListener, MouseMotionListener
-{
-    // Scaling ongoing?
-    private boolean mb_dragging = false;
-
-    // Last mouse position
-    private int m_prevY;
-
-    // Layer we're working on
-    protected PicLayerAbstract m_currentLayer = null;
-
-    /**
-     * Constructor
-     */
-    public ScalePictureActionAbstract (String name, String icon, String tooltip, MapFrame frame) {
-        super(name, icon, tooltip, frame, ImageProvider.getCursor("crosshair", null));
-        // TODO Auto-generated constructor stub
-    }
-
-    @Override
-    public void enterMode() {
-        super.enterMode();
-        Main.map.mapView.addMouseListener(this);
-        Main.map.mapView.addMouseMotionListener(this);
-    }
-
-    @Override
-    public void exitMode() {
-        super.exitMode();
-        Main.map.mapView.removeMouseListener(this);
-        Main.map.mapView.removeMouseMotionListener(this);
-    }
-
-    @Override
-    public void mousePressed(MouseEvent e) {
-        // Start scaling
-        if ( Main.map.mapView.getActiveLayer() instanceof PicLayerAbstract ) {
-            m_currentLayer = (PicLayerAbstract)Main.map.mapView.getActiveLayer();
-
-            if ( m_currentLayer != null && e.getButton() == MouseEvent.BUTTON1 ) {
-                mb_dragging = true;
-                m_prevY = e.getY();
-            }
-        }
-    }
-
-    @Override
-    public void mouseDragged(MouseEvent e) {
-        // Scale the picture
-        if(mb_dragging) {
-            double factor;
-            if ( ( e.getModifiersEx() & e.SHIFT_DOWN_MASK ) != 0 ) {
-                factor = Main.pref.getDouble("piclayer.scalefactors.high_precision", 1.0005);
-            }
-            else {
-                factor = Main.pref.getDouble("piclayer.scalefactors.low_precision", 1.015);
-            }            
-            doTheScale( Math.pow(factor, m_prevY - e.getY() ) );
-            m_prevY = e.getY();
-            Main.map.mapView.repaint();
-        }
-    }
-
-    @Override
-    public void mouseReleased(MouseEvent e) {
-        // Stop scaling
-        mb_dragging = false;
-    }
-
-    /**
-    * Does the actual scaling in the inherited class.
-    */
-    protected abstract void doTheScale( double scale );
-
-}
Index: plications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/ScaleXPictureAction.java
===================================================================
--- /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/ScaleXPictureAction.java	(revision 27119)
+++ 	(revision )
@@ -1,48 +1,0 @@
-/***************************************************************************
- *   Copyright (C) 2009 by Tomasz Stelmach                                 *
- *   http://www.stelmach-online.net/                                       *
- *                                                                         *
- *   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; either version 2 of the License, or     *
- *   (at your option) any later version.                                   *
- *                                                                         *
- *   This program 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 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 org.openstreetmap.josm.plugins.piclayer;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.actions.mapmode.MapMode;
-import org.openstreetmap.josm.gui.MapFrame;
-import org.openstreetmap.josm.tools.ImageProvider;
-
-// TODO: Move/Rotate/Scale/Shear action classes are similar. Do the redesign!
-
-/**
- * This class handles the input during scaling the picture.
- */
-public class ScaleXPictureAction extends ScalePictureActionAbstract
-{
-    /*
-     * Constructor
-     */
-    public ScaleXPictureAction(MapFrame frame) {
-        super(tr("PicLayer scale X"), "scale_x", tr("Drag to scale the picture in the X Axis"), frame);
-        // TODO Auto-generated constructor stub
-    }
-
-    public void doTheScale( double scale ) {
-            m_currentLayer.scalePictureBy( scale, 1.0 );
-        }
-}
Index: plications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/ScaleXYPictureAction.java
===================================================================
--- /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/ScaleXYPictureAction.java	(revision 27119)
+++ 	(revision )
@@ -1,48 +1,0 @@
-/***************************************************************************
- *   Copyright (C) 2009 by Tomasz Stelmach                                 *
- *   http://www.stelmach-online.net/                                       *
- *                                                                         *
- *   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; either version 2 of the License, or     *
- *   (at your option) any later version.                                   *
- *                                                                         *
- *   This program 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 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 org.openstreetmap.josm.plugins.piclayer;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.actions.mapmode.MapMode;
-import org.openstreetmap.josm.gui.MapFrame;
-import org.openstreetmap.josm.tools.ImageProvider;
-
-// TODO: Move/Rotate/Scale/Shear action classes are similar. Do the redesign!
-
-/**
- * This class handles the input during scaling the picture.
- */
-public class ScaleXYPictureAction extends ScalePictureActionAbstract
-{
-    /*
-     * Constructor
-     */
-    public ScaleXYPictureAction(MapFrame frame) {
-        super(tr("PicLayer scale"), "scale", tr("Drag to scale the picture in the X and Y Axis"), frame);
-        // TODO Auto-generated constructor stub
-    }
-
-    public void doTheScale( double scale ) {
-            m_currentLayer.scalePictureBy( scale, scale );
-        }
-}
Index: plications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/ScaleYPictureAction.java
===================================================================
--- /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/ScaleYPictureAction.java	(revision 27119)
+++ 	(revision )
@@ -1,48 +1,0 @@
-/***************************************************************************
- *   Copyright (C) 2009 by Tomasz Stelmach                                 *
- *   http://www.stelmach-online.net/                                       *
- *                                                                         *
- *   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; either version 2 of the License, or     *
- *   (at your option) any later version.                                   *
- *                                                                         *
- *   This program 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 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 org.openstreetmap.josm.plugins.piclayer;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.actions.mapmode.MapMode;
-import org.openstreetmap.josm.gui.MapFrame;
-import org.openstreetmap.josm.tools.ImageProvider;
-
-// TODO: Move/Rotate/Scale/Shear action classes are similar. Do the redesign!
-
-/**
- * This class handles the input during scaling the picture.
- */
-public class ScaleYPictureAction extends ScalePictureActionAbstract
-{
-    /*
-     * Constructor
-     */
-    public ScaleYPictureAction(MapFrame frame) {
-        super(tr("PicLayer scale Y"), "scale_y", tr("Drag to scale the picture in the Y Axis"), frame);
-        // TODO Auto-generated constructor stub
-    }
-
-    public void doTheScale( double scale ) {
-            m_currentLayer.scalePictureBy( 1.0, scale );
-        }
-}
Index: plications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/ShearPictureAction.java
===================================================================
--- /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/ShearPictureAction.java	(revision 27119)
+++ 	(revision )
@@ -1,108 +1,0 @@
-/***************************************************************************
- *                                                                         *
- *   Copyright (C) 2011 Patrick "Petschge" Kilian, based on code           *
- *   (c) 2009 by Tomasz Stelmach                                           *
- *   http://www.stelmach-online.net/                                       *
- *                                                                         *
- *   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; either version 2 of the License, or     *
- *   (at your option) any later version.                                   *
- *                                                                         *
- *   This program 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 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 org.openstreetmap.josm.plugins.piclayer;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.awt.event.MouseEvent;
-import java.awt.event.MouseListener;
-import java.awt.event.MouseMotionListener;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.actions.mapmode.MapMode;
-import org.openstreetmap.josm.gui.MapFrame;
-import org.openstreetmap.josm.tools.ImageProvider;
-import org.openstreetmap.josm.data.coor.EastNorth;
-
-//TODO: Move/Rotate/Scale/Shear action classes are similar. Do the redesign!
-
-/**
- * This class handles the input during shearing of the picture.
- */
-public class ShearPictureAction extends MapMode implements MouseListener, MouseMotionListener
-{
-    // Action ongoing?
-    private boolean mb_dragging = false;
-
-    // Last mouse position
-    private EastNorth m_prevEastNorth;
-
-    // The layer we're working on
-    private PicLayerAbstract m_currentLayer = null;
-
-    /**
-     * Constructor
-     */
-    public ShearPictureAction(MapFrame frame) {
-        super(tr("PicLayer shear"), "shear", tr("Drag to shear the picture"), frame, ImageProvider.getCursor("crosshair", null));
-    }
-
-    @Override
-    public void enterMode() {
-        super.enterMode();
-        Main.map.mapView.addMouseListener(this);
-        Main.map.mapView.addMouseMotionListener(this);
-    }
-
-    @Override
-    public void exitMode() {
-        super.exitMode();
-        Main.map.mapView.removeMouseListener(this);
-        Main.map.mapView.removeMouseMotionListener(this);
-    }
-
-    @Override
-    public void mousePressed(MouseEvent e) {
-
-        // If everything is OK, we start dragging/moving the picture
-        if ( Main.map.mapView.getActiveLayer() instanceof PicLayerAbstract ) {
-            m_currentLayer = (PicLayerAbstract)Main.map.mapView.getActiveLayer();
-
-            if ( m_currentLayer != null && e.getButton() == MouseEvent.BUTTON1 ) {
-                mb_dragging = true;
-                m_prevEastNorth=Main.map.mapView.getEastNorth(e.getX(),e.getY());
-            }
-        }
-    }
-
-    @Override
-    public void mouseDragged(MouseEvent e) {
-        // Picture moving is ongoing
-        if(mb_dragging) {
-            EastNorth eastNorth = Main.map.mapView.getEastNorth(e.getX(),e.getY());
-            m_currentLayer.shearPictureBy(
-                1000* (eastNorth.east()-m_prevEastNorth.east()),
-                1000* (eastNorth.north()-m_prevEastNorth.north())
-            );
-            m_prevEastNorth = eastNorth;
-            Main.map.mapView.repaint();
-        }
-    }
-
-    @Override
-    public void mouseReleased(MouseEvent e) {
-        // Stop moving
-        mb_dragging = false;
-    }
-
-}
Index: /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/GenericPicTransformAction.java
===================================================================
--- /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/GenericPicTransformAction.java	(revision 27120)
+++ /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/GenericPicTransformAction.java	(revision 27120)
@@ -0,0 +1,92 @@
+package org.openstreetmap.josm.plugins.piclayer.actions;
+
+import java.awt.Cursor;
+import java.awt.Point;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseMotionListener;
+import java.awt.geom.Point2D;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.actions.mapmode.MapMode;
+import org.openstreetmap.josm.data.coor.EastNorth;
+import org.openstreetmap.josm.gui.MapFrame;
+import org.openstreetmap.josm.gui.layer.Layer;
+import org.openstreetmap.josm.plugins.piclayer.layer.PicLayerAbstract;
+import org.openstreetmap.josm.tools.Shortcut;
+
+@SuppressWarnings("serial")
+public abstract class GenericPicTransformAction extends MapMode implements MouseListener, MouseMotionListener {
+
+	protected boolean isDragging = false;
+	protected PicLayerAbstract currentLayer = null;
+	protected Point2D selectedPoint = null;
+	protected EastNorth prevEastNorth = null;
+	protected Point2D prevMousePoint = null;
+
+	public GenericPicTransformAction(String name, String iconName,
+			String tooltip, Shortcut shortcut, MapFrame mapFrame, Cursor cursor) {
+		super(name, iconName, tooltip, shortcut, mapFrame, cursor);
+	}
+
+	public GenericPicTransformAction(String name, String iconName,
+			String tooltip, MapFrame mapFrame, Cursor cursor) {
+		super(name, iconName, tooltip, mapFrame, cursor);
+	}
+
+	@Override
+	public void enterMode() {
+	    super.enterMode();
+	    Main.map.mapView.addMouseListener(this);
+	    Main.map.mapView.addMouseMotionListener(this);
+	}
+
+	@Override
+	public void exitMode() {
+	    super.exitMode();
+	    Main.map.mapView.removeMouseListener(this);
+	    Main.map.mapView.removeMouseMotionListener(this);
+	}
+
+	@Override
+	public void mousePressed(MouseEvent e) {
+	    // Start action
+	    if ( Main.map.mapView.getActiveLayer() instanceof PicLayerAbstract ) {
+	        currentLayer = (PicLayerAbstract)Main.map.mapView.getActiveLayer();
+	
+	        if ( currentLayer != null && e.getButton() == MouseEvent.BUTTON1 ) {
+	            isDragging = true;
+	            prevMousePoint = new Point(e.getPoint());
+	            prevEastNorth = Main.map.mapView.getEastNorth(e.getX(),e.getY());
+	            // try to find and fill selected point if possible
+	            selectedPoint = currentLayer.findSelectedPoint(e.getPoint());
+	        }
+	    }
+	}
+
+	@Override
+    public void mouseDragged(MouseEvent e) {
+        // Call action performing
+        if(isDragging && currentLayer != null) {
+        	doAction(e);
+            prevMousePoint = new Point(e.getPoint());
+            prevEastNorth = Main.map.mapView.getEastNorth(e.getX(),e.getY());
+            Main.map.mapView.repaint();
+        }
+    }
+
+	protected abstract void doAction(MouseEvent e);
+
+	@Override
+	public void mouseReleased(MouseEvent e) {
+	    // End action
+	    isDragging = false;
+	}
+
+	@Override
+	public boolean layerIsSupported(Layer l) {
+		return l instanceof PicLayerAbstract;
+	}
+	
+	
+}
Index: /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/LoadPictureCalibrationAction.java
===================================================================
--- /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/LoadPictureCalibrationAction.java	(revision 27120)
+++ /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/LoadPictureCalibrationAction.java	(revision 27120)
@@ -0,0 +1,83 @@
+/***************************************************************************
+ *   Copyright (C) 2009 by Tomasz Stelmach                                 *
+ *   http://www.stelmach-online.net/                                       *
+ *                                                                         *
+ *   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; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program 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 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 org.openstreetmap.josm.plugins.piclayer.actions;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.event.ActionEvent;
+import java.io.File;
+import java.io.FileInputStream;
+
+import javax.swing.JFileChooser;
+import javax.swing.JOptionPane;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.actions.JosmAction;
+import org.openstreetmap.josm.plugins.piclayer.layer.CalibrationFileFilter;
+import org.openstreetmap.josm.plugins.piclayer.layer.PicLayerAbstract;
+
+/**
+ * Action to load the calibration file.
+ * 
+ */
+@SuppressWarnings("serial")
+public class LoadPictureCalibrationAction extends JosmAction {
+
+    // Owner layer of the action
+    PicLayerAbstract m_owner = null;
+    
+    // Persistent FileChooser instance to remember last directory
+    JFileChooser m_filechooser = null;
+
+    /**
+     * Constructor
+     */
+    public LoadPictureCalibrationAction( PicLayerAbstract owner ) {
+        super(tr("Load Picture Calibration..."), null, tr("Loads calibration data from a file"), null, false);
+        // Remember the owner...
+        m_owner = owner;
+    }
+
+    /**
+     * Action handler
+     */
+    public void actionPerformed(ActionEvent arg0) {
+        // Save dialog
+        JFileChooser fc = new JFileChooser();
+        fc.setAcceptAllFileFilterUsed( false );
+        fc.setFileFilter( new CalibrationFileFilter() );
+        fc.setSelectedFile( new File(m_owner.getPicLayerName() + CalibrationFileFilter.EXTENSION));
+        int result = fc.showOpenDialog(Main.parent );
+
+        if ( result == JFileChooser.APPROVE_OPTION ) {
+                    
+            // Load 
+            try {
+                m_owner.loadCalibration(new FileInputStream(fc.getSelectedFile()));
+            } catch (Exception e) {
+                // Error
+                e.printStackTrace();
+                JOptionPane.showMessageDialog(Main.parent , tr("Loading file failed: {0}", e.getMessage()));
+            }
+        }
+    }
+    
+}
Index: /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/ResetCalibrationAction.java
===================================================================
--- /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/ResetCalibrationAction.java	(revision 27120)
+++ /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/ResetCalibrationAction.java	(revision 27120)
@@ -0,0 +1,26 @@
+package org.openstreetmap.josm.plugins.piclayer.actions;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.event.ActionEvent;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.actions.JosmAction;
+import org.openstreetmap.josm.plugins.piclayer.layer.PicLayerAbstract;
+import org.openstreetmap.josm.plugins.piclayer.transform.PictureTransform;
+
+@SuppressWarnings("serial")
+public class ResetCalibrationAction extends JosmAction {
+
+	private PicLayerAbstract layer;
+	public ResetCalibrationAction(PicLayerAbstract layer, PictureTransform transformer) {
+		super(tr("Reset Calibration"), null, tr("Reset calibration"), null, false);
+		this.layer = layer;
+	}
+	
+	@Override
+	public void actionPerformed(ActionEvent arg0) {
+		layer.resetCalibration();
+		Main.map.mapView.repaint();
+	}
+}
Index: /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/SavePictureCalibrationAction.java
===================================================================
--- /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/SavePictureCalibrationAction.java	(revision 27120)
+++ /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/SavePictureCalibrationAction.java	(revision 27120)
@@ -0,0 +1,90 @@
+/***************************************************************************
+ *   Copyright (C) 2009 by Tomasz Stelmach                                 *
+ *   http://www.stelmach-online.net/                                       *
+ *                                                                         *
+ *   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; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program 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 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 org.openstreetmap.josm.plugins.piclayer.actions;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.event.ActionEvent;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.util.Properties;
+
+import javax.swing.JFileChooser;
+import javax.swing.JOptionPane;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.actions.JosmAction;
+import org.openstreetmap.josm.plugins.piclayer.layer.CalibrationFileFilter;
+import org.openstreetmap.josm.plugins.piclayer.layer.PicLayerAbstract;
+
+/**
+ * Action for resetting properties of an image.
+ * 
+ * TODO Four almost identical classes. Refactoring needed.
+ */
+@SuppressWarnings("serial")
+public class SavePictureCalibrationAction extends JosmAction {
+
+    // Owner layer of the action
+    PicLayerAbstract m_owner = null;
+    
+    /**
+     * Constructor
+     */
+    public SavePictureCalibrationAction( PicLayerAbstract owner ) {
+        super(tr("Save Picture Calibration..."), null, tr("Saves calibration data to a file"), null, false);
+        // Remember the owner...
+        m_owner = owner;
+    }
+    
+    /**
+     * Action handler
+     */
+    public void actionPerformed(ActionEvent arg0) {
+        // Save dialog
+        final JFileChooser fc = new JFileChooser();
+        fc.setAcceptAllFileFilterUsed( false );
+        fc.setFileFilter( new CalibrationFileFilter() );
+        fc.setSelectedFile( new File(m_owner.getPicLayerName() + CalibrationFileFilter.EXTENSION));
+        int result = fc.showSaveDialog( Main.parent );
+
+        if ( result == JFileChooser.APPROVE_OPTION ) {
+            // Check file extension and force it to be valid
+            File file = fc.getSelectedFile();
+            String path = file.getAbsolutePath();
+            if ( path.length() < CalibrationFileFilter.EXTENSION.length()
+                || !path.substring( path.length() - 4 ).equals(CalibrationFileFilter.EXTENSION)) {
+                file = new File( path + CalibrationFileFilter.EXTENSION );
+            }
+                        
+            // Save
+            Properties props = new Properties();
+            m_owner.saveCalibration(props);
+            try {
+                props.store(new FileOutputStream(file), tr("JOSM PicLayer plugin calibration data"));
+            } catch (Exception e) {
+                // Error
+                e.printStackTrace();
+                JOptionPane.showMessageDialog(Main.parent , tr("Saving file failed: {0}", e.getMessage()));
+            }
+        }   
+    }
+}
Index: /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/newlayer/NewLayerFromClipboardAction.java
===================================================================
--- /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/newlayer/NewLayerFromClipboardAction.java	(revision 27120)
+++ /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/newlayer/NewLayerFromClipboardAction.java	(revision 27120)
@@ -0,0 +1,66 @@
+/***************************************************************************
+ *   Copyright (C) 2009 by Tomasz Stelmach                                 *
+ *   http://www.stelmach-online.net/                                       *
+ *                                                                         *
+ *   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; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program 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 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 org.openstreetmap.josm.plugins.piclayer.actions.newlayer;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.event.ActionEvent;
+import java.io.IOException;
+import javax.swing.JOptionPane;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.actions.JosmAction;
+import org.openstreetmap.josm.plugins.piclayer.layer.PicLayerFromClipboard;
+
+/**
+ * Action responsible for creation of a new layer based on
+ * the content of the clipboard.
+ */
+@SuppressWarnings("serial")
+public class NewLayerFromClipboardAction extends JosmAction {
+
+    /**
+     * Constructor...
+     */
+    public NewLayerFromClipboardAction() {
+        super(tr("New picture layer from clipboard"), null, null, null, false);
+    }
+
+    /**
+     * Action handler
+     */
+    public void actionPerformed(ActionEvent arg0) {
+        // Create layer from clipboard
+        PicLayerFromClipboard layer = new PicLayerFromClipboard();
+        // Add layer only if successfully initialized
+        try {
+            layer.initialize();
+        }
+        catch (IOException e) {
+            // Failed
+            System.out.println( "NewLayerFromClipboardAction::actionPerformed - " + e.getMessage() );
+            JOptionPane.showMessageDialog(null, e.getMessage() );
+            return;
+        }
+        // Add layer
+        Main.main.addLayer( layer );
+    }
+}
Index: /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/newlayer/NewLayerFromFileAction.java
===================================================================
--- /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/newlayer/NewLayerFromFileAction.java	(revision 27120)
+++ /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/newlayer/NewLayerFromFileAction.java	(revision 27120)
@@ -0,0 +1,142 @@
+/***************************************************************************
+ *   Copyright (C) 2009 by Tomasz Stelmach                                 *
+ *   http://www.stelmach-online.net/                                       *
+ *                                                                         *
+ *   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; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program 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 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 org.openstreetmap.josm.plugins.piclayer.actions.newlayer;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.event.ActionEvent;
+import java.io.File;
+import java.io.IOException;
+
+import javax.imageio.ImageIO;
+import javax.swing.JFileChooser;
+import javax.swing.JOptionPane;
+import javax.swing.filechooser.FileFilter;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.actions.JosmAction;
+import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
+import org.openstreetmap.josm.gui.layer.Layer;
+import org.openstreetmap.josm.plugins.piclayer.layer.PicLayerFromFile;
+
+/**
+ * Action responsible for creation of new layers based on image files.
+ */
+@SuppressWarnings("serial")
+public class NewLayerFromFileAction extends JosmAction {
+
+    String m_lastdirprefname = "piclayer.lastdir";
+
+    /**
+     * Provides filtering of only image files.
+     */
+    private class ImageFileFilter extends FileFilter {
+
+        @Override
+        public boolean accept(File f) {
+            if ( f.isDirectory() )
+                return true;
+
+            int dotIdx = f.getName().lastIndexOf('.');
+            if (dotIdx == -1) return false;
+            String fileExtension = f.getName().substring(dotIdx+1);
+            String[] supportedExtensions = ImageIO.getReaderFormatNames();
+
+            if ("zip".equalsIgnoreCase(fileExtension)) return true;
+            // Unfortunately, getReaderFormatNames does not always return ALL extensions in 
+            // both lower and upper case, so we can not do a search in the array
+            for (String e: supportedExtensions)
+                if ( e.toLowerCase().equals(fileExtension) ) {
+                    return true;
+                }
+                    
+            return false;
+        }
+
+
+        @Override
+        public String getDescription() {
+            return tr("Supported image files");
+        }
+
+    }
+
+    /**
+     * Constructor...
+     */
+    public NewLayerFromFileAction() {
+        super(tr("New picture layer from file..."), null, null, null, false);
+    }
+
+    /**
+     * Action handler
+     */
+    public void actionPerformed(ActionEvent arg0) {
+
+        // Choose a file
+        JFileChooser fc = new JFileChooser(Main.pref.get(m_lastdirprefname));
+        fc.setAcceptAllFileFilterUsed( false );
+        fc.setFileFilter( new ImageFileFilter() );
+        fc.setMultiSelectionEnabled(true); 
+        int result = fc.showOpenDialog( Main.parent );
+
+        // Create a layer?
+        if ( result == JFileChooser.APPROVE_OPTION ) {
+            // The first loaded layer will be placed at the top of any other layer of the same class,
+            // or at the bottom of the stack if there is no such layer yet
+            // The next layers we load will be placed one after the other after this first layer
+            int newLayerPos = Main.map.mapView.getAllLayers().size();
+            for(Layer l : Main.map.mapView.getLayersOfType(PicLayerFromFile.class)) {
+                int pos = Main.map.mapView.getLayerPos(l);
+                if (pos < newLayerPos) newLayerPos = pos;
+            }
+
+            for(File file : fc.getSelectedFiles() ) {
+                // TODO: we need a progress bar here, it can take quite some time
+                
+                // Create layer from file
+                PicLayerFromFile layer = new PicLayerFromFile( file );
+                // Add layer only if successfully initialized
+                try {
+                    layer.initialize();
+                }
+                catch (IOException e) {
+                    // Failed
+                    System.out.println( "NewLayerFromFileAction::actionPerformed - " + e.getMessage() );
+                    JOptionPane.showMessageDialog(null, e.getMessage() );
+                    return;
+                }
+                Main.pref.put(m_lastdirprefname, file.getParent());
+        
+                Main.main.addLayer( layer );
+                Main.map.mapView.moveLayer(layer, newLayerPos++);
+                
+                if ( fc.getSelectedFiles().length == 1 && Main.pref.getInteger("piclayer.zoom-on-load", 1) != 0 ) {
+                    // if we are loading a single picture file, zoom on it, so that the user can see something
+                    BoundingXYVisitor v = new BoundingXYVisitor();
+                    layer.visitBoundingBox(v);
+                    Main.map.mapView.recalculateCenterScale(v);
+                }
+
+            }
+        }
+    }
+}
Index: /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/MovePictureAction.java
===================================================================
--- /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/MovePictureAction.java	(revision 27120)
+++ /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/MovePictureAction.java	(revision 27120)
@@ -0,0 +1,55 @@
+/***************************************************************************
+ *   Copyright (C) 2009 by Tomasz Stelmach                                 *
+ *   http://www.stelmach-online.net/                                       *
+ *                                                                         *
+ *   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; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program 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 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 org.openstreetmap.josm.plugins.piclayer.actions.transform;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.event.MouseEvent;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.gui.MapFrame;
+import org.openstreetmap.josm.plugins.piclayer.actions.GenericPicTransformAction;
+import org.openstreetmap.josm.tools.ImageProvider;
+import org.openstreetmap.josm.data.coor.EastNorth;
+
+/**
+ * This class handles the input during moving the picture.
+ */
+@SuppressWarnings("serial")
+public class MovePictureAction extends GenericPicTransformAction {
+
+    /**
+     * Constructor
+     */
+    public MovePictureAction(MapFrame frame) {
+        super(tr("PicLayer move"), "move", tr("Drag to move the picture"), frame, ImageProvider.getCursor("crosshair", null));
+    }
+
+	@Override
+	protected void doAction(MouseEvent e) {
+		EastNorth eastNorth = Main.map.mapView.getEastNorth(e.getX(),e.getY());
+        currentLayer.movePictureBy(
+            eastNorth.east() - prevEastNorth.east(),
+            eastNorth.north() - prevEastNorth.north()
+        );
+	}
+
+}
Index: /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/RotatePictureAction.java
===================================================================
--- /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/RotatePictureAction.java	(revision 27120)
+++ /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/RotatePictureAction.java	(revision 27120)
@@ -0,0 +1,57 @@
+/***************************************************************************
+ *   Copyright (C) 2009 by Tomasz Stelmach                                 *
+ *   http://www.stelmach-online.net/                                       *
+ *                                                                         *
+ *   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; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program 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 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 org.openstreetmap.josm.plugins.piclayer.actions.transform;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.event.InputEvent;
+import java.awt.event.MouseEvent;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.gui.MapFrame;
+import org.openstreetmap.josm.plugins.piclayer.actions.GenericPicTransformAction;
+import org.openstreetmap.josm.tools.ImageProvider;
+
+/**
+ * This class handles the input during rotating the picture.
+ */
+@SuppressWarnings("serial")
+public class RotatePictureAction extends GenericPicTransformAction {
+
+    /**
+     * Constructor
+     */
+    public RotatePictureAction(MapFrame frame) {
+        super(tr("PicLayer rotate"), "rotate", tr("Drag to rotate the picture"), frame, ImageProvider.getCursor("crosshair", null));
+    }
+
+	@Override
+	protected void doAction(MouseEvent e) {
+		double factor;
+        if ( ( e.getModifiersEx() & InputEvent.SHIFT_DOWN_MASK ) != 0 ) {
+            factor = Main.pref.getDouble("piclayer.rotatefactors.high_precision", 100.0);
+        }
+        else {
+            factor = Main.pref.getDouble("piclayer.rotatefactors.low_precision", 10.0 );
+        }            
+        currentLayer.rotatePictureBy( ( e.getY() - prevMousePoint.getY() ) / factor );
+	}
+}
Index: /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/ScalePictureActionAbstract.java
===================================================================
--- /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/ScalePictureActionAbstract.java	(revision 27120)
+++ /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/ScalePictureActionAbstract.java	(revision 27120)
@@ -0,0 +1,60 @@
+/***************************************************************************
+ *   Copyright (C) 2009 by Tomasz Stelmach                                 *
+ *   http://www.stelmach-online.net/                                       *
+ *                                                                         *
+ *   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; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program 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 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 org.openstreetmap.josm.plugins.piclayer.actions.transform;
+
+import java.awt.event.InputEvent;
+import java.awt.event.MouseEvent;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.gui.MapFrame;
+import org.openstreetmap.josm.plugins.piclayer.actions.GenericPicTransformAction;
+import org.openstreetmap.josm.tools.ImageProvider;
+
+/**
+ * This class handles the input during scaling the picture.
+ */
+@SuppressWarnings("serial")
+public abstract class ScalePictureActionAbstract extends GenericPicTransformAction {
+
+	/**
+     * Constructor
+     */
+    public ScalePictureActionAbstract (String name, String icon, String tooltip, MapFrame frame) {
+        super(name, icon, tooltip, frame, ImageProvider.getCursor("crosshair", null));
+    }
+
+    protected void doAction(MouseEvent e) {
+        double factor;
+        if ( ( e.getModifiersEx() & InputEvent.SHIFT_DOWN_MASK ) != 0 ) {
+            factor = Main.pref.getDouble("piclayer.scalefactors.high_precision", 1.0005);
+        }
+        else {
+            factor = Main.pref.getDouble("piclayer.scalefactors.low_precision", 1.015);
+        }            
+        doTheScale( Math.pow(factor, prevMousePoint.getY() - e.getY() ) );
+    }
+
+    /**
+     * Does the actual scaling in the inherited class.
+     */
+     protected abstract void doTheScale( double scale );
+
+}
Index: /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/ScaleXPictureAction.java
===================================================================
--- /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/ScaleXPictureAction.java	(revision 27120)
+++ /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/ScaleXPictureAction.java	(revision 27120)
@@ -0,0 +1,43 @@
+/***************************************************************************
+ *   Copyright (C) 2009 by Tomasz Stelmach                                 *
+ *   http://www.stelmach-online.net/                                       *
+ *                                                                         *
+ *   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; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program 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 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 org.openstreetmap.josm.plugins.piclayer.actions.transform;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import org.openstreetmap.josm.gui.MapFrame;
+
+/**
+ * This class handles the input during scaling the picture.
+ */
+@SuppressWarnings("serial")
+public class ScaleXPictureAction extends ScalePictureActionAbstract
+{
+    /*
+     * Constructor
+     */
+    public ScaleXPictureAction(MapFrame frame) {
+        super(tr("PicLayer scale X"), "scale_x", tr("Drag to scale the picture in the X Axis"), frame);
+    }
+
+    public void doTheScale( double scale ) {
+            currentLayer.scalePictureBy( scale, 1.0 );
+        }
+}
Index: /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/ScaleXYPictureAction.java
===================================================================
--- /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/ScaleXYPictureAction.java	(revision 27120)
+++ /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/ScaleXYPictureAction.java	(revision 27120)
@@ -0,0 +1,43 @@
+/***************************************************************************
+ *   Copyright (C) 2009 by Tomasz Stelmach                                 *
+ *   http://www.stelmach-online.net/                                       *
+ *                                                                         *
+ *   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; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program 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 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 org.openstreetmap.josm.plugins.piclayer.actions.transform;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import org.openstreetmap.josm.gui.MapFrame;
+
+/**
+ * This class handles the input during scaling the picture.
+ */
+@SuppressWarnings("serial")
+public class ScaleXYPictureAction extends ScalePictureActionAbstract
+{
+    /*
+     * Constructor
+     */
+    public ScaleXYPictureAction(MapFrame frame) {
+        super(tr("PicLayer scale"), "scale", tr("Drag to scale the picture in the X and Y Axis"), frame);
+    }
+
+    public void doTheScale( double scale ) {
+            currentLayer.scalePictureBy( scale, scale );
+        }
+}
Index: /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/ScaleYPictureAction.java
===================================================================
--- /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/ScaleYPictureAction.java	(revision 27120)
+++ /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/ScaleYPictureAction.java	(revision 27120)
@@ -0,0 +1,43 @@
+/***************************************************************************
+ *   Copyright (C) 2009 by Tomasz Stelmach                                 *
+ *   http://www.stelmach-online.net/                                       *
+ *                                                                         *
+ *   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; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program 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 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 org.openstreetmap.josm.plugins.piclayer.actions.transform;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import org.openstreetmap.josm.gui.MapFrame;
+
+/**
+ * This class handles the input during scaling the picture.
+ */
+@SuppressWarnings("serial")
+public class ScaleYPictureAction extends ScalePictureActionAbstract
+{
+    /*
+     * Constructor
+     */
+    public ScaleYPictureAction(MapFrame frame) {
+        super(tr("PicLayer scale Y"), "scale_y", tr("Drag to scale the picture in the Y Axis"), frame);
+    }
+
+    public void doTheScale( double scale ) {
+        currentLayer.scalePictureBy( 1.0, scale );
+    }
+}
Index: /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/ShearPictureAction.java
===================================================================
--- /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/ShearPictureAction.java	(revision 27120)
+++ /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/ShearPictureAction.java	(revision 27120)
@@ -0,0 +1,57 @@
+/***************************************************************************
+ *                                                                         *
+ *   Copyright (C) 2011 Patrick "Petschge" Kilian, based on code           *
+ *   (c) 2009 by Tomasz Stelmach                                           *
+ *   http://www.stelmach-online.net/                                       *
+ *                                                                         *
+ *   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; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program 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 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 org.openstreetmap.josm.plugins.piclayer.actions.transform;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.event.MouseEvent;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.gui.MapFrame;
+import org.openstreetmap.josm.plugins.piclayer.actions.GenericPicTransformAction;
+import org.openstreetmap.josm.tools.ImageProvider;
+import org.openstreetmap.josm.data.coor.EastNorth;
+
+/**
+ * This class handles the input during shearing of the picture.
+ */
+@SuppressWarnings("serial")
+public class ShearPictureAction extends GenericPicTransformAction {
+
+	/**
+     * Constructor
+     */
+    public ShearPictureAction(MapFrame frame) {
+        super(tr("PicLayer shear"), "shear", tr("Drag to shear the picture"), frame, ImageProvider.getCursor("crosshair", null));
+    }
+
+	@Override
+	protected void doAction(MouseEvent e) {
+        EastNorth eastNorth = Main.map.mapView.getEastNorth(e.getX(),e.getY());
+        currentLayer.shearPictureBy(
+            1000* (eastNorth.east() - prevEastNorth.east()),
+            1000* (eastNorth.north() - prevEastNorth.north())
+        );
+	}
+
+}
Index: /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/affine/MovePointAction.java
===================================================================
--- /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/affine/MovePointAction.java	(revision 27120)
+++ /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/affine/MovePointAction.java	(revision 27120)
@@ -0,0 +1,49 @@
+package org.openstreetmap.josm.plugins.piclayer.actions.transform.affine;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.event.MouseEvent;
+import java.awt.geom.NoninvertibleTransformException;
+import java.awt.geom.Point2D;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.gui.MapFrame;
+import org.openstreetmap.josm.plugins.piclayer.actions.GenericPicTransformAction;
+import org.openstreetmap.josm.tools.ImageProvider;
+
+// old version - ctrl move point (not transforming picture)
+@SuppressWarnings("serial")
+public class MovePointAction extends GenericPicTransformAction {
+
+	public MovePointAction(MapFrame frame) {
+        super(tr("PicLayer Move point"), "movepoint", tr("Drag or create point on the picture"), frame, ImageProvider.getCursor("crosshair", null));
+	}
+
+	@Override
+	protected void doAction(MouseEvent e) {
+		try {
+			Point2D pressed = currentLayer.transformPoint(e.getPoint());
+			if (selectedPoint != null) {
+				currentLayer.getTransformer().replaceOriginPoint(selectedPoint, pressed);
+				selectedPoint = pressed;
+			}
+		} catch (NoninvertibleTransformException e1) {
+			e1.printStackTrace();
+		}
+	}
+	
+	@Override
+	public void mouseClicked(MouseEvent e) {
+		if (currentLayer == null)
+			return;
+		
+		try {
+			Point2D pressed = currentLayer.transformPoint(e.getPoint());
+			if (selectedPoint == null)
+				currentLayer.getTransformer().addOriginPoint(pressed);
+		} catch (NoninvertibleTransformException e1) {
+			e1.printStackTrace();
+		}
+		Main.map.mapView.repaint();
+	}
+}
Index: /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/affine/TransformPointAction.java
===================================================================
--- /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/affine/TransformPointAction.java	(revision 27120)
+++ /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/affine/TransformPointAction.java	(revision 27120)
@@ -0,0 +1,37 @@
+package org.openstreetmap.josm.plugins.piclayer.actions.transform.affine;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.event.MouseEvent;
+import java.awt.geom.NoninvertibleTransformException;
+import java.awt.geom.Point2D;
+
+import javax.swing.JOptionPane;
+
+import org.openstreetmap.josm.gui.MapFrame;
+import org.openstreetmap.josm.plugins.piclayer.actions.GenericPicTransformAction;
+import org.openstreetmap.josm.tools.ImageProvider;
+
+@SuppressWarnings("serial")
+public class TransformPointAction extends GenericPicTransformAction {
+
+	public TransformPointAction(MapFrame frame) {
+		super(tr("PicLayer Transform point"), "transformpoint", tr("Transform point on the picture"), frame, ImageProvider.getCursor("crosshair", null));
+	}
+
+	@Override
+	protected void doAction(MouseEvent e) {
+		try {
+			Point2D pressed = currentLayer.transformPoint(e.getPoint());
+			if (selectedPoint != null) {
+			    if (currentLayer.getTransformer().getOriginPoints().size() < 3)
+			        JOptionPane.showMessageDialog(null, tr("You should have 3 checkpoints to transform the image!"), tr("PicLayer"), JOptionPane.ERROR_MESSAGE, null);
+			    else
+			        currentLayer.getTransformer().updatePair(selectedPoint, pressed);
+			}
+		} catch (NoninvertibleTransformException e1) {
+			e1.printStackTrace();
+		}
+	}
+
+}
Index: /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/layer/CalibrationFileFilter.java
===================================================================
--- /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/layer/CalibrationFileFilter.java	(revision 27120)
+++ /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/layer/CalibrationFileFilter.java	(revision 27120)
@@ -0,0 +1,50 @@
+/***************************************************************************
+ *   Copyright (C) 2009 by Tomasz Stelmach                                 *
+ *   http://www.stelmach-online.net/                                       *
+ *                                                                         *
+ *   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; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program 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 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 org.openstreetmap.josm.plugins.piclayer.layer;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.io.File;
+
+import javax.swing.filechooser.FileFilter;
+
+/**
+ * Filter for the file dialog. Allows only calibration files.
+ */
+public class CalibrationFileFilter extends FileFilter {
+
+    // Extension used by calibration files
+    public static final String EXTENSION = ".cal";
+
+    @Override
+    public boolean accept(File f) {
+        String ext3 = ( f.getName().length() > 4 ) ?  f.getName().substring( f.getName().length() - 4 ).toLowerCase() : "";
+
+        // TODO: check what is supported by Java :)
+        return ( f.isDirectory()
+            ||  ext3.equals( EXTENSION )
+            );
+    }
+
+    @Override
+    public String getDescription() {
+        return tr("Calibration Files")+ " (*" + EXTENSION + ")";
+    }
+}
Index: /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/layer/PicLayerAbstract.java
===================================================================
--- /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/layer/PicLayerAbstract.java	(revision 27120)
+++ /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/layer/PicLayerAbstract.java	(revision 27120)
@@ -0,0 +1,527 @@
+/***************************************************************************
+ *   Copyright (C) 2009 by Tomasz Stelmach                                 *
+ *   http://www.stelmach-online.net/                                       *
+ *                                                                         *
+ *   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; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program 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 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 org.openstreetmap.josm.plugins.piclayer.layer;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.Image;
+import java.awt.Point;
+import java.awt.Toolkit;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.NoninvertibleTransformException;
+import java.awt.geom.Point2D;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.util.Properties;
+
+import javax.swing.Action;
+import javax.swing.Icon;
+import javax.swing.ImageIcon;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.actions.RenameLayerAction;
+import org.openstreetmap.josm.data.Bounds;
+import org.openstreetmap.josm.data.coor.EastNorth;
+import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
+import org.openstreetmap.josm.gui.MapView;
+import org.openstreetmap.josm.gui.layer.Layer;
+import org.openstreetmap.josm.plugins.piclayer.actions.LoadPictureCalibrationAction;
+import org.openstreetmap.josm.plugins.piclayer.actions.ResetCalibrationAction;
+import org.openstreetmap.josm.plugins.piclayer.actions.SavePictureCalibrationAction;
+import org.openstreetmap.josm.plugins.piclayer.transform.PictureTransform;
+import org.openstreetmap.josm.tools.Utils;
+
+/**
+ * Base class for layers showing images. Actually it does all the showing. The
+ * subclasses are supposed only to create images in different ways (load from
+ * files, copy from clipboard, hack into a spy satellite and download them,
+ * anything...)
+ */
+public abstract class PicLayerAbstract extends Layer {
+    // Counter - just for naming of layers
+    private static int imageCounter = 0;
+    // This is the main image to be displayed
+    private Image image = null;
+    private static Image pinImage;
+    // Initial position of the image in the real world
+    private EastNorth initialImagePosition;
+    // Position of the image in the real world
+    private EastNorth imagePosition;
+    // The scale that was set on the map during image creation
+    private double initialImageScale = 1.0;
+    // Layer icon
+    private Icon layerIcon = null;
+
+    private PictureTransform transformer;
+
+    public PictureTransform getTransformer() {
+        return transformer;
+    }
+
+    // Keys for saving in Properties
+    private final String INITIAL_POS_X = "INITIAL_POS_X";
+    private final String INITIAL_POS_Y = "INITIAL_POS_y";
+    private final String POSITION_X = "POSITION_X";
+    private final String POSITION_Y = "POSITION_Y";
+    private final String ANGLE = "ANGLE";
+    private final String INITIAL_SCALE = "INITIAL_SCALE";
+    private final String SCALEX = "SCALEX";
+    private final String SCALEY = "SCALEY";
+    private final String SHEARX = "SHEARX";
+    private final String SHEARY = "SHEARY";
+
+    private final String MATRIXm00 = "M00";
+    private final String MATRIXm01 = "M01";
+    private final String MATRIXm10 = "M10";
+    private final String MATRIXm11 = "M11";
+    private final String MATRIXm02 = "M02";
+    private final String MATRIXm12 = "M12";
+
+    /**
+     * Constructor
+     */
+    public PicLayerAbstract() {
+        super("PicLayer #" + imageCounter);
+
+        //Increase number
+        imageCounter++;
+
+        // Load layer icon
+        layerIcon = new ImageIcon(Toolkit.getDefaultToolkit().createImage(getClass().getResource("/images/layericon.png")));
+
+        if (pinImage == null) {
+            // allow system to load the image and use it in future
+            pinImage = new ImageIcon(Toolkit.getDefaultToolkit().createImage(getClass().getResource("/images/arrow.png"))).getImage();
+        }
+    }
+
+    /**
+     * Initializes the image. Gets the image from a subclass and stores some
+     * initial parameters. Throws exception if something fails.
+     */
+    public void initialize() throws IOException {
+        // First, we initialize the calibration, so that createImage() can rely on it
+
+        // If the map does not exist - we're screwed. We should not get into this situation in the first place!
+        if ( Main.map != null && Main.map.mapView != null ) {
+
+            EastNorth center = Main.map.mapView.getCenter();
+
+            imagePosition = new EastNorth(center.east(), center.north());
+            initialImagePosition = new EastNorth(imagePosition.east(), imagePosition.north());
+            // Initial scale at which the image was loaded
+            initialImageScale = Main.map.mapView.getDist100Pixel();
+        } else {
+            throw new IOException(tr("Could not find the map object."));
+        }
+
+        // Create image
+        image = createImage();
+        if ( image == null ) {
+            throw new IOException(tr("PicLayer failed to load or import the image."));
+        }
+        // Load image completely
+        (new ImageIcon(image)).getImage();
+
+        transformer = new PictureTransform();
+
+        lookForCalibration();
+    }
+
+    /**
+     * To be overridden by subclasses. Provides an image from an external sources.
+     * Throws exception if something does not work.
+     *
+     * TODO: Replace the IOException by our own exception.
+     */
+    protected abstract Image createImage() throws IOException;
+
+    protected abstract void lookForCalibration() throws IOException;
+    /**
+     * To be overridden by subclasses. Returns the user readable name of the layer.
+     */
+    public abstract String getPicLayerName();
+
+    @Override
+    public Icon getIcon() { return layerIcon; }
+
+    @Override
+    public Object getInfoComponent() { return null; }
+
+    @Override
+    public Action[] getMenuEntries() {
+        // Main menu
+        return new Action[] {
+                new ResetCalibrationAction(this, transformer),
+                SeparatorLayerAction.INSTANCE,
+                new SavePictureCalibrationAction(this),
+                new LoadPictureCalibrationAction(this),
+                SeparatorLayerAction.INSTANCE,
+                new RenameLayerAction(null,this),
+        };
+    }
+
+    @Override
+    public String getToolTipText() {
+        return getPicLayerName();
+    }
+
+    @Override
+    public boolean isMergable(Layer arg0) {
+        return false;
+    }
+
+    @Override
+    public void mergeFrom(Layer arg0) {}
+
+    @Override
+    public void paint(Graphics2D g2, MapView mv, Bounds bounds) {
+
+        if ( image != null) {
+
+            // Position image at the right graphical place
+            EastNorth center = Main.map.mapView.getCenter();
+            EastNorth leftop = Main.map.mapView.getEastNorth( 0, 0 );
+            // Number of pixels for one unit in east north space.
+            // This is the same in x- and y- direction.
+            double pixel_per_en = ( Main.map.mapView.getWidth() / 2.0 ) / ( center.east() - leftop.east() );
+
+            //     This is now the offset in screen pixels
+            double pic_offset_x = (( imagePosition.east() - leftop.east() ) * pixel_per_en);
+            double pic_offset_y = (( leftop.north() - imagePosition.north() ) * pixel_per_en);
+
+            Graphics2D g = (Graphics2D)g2.create();
+            // Move
+            g.translate( pic_offset_x, pic_offset_y );
+
+            // Scale
+            double scalex = initialImageScale * pixel_per_en / getMetersPerEasting(imagePosition) / 100;
+            double scaley = initialImageScale * pixel_per_en / getMetersPerNorthing(imagePosition) / 100;
+            g.scale( scalex, scaley );
+
+            g.transform(transformer.getTransform());
+
+            // Draw picture
+            g.drawImage( image, -image.getWidth(null) / 2, -image.getHeight(null) / 2, null );
+
+            // Draw additional rectangle for the active pic layer
+            if ( Main.map.mapView.getActiveLayer() == this ) {
+                g.setColor( new Color( 0xFF0000 ) );
+                g.drawRect(
+                    -image.getWidth(null) / 2,
+                    -image.getHeight(null) / 2,
+                    image.getWidth(null),
+                    image.getHeight(null)
+                );
+            }
+            // draw points for selection
+            Graphics2D gPoints = (Graphics2D)g2.create();
+
+            gPoints.translate(pic_offset_x, pic_offset_y);
+
+            gPoints.setColor(Color.RED); // red color for points output
+
+            AffineTransform tr = AffineTransform.getScaleInstance(scalex, scaley);
+            tr.concatenate(transformer.getTransform());
+
+            for (Point2D p : transformer.getOriginPoints()) {
+               Point2D trP = tr.transform(p, null);
+               int x = (int)trP.getX(), y = (int)trP.getY();
+               gPoints.drawOval(x-2, y-2, 5, 5);
+               gPoints.drawImage(pinImage, x, y, null);
+            }
+
+        } else {
+            // TODO: proper logging
+            System.out.println( "PicLayerAbstract::paint - general drawing error (image is null or Graphics not 2D" );
+        }
+    }
+
+    /**
+     * Returns the distance in meter, that corresponds to one unit in east north
+     * space. For normal projections, it is about 1 (but usually changing with
+     * latitude).
+     * For EPSG:4326, it is the distance from one meridian of full degree to the
+     * next (a couple of kilometers).
+     */
+    private double getMetersPerEasting(EastNorth en) {
+        /* Natural scale in east/north units per pixel.
+         * This means, the projection should be able to handle
+         * a shift of that size in east north space without
+         * going out of bounds.
+         *
+         * Also, this should get us somewhere in the range of meters,
+         * so we get the result at the point 'en' and not some average.
+         */
+        double naturalScale = Main.getProjection().getDefaultZoomInPPD();
+        naturalScale *= 0.01; // make a little smaller
+
+        LatLon ll1 = Main.getProjection().eastNorth2latlon(
+                new EastNorth(en.east() - naturalScale, en.north()));
+        LatLon ll2 = Main.getProjection().eastNorth2latlon(
+                new EastNorth(en.east() + naturalScale, en.north()));
+
+        double dist = ll1.greatCircleDistance(ll2) / naturalScale / 2;
+        return dist;
+    }
+
+    /* see getMetersPerEasting */
+    private double getMetersPerNorthing(EastNorth en) {
+        double naturalScale = Main.getProjection().getDefaultZoomInPPD();
+        naturalScale *= 0.01;
+
+        LatLon ll1 = Main.getProjection().eastNorth2latlon(
+                new EastNorth(en.east(), en.north()- naturalScale));
+        LatLon ll2 = Main.getProjection().eastNorth2latlon(
+                new EastNorth(en.east(), en.north() + naturalScale));
+
+        double dist = ll1.greatCircleDistance(ll2) / naturalScale / 2;
+        return dist;
+    }
+
+    @Override
+    /**
+     * Computes the (rough) bounding box.
+     * We ignore the rotation, the resulting bounding box contains any possible
+     * rotation.
+     */
+    public void visitBoundingBox(BoundingXYVisitor arg0) {
+        if ( image == null )
+            return;
+        String projcode = Main.getProjection().toCode();
+
+        // TODO: bounding box only supported when coordinates are in meters
+        // The reason for that is that this .cal think makes us a hard time.
+        // The position is stored as a raw data (can be either in degrees or
+        // in meters, depending on the projection used at creation), but the
+        // initial scale is in m/100pix
+        // So for now, we support the bounding box only when everything is in meters
+        if (projcode.equals("EPSG:4326") )
+            return;
+
+        EastNorth center = imagePosition;
+        double w = image.getWidth(null);
+        double h = image.getHeight(null);
+        double diag_pix = Math.sqrt(w*w+h*h);
+
+        // initialImageScale is a the scale (unit: m/100pix) at creation time
+        double diag_m = (diag_pix/100) * initialImageScale;
+
+        AffineTransform trans = transformer.getTransform();
+        double factor = Math.max(trans.getScaleX(), trans.getScaleY());
+
+        double offset = factor * diag_m / 2.0;
+
+        EastNorth topleft = center.add(-offset, -offset);
+        EastNorth bottomright = center.add(offset, offset);
+        arg0.visit(topleft);
+        arg0.visit(bottomright);
+    }
+
+    /**
+     * Saves the calibration data into properties structure
+     * @param props Properties to save to
+     */
+    public void saveCalibration( Properties props ) {
+        // Save
+        double[] matrix = new double[6];
+        transformer.getTransform().getMatrix(matrix);
+
+        props.put(MATRIXm00, Double.toString(matrix[0]));
+        props.put(MATRIXm01, Double.toString(matrix[1]));
+        props.put(MATRIXm10, Double.toString(matrix[2]));
+        props.put(MATRIXm11, Double.toString(matrix[3]));
+        props.put(MATRIXm02, Double.toString(matrix[4]));
+        props.put(MATRIXm12, Double.toString(matrix[5]));
+        props.put(POSITION_X, Double.toString(imagePosition.getX()));
+        props.put(POSITION_Y, Double.toString(imagePosition.getY()));
+    }
+
+    /**
+     * Loads calibration data from file
+     * @param file The file to read from
+     * @return
+     */
+    public void loadCalibration(InputStream is) throws IOException {
+        Properties props = new Properties();
+        props.load(is);
+        loadCalibration(props);
+    }
+
+    /**
+     * Loads calibration data from properties structure
+     * @param props Properties to load from
+     * @return
+     */
+    public void loadCalibration( Properties props ) {
+        // Load
+
+        AffineTransform transform;
+
+        if (props.containsKey(INITIAL_POS_X)) {// old format
+            double in_pos_x = Double.valueOf( props.getProperty(INITIAL_POS_X));
+            double in_pos_y = Double.valueOf( props.getProperty(INITIAL_POS_Y));
+            double angle = Double.valueOf( props.getProperty(ANGLE));
+            double in_scale = Double.valueOf( props.getProperty(INITIAL_SCALE));
+            double scale_x = Double.valueOf( props.getProperty(SCALEX));
+            double scale_y = Double.valueOf( props.getProperty(SCALEY));
+            double shear_x = Double.valueOf( props.getProperty(SHEARX));
+            double shear_y = Double.valueOf( props.getProperty(SHEARY));
+
+            initialImagePosition.setLocation(in_pos_x, in_pos_y);
+
+            // transform to matrix from these values - need testing
+            transform = AffineTransform.getRotateInstance(angle);
+            transform.scale(scale_x, scale_y);
+            transform.shear(shear_x, shear_y);
+            initialImageScale = in_scale;
+        } else {
+            double pos_x = Double.valueOf( props.getProperty(POSITION_X));
+            double pos_y = Double.valueOf( props.getProperty(POSITION_Y));
+            imagePosition = new EastNorth(pos_x, pos_y);
+            initialImageScale = 1; //in_scale
+
+            // initialize matrix
+            double[] matrix = new double[6];
+            matrix[0] = Double.parseDouble(props.getProperty(MATRIXm00));
+            matrix[1] = Double.parseDouble(props.getProperty(MATRIXm01));
+            matrix[2] = Double.parseDouble(props.getProperty(MATRIXm10));
+            matrix[3] = Double.parseDouble(props.getProperty(MATRIXm11));
+            matrix[4] = Double.parseDouble(props.getProperty(MATRIXm02));
+            matrix[5] = Double.parseDouble(props.getProperty(MATRIXm12));
+
+            transform = new AffineTransform(matrix);
+        }
+        transformer.resetCalibration();
+        transformer.getTransform().concatenate(transform);
+
+        // Refresh
+        Main.map.mapView.repaint();
+    }
+
+    public void loadWorldfile(InputStream is) throws IOException {
+        BufferedReader br = null;
+        try {
+            Reader reader = new InputStreamReader(is);
+            br = new BufferedReader(reader);
+            double e[] = new double[6];
+            for (int i=0; i<6; ++i) {
+                String line = br.readLine();
+                e[i] = Double.parseDouble(line);
+            }
+            double sx=e[0], ry=e[1], rx=e[2], sy=e[3], dx=e[4], dy=e[5];
+            int w = image.getWidth(null);
+            int h = image.getHeight(null);
+            imagePosition.setLocation(
+                    dx + w/2*sx + h/2*rx,
+                    dy + w/2*ry + h/2*sy
+            );
+            initialImagePosition.setLocation(imagePosition);
+//            m_angle = 0;
+            double scalex = 100*sx*getMetersPerEasting(imagePosition);
+            double scaley = -100*sy*getMetersPerNorthing(imagePosition);
+            double shearx = rx / sx;
+            double sheary = ry / sy;
+
+            transformer.resetCalibration();
+            AffineTransform tr = transformer.getTransform();
+            tr.scale(scalex, scaley);
+            tr.shear(shearx, sheary);
+
+            initialImageScale = 1;
+            Main.map.mapView.repaint();
+        } finally {
+            Utils.close(br);
+        }
+    }
+
+    public Point2D transformPoint(Point p) throws NoninvertibleTransformException {
+        // Position image at the right graphical place
+
+        EastNorth center = Main.map.mapView.getCenter();
+        EastNorth leftop = Main.map.mapView.getEastNorth( 0, 0 );
+        // Number of pixels for one unit in east north space.
+        // This is the same in x- and y- direction.
+        double pixel_per_en = ( Main.map.mapView.getWidth() / 2.0 ) / ( center.east() - leftop.east() );
+
+        //     This is now the offset in screen pixels
+        double pic_offset_x = (( imagePosition.east() - leftop.east() ) * pixel_per_en);
+        double pic_offset_y = (( leftop.north() - imagePosition.north() ) * pixel_per_en); // something bad...
+
+        AffineTransform pointTrans = AffineTransform.getTranslateInstance(pic_offset_x, pic_offset_y);
+
+        double scalex = initialImageScale * pixel_per_en / getMetersPerEasting(imagePosition) / 100;
+        double scaley = initialImageScale * pixel_per_en / getMetersPerNorthing(imagePosition) / 100;
+
+        pointTrans.scale(scalex, scaley); // ok here
+
+        pointTrans.concatenate(transformer.getTransform());
+
+        Point2D result = pointTrans.inverseTransform(p, null);
+        return result;
+    }
+
+    /**
+     * Moves the picture. Scaled in EastNorth...
+     */
+    public void movePictureBy(double x, double y) {
+        imagePosition = imagePosition.add(x, y);
+    }
+
+    public void rotatePictureBy(double angle) {
+        transformer.concatenateTransform(AffineTransform.getRotateInstance(angle));
+    }
+
+    public void scalePictureBy(double scalex, double scaley) {
+        transformer.concatenateTransform(AffineTransform.getScaleInstance(scalex, scaley));
+    }
+
+    public void shearPictureBy(double shx, double shy) {
+        transformer.concatenateTransform(AffineTransform.getShearInstance(shx, shy));
+    }
+
+    public void resetCalibration() {
+        transformer.resetCalibration();
+        imagePosition.setLocation(initialImagePosition);
+    }
+
+    // get image coordinates by mouse coords
+    public Point2D findSelectedPoint(Point point) {
+        if (image == null)
+            return null;
+
+        try {
+            Point2D pressed = transformPoint(point);
+            for (Point2D p : transformer.getOriginPoints())
+                if (p.distance(pressed) <= 4.0) // if user clicked to select some of origin point
+                    return p;
+        } catch (NoninvertibleTransformException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+}
Index: /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/layer/PicLayerFromClipboard.java
===================================================================
--- /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/layer/PicLayerFromClipboard.java	(revision 27120)
+++ /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/layer/PicLayerFromClipboard.java	(revision 27120)
@@ -0,0 +1,72 @@
+/***************************************************************************
+ *   Copyright (C) 2009 by Tomasz Stelmach                                 *
+ *   http://www.stelmach-online.net/                                       *
+ *                                                                         *
+ *   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; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program 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 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 org.openstreetmap.josm.plugins.piclayer.layer;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.Image;
+import java.awt.Toolkit;
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.Transferable;
+import java.awt.datatransfer.UnsupportedFlavorException;
+import java.io.IOException;
+
+/**
+ * Layer displaying a picture copied from the clipboard.
+ */
+public class PicLayerFromClipboard extends PicLayerAbstract {
+
+    @Override
+    protected Image createImage() throws IOException {
+        // Return item
+        Image image = null;
+        // Access the clipboard
+        Transferable t = Toolkit.getDefaultToolkit().getSystemClipboard().getContents(null);
+        // Check result
+        if ( t == null ) {
+            throw new IOException(tr("Nothing in clipboard"));
+        }
+
+        // TODO: Why is it so slow?
+        // Try to make it an image data
+        try {
+            if (t.isDataFlavorSupported(DataFlavor.imageFlavor)) {
+                image = (Image)t.getTransferData(DataFlavor.imageFlavor);
+            } else {
+                throw new IOException(tr("The clipboard data is not an image"));
+            }
+        } catch (UnsupportedFlavorException e) {
+            throw new IOException( e.getMessage() );
+        }
+
+        return image;
+    }
+
+    @Override
+    public String getPicLayerName() {
+        return "Clipboard";
+    }
+
+    @Override
+    protected void lookForCalibration() throws IOException {
+    }
+
+}
Index: /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/layer/PicLayerFromFile.java
===================================================================
--- /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/layer/PicLayerFromFile.java	(revision 27120)
+++ /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/layer/PicLayerFromFile.java	(revision 27120)
@@ -0,0 +1,281 @@
+/***************************************************************************
+ *   Copyright (C) 2009 by Tomasz Stelmach                                 *
+ *   http://www.stelmach-online.net/                                       *
+ *                                                                         *
+ *   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; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program 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 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 org.openstreetmap.josm.plugins.piclayer.layer;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import org.openstreetmap.josm.Main;
+
+import java.awt.Image;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+import javax.imageio.ImageIO;
+import javax.swing.JOptionPane;
+
+import org.openstreetmap.josm.tools.Utils;
+/**
+ * Layer displaying a picture loaded from a file.
+ */
+public class PicLayerFromFile extends PicLayerAbstract {
+
+    // File to load from.
+    private File m_file;
+
+    // whether the file is a zip archive
+    private boolean isZip;
+    // if so, what is the name of the image inside the archive?
+    private String imgNameInZip;
+
+    // Tooltip text
+    private String m_tooltiptext;
+
+    public PicLayerFromFile( File file ) {
+        // Remember the file
+        m_file = file;
+
+        if ("zip".equalsIgnoreCase(getFileExtension(file))) {
+            isZip = true;
+        }
+
+        // Generate tooltip text
+        m_tooltiptext = m_file.getAbsolutePath();
+
+        // Set the name of the layer as the base name of the file
+        setName(m_file.getName());
+    }
+
+    @Override
+    protected Image createImage() throws IOException {
+        // Try to load file
+        Image image = null;
+
+        if (isZip) {
+            ZipFile zipFile = null;
+            try
+            {
+                zipFile = new ZipFile(m_file);
+                ZipEntry imgEntry = null;
+                Enumeration<? extends ZipEntry> entries = zipFile.entries();
+                String[] supportedImageExtensions = ImageIO.getReaderFormatNames();
+
+                while_loop:
+                while (entries.hasMoreElements()) {
+                    ZipEntry entry = entries.nextElement();
+                    for (String extension : supportedImageExtensions) {
+                        if (entry.getName().endsWith("." + extension)) {
+                            imgEntry = entry;
+                            break while_loop;
+                        }
+                    }
+                }
+                if (imgEntry != null) {
+                    imgNameInZip = imgEntry.getName();
+                    InputStream is = null;
+                    try {
+                        is = zipFile.getInputStream(imgEntry);
+                        image = ImageIO.read(is);
+                        return image;
+                    } finally {
+                        Utils.close(is);
+                    }
+                }
+                System.err.println("Warning: no image in zip file found");
+                return null;
+            } catch (Exception e) {
+                System.err.println(tr("Warning: failed to handle zip file ''{0}''. Exception was: {1}", m_file.getName(), e.toString()));
+                return null;
+            } finally {
+                if (zipFile != null) {
+                    try {
+                        zipFile.close();
+                    } catch (IOException ex) {
+                    }
+                }
+            }
+        } else {
+            image = ImageIO.read( m_file );
+            return image;
+        }
+    }
+
+    public enum CalibrationType { CAL, WORLDFILE }
+
+    public static class CalData {
+        public String[] imgExt;
+        public String[] calExt;
+        public CalibrationType type;
+
+        public CalData(String[] imgExt, String[] calExt, CalibrationType type) {
+            this.imgExt = imgExt;
+            this.calExt = calExt;
+            this.type = type;
+        }
+    }
+
+    @Override
+    protected void lookForCalibration() throws IOException {
+        // Manage a potential existing calibration file
+
+        String[][] imgExtensions = new String[][] {
+            { ".jpg", ".jpeg" },
+            { ".png" },
+            { ".tif", ".tiff" },
+            { ".bmp" },
+        };
+        String[][] wldExtensions = new String[][] {
+            { ".wld", ".jgw", ".jpgw" },
+            { ".wld", ".pgw", ".pngw" },
+            { ".wld", ".tfw", ".tifw" },
+            { ".wld", ".bmpw", ".bpw"},
+        };
+
+        if (isZip) {
+            ZipFile zipFile = null;
+            try
+            {
+                zipFile = new ZipFile(m_file);
+                String calFileStr = imgNameInZip + CalibrationFileFilter.EXTENSION;
+                ZipEntry calEntry = zipFile.getEntry(calFileStr);
+                if (calEntry != null) {
+                    if (confirmCalibrationLoading(calFileStr)) {
+                        InputStream is = zipFile.getInputStream(calEntry);
+                        loadCalibration(is);
+                        return;
+                    }
+                } else {
+                    int dotIdx = imgNameInZip.lastIndexOf(".");
+                    if (dotIdx == -1) return;
+                    String extension = imgNameInZip.substring(dotIdx);
+                    String namepart = imgNameInZip.substring(0, dotIdx);
+                    for (int i=0; i<imgExtensions.length; ++i) {
+                        if (Arrays.asList(imgExtensions[i]).contains(extension.toLowerCase())) {
+                            for (String wldExtension : wldExtensions[i]) {
+                                String wldName = namepart+wldExtension;
+                                ZipEntry wldEntry = zipFile.getEntry(wldName);
+                                if (wldEntry != null) {
+                                    if (confirmCalibrationLoading(wldName)) {
+                                        InputStream is = zipFile.getInputStream(wldEntry);
+                                        loadWorldfile(is);
+                                        return;
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            } catch (Exception e) {
+                System.err.println(tr("Warning: failed to handle zip file ''{0}''. Exception was: {1}", m_file.getName(), e.toString()));
+                return;
+            } finally {
+                if (zipFile != null) {
+                    try {
+                        zipFile.close();
+                    } catch (IOException ex) {
+                    }
+                }
+            }
+        } else {
+            File calFile = new File(m_file + CalibrationFileFilter.EXTENSION);
+            if (calFile.exists()) {
+                if (confirmCalibrationLoading(calFile.getName())) {
+                    loadCalibration(new FileInputStream(calFile));
+                }
+            } else {
+                int dotIdx = m_file.getName().lastIndexOf(".");
+                if (dotIdx == -1) return;
+                String extension = m_file.getName().substring(dotIdx);
+                String namepart = m_file.getName().substring(0, dotIdx);
+                for (int i=0; i<imgExtensions.length; ++i) {
+                    if (Arrays.asList(imgExtensions[i]).contains(extension.toLowerCase())) {
+                        for (String wldExtension : wldExtensions[i]) {
+                            File wldFile = new File(m_file.getParentFile(), namepart+wldExtension);
+                            if (wldFile.exists()) {
+                                loadWorldfile(new FileInputStream(wldFile));
+                                return;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    protected boolean confirmCalibrationLoading(String fileName) {
+        String prefkey = "piclayer.autoloadcal";
+        String policy = Main.pref.get(prefkey, "");
+        policy = policy.trim().toLowerCase();
+        boolean loadcal = false;
+
+        String msg = tr("A calibration file associated to the picture file was found: {0}\n", fileName);
+        if ( policy.equals("yes") ) {
+            loadcal = true;
+        }
+        else if ( policy.equals("no") ) {
+            loadcal = false;
+        }
+        else if ( policy.equals("ask") ) {
+            msg += "\n" + tr("Set \"{0}\" to yes/no/ask in the preferences\n"+
+                            "to control the autoloading of calibration files.", prefkey);
+            msg += "\n" + tr("Do you want to apply it ?");
+            int answer = JOptionPane.showConfirmDialog(Main.parent, msg, tr("Load calibration file ?"), JOptionPane.YES_NO_OPTION);
+            if (answer == JOptionPane.YES_OPTION) {
+                loadcal = true;
+            }
+        }
+        else {
+            msg += "\n" + tr("It will be applied automatically.");
+            msg += "\n" + tr("Also, from now on, calibration files will always be loaded automatically.");
+            msg += "\n" + tr("Set \"{0}\" to yes/no/ask in the preferences\n"+
+                            "to control the autoloading of calibration files.", prefkey);
+            // TODO: there should be here a yes/no dialog with a checkbox "do not ask again"
+            JOptionPane.showMessageDialog(Main.parent, msg,
+                "Automatic loading of the calibration", JOptionPane.INFORMATION_MESSAGE);
+            Main.pref.put(prefkey, "yes");
+            loadcal = true;
+        }
+        return loadcal;
+    }
+
+    @Override
+    public String getPicLayerName() {
+        return m_tooltiptext;
+    }
+
+    /**
+     * Get the file extension
+     * @param f the file
+     * @return everything after the last '.'
+     *         the empty string, if there is no extension
+     */
+    public static String getFileExtension(File f) {
+        int dotIdx = f.getName().lastIndexOf('.');
+        if (dotIdx == -1) return "";
+        return f.getName().substring(dotIdx+1);
+    }
+
+}
Index: /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/transform/Matrix3D.java
===================================================================
--- /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/transform/Matrix3D.java	(revision 27120)
+++ /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/transform/Matrix3D.java	(revision 27120)
@@ -0,0 +1,77 @@
+package org.openstreetmap.josm.plugins.piclayer.transform;
+
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Point2D;
+import java.util.List;
+
+
+class Matrix3D {
+	double[][] a;
+	
+	public Matrix3D() {
+		a = new double[3][]; a[0] = new double[3]; a[1] = new double[3]; a[2] = new double[3];
+	}
+	
+	public Matrix3D(PictureTransform pictureTransform, double b11, double b12, double b13, double b21, double b22, double b23, double b31, double b32, double b33) {
+		this();
+		
+		a[0][0] = b11; a[0][1] = b12; a[0][2] = b13;
+		a[1][0] = b21; a[1][1] = b22; a[1][2] = b23;
+		a[2][0] = b31; a[2][1] = b32; a[2][2] = b33;
+	}
+	
+	public Matrix3D(List<? extends Point2D> list) {
+		this();
+		
+		for(int i=0; i<3; i++) {
+			Point2D p = list.get(i);
+			a[0][i] = p.getX();
+			a[1][i] = p.getY();
+			a[2][i] = 1;
+		}
+	}
+
+	public Matrix3D multiply(Matrix3D m) {
+		Matrix3D result = new Matrix3D();
+		for(int i=0; i<3; i++) 
+			for (int j=0; j<3; j++) {
+				double sum = 0;
+				for (int k=0; k<3; k++)
+					sum += a[i][k]*m.a[k][j];
+				result.a[i][j] = sum;
+			}				
+		return result;
+	}
+	
+	private double determinant() {
+		return a[0][0]*(a[1][1]*a[2][2]-a[1][2]*a[2][1])-a[0][1]*(a[1][0]*a[2][2]-a[1][2]*a[2][0])
+		   	+a[0][2]*(a[1][0]*a[2][1]-a[1][1]*a[2][0]);
+	}
+	
+	public Matrix3D inverse() throws NoSolutionException {
+		Matrix3D invert = new Matrix3D();
+		double det = determinant();
+		if (Math.abs(det) <= Double.MIN_VALUE)
+			throw new NoSolutionException("Determinant = 0");
+		
+		double s = 1/det;
+		
+	    invert.a[0][0] = (s) * (a[1][1] * a[2][2] - a[1][2] * a[2][1]);
+	    invert.a[1][0] = (s) * (a[1][2] * a[2][0] - a[1][0] * a[2][2]);
+	    invert.a[2][0] = (s) * (a[1][0] * a[2][1] - a[1][1] * a[2][0]);
+	    invert.a[0][1] = (s) * (a[0][2] * a[2][1] - a[0][1] * a[2][2]);
+	    invert.a[1][1] = (s) * (a[0][0] * a[2][2] - a[0][2] * a[2][0]);
+	    invert.a[2][1] = (s) * (a[0][1] * a[2][0] - a[0][0] * a[2][1]);
+	    invert.a[0][2] = (s) * (a[0][1] * a[1][2] - a[0][2] * a[1][1]);
+	    invert.a[1][2] = (s) * (a[0][2] * a[1][0] - a[0][0] * a[1][2]);
+	    invert.a[2][2] = (s) * (a[0][0] * a[1][1] - a[0][1] * a[1][0]);
+	    
+	    return invert;
+	}
+	
+	public AffineTransform toAffineTransform() throws NoSolutionException {
+		if (!(Math.abs(a[2][0]) <= 1e-2 && Math.abs(a[2][1]) <= 1e-2 && Math.abs(a[2][2]-1) <= 1e-2))
+			throw new NoSolutionException("Resulted matrix is not AF");
+		return new AffineTransform(a[0][0], a[1][0], a[0][1], a[1][1], a[0][2], a[1][2]);
+	}
+}
Index: /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/transform/NoSolutionException.java
===================================================================
--- /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/transform/NoSolutionException.java	(revision 27120)
+++ /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/transform/NoSolutionException.java	(revision 27120)
@@ -0,0 +1,10 @@
+package org.openstreetmap.josm.plugins.piclayer.transform;
+
+class NoSolutionException extends Exception {
+	
+	public NoSolutionException(String message) {
+		super(message);
+	}
+
+	private static final long serialVersionUID = 3170170664858078930L;
+}
Index: /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/transform/PictureTransform.java
===================================================================
--- /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/transform/PictureTransform.java	(revision 27120)
+++ /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/transform/PictureTransform.java	(revision 27120)
@@ -0,0 +1,114 @@
+package org.openstreetmap.josm.plugins.piclayer.transform;
+
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Point2D;
+import java.util.ArrayList;
+import java.util.List;
+
+public class PictureTransform {
+
+	private AffineTransform cachedTransform;
+	
+	private List<Point2D> originPoints;
+	private List<Point2D> desiredPoints;
+	
+	public PictureTransform() {
+		cachedTransform = new AffineTransform();
+		originPoints = new ArrayList<Point2D>(3);
+		desiredPoints = new ArrayList<Point2D>(3);
+	}
+	
+	public AffineTransform getTransform() {
+		return cachedTransform;
+	}
+	
+	public List<? extends Point2D> getOriginPoints() {
+		return originPoints;
+	}
+	
+	public List<? extends Point2D> getDesiredPoints() {
+		return desiredPoints;
+	}
+	
+	public void addDesiredPoint(Point2D picturePoint) {
+		if (desiredPoints.size() < 3)
+			desiredPoints.add(picturePoint);
+		trySolve();
+	}
+	
+	private AffineTransform solveEquation() throws NoSolutionException {
+		Matrix3D X = new Matrix3D(originPoints);
+		Matrix3D Y = new Matrix3D(desiredPoints);
+		Matrix3D result = Y.multiply(X.inverse());
+		
+		return result.toAffineTransform();
+	}
+
+	public void addOriginPoint(Point2D originPoint) {
+		if (originPoints.size() < 3)
+			originPoints.add(originPoint);
+		trySolve();
+	}
+	
+	public void resetCalibration() {
+		originPoints.clear();
+		desiredPoints.clear();
+		cachedTransform = new AffineTransform();
+	}
+
+	private void trySolve() {
+		if (desiredPoints.size() == 3 && originPoints.size() == 3) {
+			try {
+				cachedTransform.concatenate(solveEquation());
+				desiredPoints.clear();
+			} catch (NoSolutionException e) {
+				System.err.println(e.getMessage());
+			}
+		}
+	}
+
+	/** 
+	 * updates pair of points (suppose that other pairs are (origin=>origin) points are the same),
+	 * solves equation, 
+	 * applies transform matrix to the existing cachedTransform
+	 * 
+	 * @param originPoint - should be one of origin points, otherwise - no transform applied
+	 * @param desiredPoint - new place for the point
+	 */
+	public void updatePair(Point2D originPoint, Point2D desiredPoint) {
+		if (originPoints.size() < 3) // not enough information for creating transform - 3 points needed
+			return;
+		
+		if (originPoint == null) 
+			return;
+		
+		desiredPoints.clear();
+		
+		for (Point2D origin : originPoints) {
+			if (origin.equals(originPoint))
+				desiredPoints.add(desiredPoint);
+			else
+				desiredPoints.add(origin);
+		}
+		trySolve();
+	}
+
+	public void replaceOriginPoint(Point2D originPoint, Point2D newOriginPoint) {
+		if (originPoint == null || newOriginPoint == null) 
+			return;
+		
+		int index = originPoints.indexOf(originPoint);
+		if (index < 0) 
+			return;
+		
+		originPoints.set(index, newOriginPoint);
+	}
+	
+	public void concatenateTransform(AffineTransform transform) {
+		cachedTransform.concatenate(transform);
+		for (int i = 0; i < originPoints.size(); i++) {
+			Point2D point = originPoints.get(i);
+			transform.transform(point, point);
+		}
+	}
+}
