Index: /applications/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 26497)
+++ /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/LoadPictureCalibrationAction.java	(revision 26498)
@@ -73,5 +73,5 @@
             // Load 
             try {
-                m_owner.loadCalibration(fc.getSelectedFile());
+                m_owner.loadCalibration(new FileInputStream(fc.getSelectedFile()));
             } catch (Exception e) {
                 // Error
Index: /applications/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 26497)
+++ /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/NewLayerFromFileAction.java	(revision 26498)
@@ -54,7 +54,10 @@
                 return true;
 
-            String fileExtension = f.getName().substring(f.getName().lastIndexOf('.')+1);
+            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
Index: /applications/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 26497)
+++ /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/PicLayerAbstract.java	(revision 26498)
@@ -34,4 +34,7 @@
 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;
@@ -51,4 +54,5 @@
 import org.openstreetmap.josm.gui.MapView;
 import org.openstreetmap.josm.gui.layer.Layer;
+import org.openstreetmap.josm.tools.Utils;
 
 /**
@@ -406,7 +410,7 @@
      * @return
      */
-    public void loadCalibration(File file) throws IOException {
+    public void loadCalibration(InputStream is) throws IOException {
         Properties props = new Properties();
-        props.load(new FileInputStream(file));
+        props.load(is);
         loadCalibration(props);
     }
@@ -441,27 +445,32 @@
     }
     
-    public void loadWorldfile(File file) throws IOException {
-        FileReader reader = new FileReader(file);
-        BufferedReader 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();
+    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);
+        }
     }
 
Index: /applications/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 26497)
+++ /applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/PicLayerFromFile.java	(revision 26498)
@@ -27,8 +27,16 @@
 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.
@@ -38,4 +46,10 @@
     // 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;
@@ -45,99 +59,205 @@
         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());
     }
 
-    protected String getFilePath() {
-        return m_file.getAbsolutePath();
-    }
-
-    public File getDefaultCalPath() {
-        File calFile = new File(m_file + CalibrationFileFilter.EXTENSION);
-        return calFile;
-    }
-    
     @Override
     protected Image createImage() throws IOException {
         // Try to load file
         Image image = null;
-        image = ImageIO.read( m_file );
-        return image;
-    }
-    
+
+        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
-        File calFile = getDefaultCalPath();
-        if ( calFile.exists() ) {
-            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:")+"\n"+calFile.getName();
-            if ( policy.equals("yes") ) {
+
+        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:")+"\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 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, frow now on, cal 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;
-            }
-            if ( loadcal )
-                loadCalibration(calFile);
-        } else {
-            
-            // try to find and load world file
-            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);
-            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"},
-            };
-            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()) {
-                            System.out.println("Loading world file: "+wldFile);
-                            loadWorldfile(wldFile);
-                            return;
-                        }
-                    }
-                }
-            }
-        }
+        }
+        else {
+            msg += "\n" + tr("It will be applied automatically.");
+            msg += "\n" + tr("Also, frow now on, cal 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;
     }
 
@@ -146,3 +266,16 @@
         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);
+    }
+
 }
