Index: applications/editors/josm/plugins/cadastre-fr/src/cadastre_fr/GeorefImage.java
===================================================================
--- applications/editors/josm/plugins/cadastre-fr/src/cadastre_fr/GeorefImage.java	(revision 20198)
+++ applications/editors/josm/plugins/cadastre-fr/src/cadastre_fr/GeorefImage.java	(revision 20211)
@@ -9,7 +9,8 @@
 import java.awt.GraphicsDevice;
 import java.awt.GraphicsEnvironment;
+import java.awt.Image;
 import java.awt.Point;
-import java.awt.Transparency;
 import java.awt.image.BufferedImage;
+import java.awt.image.ImageObserver;
 import java.io.IOException;
 import java.io.ObjectInputStream;
@@ -22,5 +23,5 @@
 import org.openstreetmap.josm.gui.NavigatableComponent;
 
-public class GeorefImage implements Serializable {
+public class GeorefImage implements Serializable, ImageObserver {
     private static final long serialVersionUID = 1L;
 
@@ -35,4 +36,6 @@
     // angle with georeferenced original image after rotation (raster images only)(in radian)
     public double angle = 0;
+    public int imageOriginalHeight = 0;
+    public int imageOriginalWidth = 0;
 
     public BufferedImage image;
@@ -43,4 +46,5 @@
     public GeorefImage(BufferedImage img, EastNorth min, EastNorth max) {
         image = img;
+        
         this.min = min;
         this.max = max;
@@ -53,4 +57,6 @@
         this.orgCroppedRaster[2] = max;
         this.orgCroppedRaster[3] = new EastNorth(max.east(), min.north());
+        this.imageOriginalHeight = img.getHeight();
+        this.imageOriginalWidth = img.getWidth();
         updatePixelPer();
     }
@@ -63,18 +69,17 @@
 
     /**
-     * Recalculate the new bounding box of the image based on the previous [min,max] bbox 
-     * and the new box after rotation [c,d]. 
+     * Recalculate the new bounding box of the image based on the four points provided as parameters. 
      * The new bbox defined in [min.max] will retain the extreme values of both boxes. 
-     * @param oldMin the original box min point, before rotation
-     * @param oldMax the original box max point, before rotation
-     * @param c the new box min point, after rotation
-     * @param d the new box max point, after rotation
-     */
-    private EastNorthBound getNewBounding(EastNorth oldMin, EastNorth oldMax, EastNorth c, EastNorth d) {
+     * @param p1 one of the bounding box corner
+     * @param p2 one of the bounding box corner
+     * @param p3 one of the bounding box corner
+     * @param p4 one of the bounding box corner
+     */
+    private EastNorthBound computeNewBounding(EastNorth p1, EastNorth p2, EastNorth p3, EastNorth p4) {
         EastNorth pt[] = new EastNorth[4];
-        pt[0] = oldMin;
-        pt[1] = oldMax;
-        pt[2] = c;
-        pt[3] = d;
+        pt[0] = p1;
+        pt[1] = p2;
+        pt[2] = p3;
+        pt[3] = p4;
         double smallestEast = Double.MAX_VALUE;
         double smallestNorth = Double.MAX_VALUE;
@@ -109,7 +114,7 @@
             g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, transparency));
         if (drawBoundaries) {
-            g.setColor(Color.green);
             if (orgCroppedRaster == null) {
                 // this is the old cache format where only [min,max] bbox is stored
+                g.setColor(Color.green);
                 g.drawRect(minPt.x, maxPt.y, maxPt.x - minPt.x, minPt.y - maxPt.y);
             } else {
@@ -117,7 +122,20 @@
                 for (int i=0; i<4; i++)
                     croppedPoint[i] = nc.getPoint(orgCroppedRaster[i]);
-                croppedPoint[4] = croppedPoint[0]; 
+                croppedPoint[4] = croppedPoint[0];
+                for (int i=0; i<4; i++) {
+                    g.setColor(Color.green);
+                    g.drawLine(croppedPoint[i].x, croppedPoint[i].y, croppedPoint[i+1].x, croppedPoint[i+1].y);
+                }
+                /* 
+                //Uncomment this section to display the original image size (before cropping)
+                Point[] orgPoint = new Point[5];
                 for (int i=0; i<4; i++)
-                    g.drawLine(croppedPoint[i].x, croppedPoint[i].y, croppedPoint[i+1].x, croppedPoint[i+1].y);
+                    orgPoint[i] = nc.getPoint(orgRaster[i]);
+                orgPoint[4] = orgPoint[0];
+                for (int i=0; i<4; i++) {
+                  g.setColor(Color.red);
+                  g.drawLine(orgPoint[i].x, orgPoint[i].y, orgPoint[i+1].x, orgPoint[i+1].y);
+                }
+                */
             }
         }
@@ -171,9 +189,11 @@
      */
     private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
-        if (WMSLayer.currentFormat == 2 || WMSLayer.currentFormat == 3) {
+        if (WMSLayer.currentFormat >= 2) {
             max = new EastNorth(in.readDouble(), in.readDouble());
             min = new EastNorth(in.readDouble(), in.readDouble());
         }
-        if (WMSLayer.currentFormat == 3) {
+        orgRaster = null;
+        orgCroppedRaster = null;
+        if (WMSLayer.currentFormat >= 3) {
             orgRaster = new EastNorth[4];
             orgCroppedRaster = new EastNorth[4];
@@ -187,9 +207,9 @@
             orgCroppedRaster[2] = new EastNorth(in.readDouble(), in.readDouble());
             orgCroppedRaster[3] = new EastNorth(in.readDouble(), in.readDouble());
-        } else {
-            orgRaster = null;
-            orgCroppedRaster = null;
-            angle = 0;
-        }
+        }
+        if (WMSLayer.currentFormat >= 4) {
+            imageOriginalHeight = in.readInt();
+            imageOriginalWidth =  in.readInt();
+        }        
         image = (BufferedImage) ImageIO.read(ImageIO.createImageInputStream(in));
         updatePixelPer();
@@ -216,4 +236,6 @@
         out.writeDouble(orgCroppedRaster[2].getX()); out.writeDouble(orgCroppedRaster[2].getY());
         out.writeDouble(orgCroppedRaster[3].getX()); out.writeDouble(orgCroppedRaster[3].getY());
+        out.writeInt(imageOriginalHeight);
+        out.writeInt(imageOriginalWidth);
         ImageIO.write(image, "png", ImageIO.createImageOutputStream(out));
     }
@@ -272,33 +294,68 @@
      * Rotate this image and its min/max coordinates around anchor point
      * @param anchor anchor of rotation
-     * @param ang angle of rotation (in radian)
-     */
-    public void rotate(EastNorth anchor, double ang) {
+     * @param old_ang previous angle of image before rotation (0 the first time)(in radian)
+     * @param delta_ang angle of rotation (in radian)
+     */
+    public void rotate(EastNorth anchor, double delta_ang) {
+        if (orgRaster == null || orgCroppedRaster == null)
+            return;
         // rotate the bounding boxes coordinates first
-        EastNorth min2 = new EastNorth(orgRaster[0].east(), orgRaster[2].north());
-        EastNorth max2 = new EastNorth(orgRaster[2].east(), orgRaster[0].north());
         for (int i=0; i<4; i++) {
-            orgRaster[i] = orgRaster[i].rotate(anchor, ang);
-            orgCroppedRaster[i] = orgCroppedRaster[i].rotate(anchor, ang);
-        }
-        min2 = min2.rotate(anchor, ang);
-        max2 = max2.rotate(anchor, ang);
-        EastNorthBound enb = getNewBounding(orgCroppedRaster[0], orgCroppedRaster[2], min2, max2);
-        min = enb.min;
-        max = enb.max;
-        angle=+ang;
-        
+            orgRaster[i] = orgRaster[i].rotate(anchor, delta_ang);
+            orgCroppedRaster[i] = orgCroppedRaster[i].rotate(anchor, delta_ang);
+        }
         // rotate the image now
-        double sin = Math.abs(Math.sin(ang)), cos = Math.abs(Math.cos(ang));
-        int w = image.getWidth(), h = image.getHeight();
-        int neww = (int)Math.floor(w*cos+h*sin), newh = (int)Math.floor(h*cos+w*sin);
+        double sin = Math.abs(Math.sin(angle+delta_ang)), cos = Math.abs(Math.cos(angle+delta_ang));
+        int w = imageOriginalWidth, h = imageOriginalHeight;
+        int neww = (int)Math.floor(w*cos+h*sin);
+        int newh = (int)Math.floor(h*cos+w*sin);
         GraphicsConfiguration gc = getDefaultConfiguration();
-        BufferedImage result = gc.createCompatibleImage(neww, newh, Transparency.TRANSLUCENT);
+        BufferedImage result = gc.createCompatibleImage(neww, newh, image.getTransparency());
         Graphics2D g = result.createGraphics();
-        g.translate((neww-w)/2, (newh-h)/2);
-        g.rotate(ang, w/2, h/2);
+        g.translate((neww-image.getWidth())/2, (newh-image.getHeight())/2);
+        g.rotate(delta_ang, image.getWidth()/2, image.getHeight()/2);
         g.drawRenderedImage(image, null);
         g.dispose();
         image = result;
+        EastNorthBound enb = computeNewBounding(orgCroppedRaster[0], orgCroppedRaster[1], orgCroppedRaster[2], orgCroppedRaster[3]);
+        min = enb.min;
+        max = enb.max;
+        angle+=delta_ang;
+    }
+    
+    /**
+     * Crop the image based on new bbox coordinates adj1 and adj2 (for raster images only).
+     * @param adj1 is the new corner bottom, left
+     * @param adj2 is the new corner top, right
+     */
+    public void crop(EastNorth adj1, EastNorth adj2) {
+        // s1 and s2 have 0,0 at top, left where all EastNorth coord. have 0,0 at bottom, left
+        int sx1 = (int)((adj1.getX() - min.getX())*getPixelPerEast());
+        int sy1 = (int)((max.getY() - adj2.getY())*getPixelPerNorth());
+        int sx2 = (int)((adj2.getX() - min.getX())*getPixelPerEast());
+        int sy2 = (int)((max.getY() - adj1.getY())*getPixelPerNorth());
+        int newWidth = Math.abs(sx2 - sx1);
+        int newHeight = Math.abs(sy2 - sy1);
+        BufferedImage new_img = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_ARGB);
+        Graphics g = new_img.getGraphics();
+        g.drawImage(image, 0, 0, newWidth-1, newHeight-1,
+                sx1, sy1, sx2, sy2,
+                this);
+        image = new_img;
+        this.min = adj1;
+        this.max = adj2;
+        this.orgCroppedRaster[0] = min;
+        this.orgCroppedRaster[1] = new EastNorth(min.east(), max.north());
+        this.orgCroppedRaster[2] = max;
+        this.orgCroppedRaster[3] = new EastNorth(max.east(), min.north());
+        this.imageOriginalWidth = newWidth;
+        this.imageOriginalHeight = newHeight;
+        updatePixelPer();
+    }
+
+    @Override
+    public boolean imageUpdate(Image img, int infoflags, int x, int y,
+            int width, int height) {
+        return false;
     }
 
Index: applications/editors/josm/plugins/cadastre-fr/src/cadastre_fr/WMSAdjustAction.java
===================================================================
--- applications/editors/josm/plugins/cadastre-fr/src/cadastre_fr/WMSAdjustAction.java	(revision 20198)
+++ applications/editors/josm/plugins/cadastre-fr/src/cadastre_fr/WMSAdjustAction.java	(revision 20211)
@@ -86,6 +86,8 @@
         }
         modifiedLayers.clear();
-        selectedLayer.adjustModeEnabled = false;
-        selectedLayer = null;
+        if (selectedLayer != null) {
+            selectedLayer.adjustModeEnabled = false;
+            selectedLayer = null;
+        }
     }
 
Index: applications/editors/josm/plugins/cadastre-fr/src/cadastre_fr/WMSLayer.java
===================================================================
--- applications/editors/josm/plugins/cadastre-fr/src/cadastre_fr/WMSLayer.java	(revision 20198)
+++ applications/editors/josm/plugins/cadastre-fr/src/cadastre_fr/WMSLayer.java	(revision 20211)
@@ -54,7 +54,8 @@
     /**
      * v1 to v2 = not supported
-     * v2 to v3 = add 4 more EastNorth coordinates in GeorefImages 
-     */
-    protected final int serializeFormatVersion = 3;
+     * v2 to v3 = add 4 more EastNorth coordinates in GeorefImages
+     * v3 to v4 = add original raster image width and height
+     */
+    protected final int serializeFormatVersion = 4;
     
     public static int currentFormat;
@@ -535,22 +536,10 @@
         EastNorth adj2 = new EastNorth(en1.east() > en2.east() ? en1.east() : en2.east(),
                 en1.north() > en2.north() ? en1.north() : en2.north());
-        // s1 and s2 have 0,0 at top, left where all EastNorth coord. have 0,0 at bottom, left
-        int sx1 = (int)((adj1.getX() - images.get(0).min.getX())*images.get(0).getPixelPerEast());
-        int sy1 = (int)((images.get(0).max.getY() - adj2.getY())*images.get(0).getPixelPerNorth());
-        int sx2 = (int)((adj2.getX() - images.get(0).min.getX())*images.get(0).getPixelPerEast());
-        int sy2 = (int)((images.get(0).max.getY() - adj1.getY())*images.get(0).getPixelPerNorth());
-        int newWidth = Math.abs(sx2 - sx1);
-        int newHeight = Math.abs(sy2 - sy1);
-        BufferedImage new_img = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_ARGB);
-        Graphics g = new_img.getGraphics();
-        g.drawImage(images.get(0).image, 0, 0, newWidth-1, newHeight-1,
-                sx1, sy1, sx2, sy2,
-                this);
-        images.set(0, new GeorefImage(new_img, adj1, adj2));
-        // important: update the layer georefs !
+        images.get(0).crop(adj1, adj2);
+        // update the layer georefs
         rasterMin = adj1;
         rasterMax = adj2;
+        setCommuneBBox(new EastNorthBound(new EastNorth(0,0), new EastNorth(images.get(0).image.getWidth()-1,images.get(0).image.getHeight()-1)));
         rasterRatio = (rasterMax.getX()-rasterMin.getX())/(communeBBox.max.getX() - communeBBox.min.getX());
-        setCommuneBBox(new EastNorthBound(new EastNorth(0,0), new EastNorth(newWidth-1,newHeight-1)));
     }
 
@@ -581,4 +570,5 @@
     public void displace(double dx, double dy) {
         this.rasterMin = new EastNorth(rasterMin.east() + dx, rasterMin.north() + dy);
+        this.rasterMax = new EastNorth(rasterMax.east() + dx, rasterMax.north() + dy);
         images.get(0).shear(dx, dy);
     }
@@ -586,4 +576,5 @@
     public void resize(EastNorth rasterCenter, double proportion) {
         this.rasterMin = rasterMin.interpolate(rasterCenter, proportion);
+        this.rasterMax = rasterMax.interpolate(rasterCenter, proportion);
         images.get(0).scale(rasterCenter, proportion);
     }
@@ -591,5 +582,8 @@
     public void rotate(EastNorth rasterCenter, double angle) {
         this.rasterMin = rasterMin.rotate(rasterCenter, angle);
+        this.rasterMax = rasterMax.rotate(rasterCenter, angle);
+//        double proportion = dst1.distance(dst2)/org1.distance(org2);
         images.get(0).rotate(rasterCenter, angle);
+        this.angle += angle; 
     }
 
