001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.plugins.streetside; 003 004import java.awt.image.BufferedImage; 005import java.io.File; 006import java.io.IOException; 007import java.text.ParseException; 008import java.util.Calendar; 009 010import javax.imageio.ImageIO; 011 012import org.openstreetmap.josm.data.coor.CachedLatLon; 013import org.openstreetmap.josm.data.coor.LatLon; 014import org.openstreetmap.josm.gui.MapView; 015import org.openstreetmap.josm.gui.layer.geoimage.GeoImageLayer; 016import org.openstreetmap.josm.gui.layer.geoimage.ImageEntry; 017import org.openstreetmap.josm.plugins.streetside.cubemap.CubemapUtils; 018import org.openstreetmap.josm.plugins.streetside.utils.StreetsideUtils; 019 020/** 021 * A StreetsideImoprtedImage object represents a picture imported locally. 022 * 023 * @author nokutu 024 * 025 */ 026public class StreetsideImportedImage extends StreetsideAbstractImage { 027 028 /** The picture file. */ 029 protected File file; 030 031 /** 032 * Creates a new StreetsideImportedImage object using as date the current date. 033 * Using when the EXIF tags doesn't contain that info. 034 * 035 * @param id The Streetside image id 036 * @param latLon The latitude and longitude where the picture was taken. 037 * @param ca Direction of the picture (0 means north). 038 * @param file The file containing the picture. 039 */ 040 public StreetsideImportedImage(final String id, final LatLon latLon, final double ca, final File file) { 041 this(id, latLon, ca, file, Calendar.getInstance().getTimeInMillis()); 042 } 043 044 /** 045 * Main constructor of the class. 046 * 047 * @param id The Streetside image id 048 * @param latLon Latitude and Longitude where the picture was taken. 049 * @param ca Direction of the picture (0 means north), 050 * @param file The file containing the picture. 051 * @param datetimeOriginal The date the picture was taken. 052 */ 053 public StreetsideImportedImage(final String id, final LatLon latLon, final double ca, final File file, final String datetimeOriginal) { 054 this(id, latLon, ca, file, parseTimestampElseCurrentTime(datetimeOriginal)); 055 } 056 057 /** 058 * Constructs a new image from an image entry of a {@link GeoImageLayer}. 059 * @param geoImage the {@link ImageEntry}, from which the corresponding fields are taken 060 * @return new image 061 */ 062 public static StreetsideImportedImage createInstance(final ImageEntry geoImage) { 063 if (geoImage == null) { 064 return null; 065 } 066 if (geoImage.getFile() == null) { 067 throw new IllegalArgumentException("Can't create an imported image from an ImageEntry without associated file."); 068 } 069 final CachedLatLon cachedCoord = geoImage.getPos(); 070 LatLon coord = cachedCoord == null ? null : cachedCoord.getRoundedToOsmPrecision(); 071 if (coord == null) { 072 final MapView mv = StreetsidePlugin.getMapView(); 073 coord = mv == null ? new LatLon(0, 0) : mv.getProjection().eastNorth2latlon(mv.getCenter()); 074 } 075 final double ca = geoImage.getExifImgDir() == null ? 0 : geoImage.getExifImgDir(); 076 final long time = geoImage.hasGpsTime() 077 ? geoImage.getGpsTime().getTime() 078 : geoImage.hasExifTime() ? geoImage.getExifTime().getTime() : System.currentTimeMillis(); 079 return new StreetsideImportedImage(CubemapUtils.IMPORTED_ID, coord, ca, geoImage.getFile(), time); 080 } 081 082 private static long parseTimestampElseCurrentTime(final String timestamp) { 083 try { 084 return StreetsideUtils.getEpoch(timestamp, "yyyy:MM:dd HH:mm:ss"); 085 } catch (ParseException e) { 086 try { 087 return StreetsideUtils.getEpoch(timestamp, "yyyy/MM/dd HH:mm:ss"); 088 } catch (ParseException e1) { 089 return StreetsideUtils.currentTime(); 090 } 091 } 092 } 093 094 public StreetsideImportedImage(final String id, final LatLon latLon, final double he, final File file, final long ca) { 095 super(id, latLon, he); 096 this.file = file; 097 this.cd = ca; 098 } 099 100 /** 101 * Returns the pictures of the file. 102 * 103 * @return A {@link BufferedImage} object containing the picture, or null if 104 * the {@link File} given in the constructor was null. 105 * @throws IOException 106 * If the file parameter of the object isn't an image. 107 */ 108 public BufferedImage getImage() throws IOException { 109 if (file != null) 110 return ImageIO.read(file); 111 return null; 112 } 113 114 /** 115 * Returns the {@link File} object where the picture is located. 116 * 117 * @return The {@link File} object where the picture is located. 118 */ 119 public File getFile() { 120 return file; 121 } 122 123 @Override 124 public int compareTo(StreetsideAbstractImage image) { 125 if (image instanceof StreetsideImportedImage) 126 return file.compareTo(((StreetsideImportedImage) image).getFile()); 127 return hashCode() - image.hashCode(); 128 } 129 130 @Override 131 public int hashCode() { 132 final int prime = 31; 133 int result = 1; 134 result = prime * result + ((file == null) ? 0 : file.hashCode()); 135 return result; 136 } 137 138 @Override 139 public boolean equals(Object obj) { 140 if (this == obj) { 141 return true; 142 } 143 if (obj == null) { 144 return false; 145 } 146 if (!(obj instanceof StreetsideImportedImage)) { 147 return false; 148 } 149 StreetsideImportedImage other = (StreetsideImportedImage) obj; 150 if (file == null) { 151 if (other.file != null) { 152 return false; 153 } 154 } else if (!file.equals(other.file)) { 155 return false; 156 } 157 return true; 158 } 159}