/***************************************************************************
* 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.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.Main;
/**
* 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) {
try (ZipFile 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();
try (InputStream is = zipFile.getInputStream(imgEntry)) {
return ImageIO.read(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;
}
} 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) {
try (ZipFile 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) {
Main.warn(tr("Warning: failed to handle zip file ''{0}''. Exception was: {1}", m_file.getName(), e.toString()));
return;
}
} 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);
}
}