001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.data.imagery.street_level;
003
004import java.awt.Dimension;
005import java.awt.image.BufferedImage;
006import java.io.File;
007import java.io.IOException;
008import java.time.Instant;
009import java.util.List;
010
011import javax.imageio.IIOParam;
012
013import org.openstreetmap.josm.data.coor.ILatLon;
014import org.openstreetmap.josm.gui.layer.geoimage.ImageViewerDialog;
015
016/**
017 * An interface for image entries that will be shown in {@link org.openstreetmap.josm.gui.layer.geoimage.ImageDisplay}
018 * @author Taylor Smock
019 * @param <I> type of image
020 * @since 18246
021 */
022public interface IImageEntry<I extends IImageEntry<I>> {
023    /**
024     * Select the next image
025     * @param imageViewerDialog The image viewer to update
026     */
027    default void selectNextImage(final ImageViewerDialog imageViewerDialog) {
028        this.selectImage(imageViewerDialog, this.getNextImage());
029    }
030
031    /**
032     * Get what would be the next image
033     * @return The next image
034     */
035    I getNextImage();
036
037    /**
038     * Select the previous image
039     * @param imageViewerDialog The image viewer to update
040     */
041    default void selectPreviousImage(final ImageViewerDialog imageViewerDialog) {
042        this.selectImage(imageViewerDialog, this.getPreviousImage());
043    }
044
045    /**
046     * Get the previous image
047     * @return The previous image
048     */
049    I getPreviousImage();
050
051    /**
052     * Select the first image for the data or sequence
053     * @param imageViewerDialog The image viewer to update
054     */
055    default void selectFirstImage(final ImageViewerDialog imageViewerDialog) {
056        this.selectImage(imageViewerDialog, this.getFirstImage());
057    }
058
059    /**
060     * Get the first image for the data or sequence
061     * @return The first image
062     */
063    I getFirstImage();
064
065    /**
066     * Select the last image for the data or sequence
067     * @param imageViewerDialog The image viewer to update
068     */
069    default void selectLastImage(final ImageViewerDialog imageViewerDialog) {
070        this.selectImage(imageViewerDialog, this.getLastImage());
071    }
072
073    /**
074     * Select a specific image
075     * @param imageViewerDialog The image viewer to update
076     * @param entry The image to select
077     * @since 18290
078     */
079    default void selectImage(final ImageViewerDialog imageViewerDialog, final IImageEntry<?> entry) {
080        imageViewerDialog.displayImage(entry);
081    }
082
083    /**
084     * Get the last image for the data or sequence
085     * @return The last image
086     */
087    I getLastImage();
088
089    /**
090     * Remove the image
091     * @return {@code true} if removal was successful
092     * @throws UnsupportedOperationException If the implementation does not support removal.
093     * Use {@link #isRemoveSupported()}} to check for support.
094     */
095    default boolean remove() {
096        throw new UnsupportedOperationException("remove is not supported for " + this.getClass().getSimpleName());
097    }
098
099    /**
100     * Check if image removal is supported
101     * @return {@code true} if removal is supported
102     */
103    default boolean isRemoveSupported() {
104        return false;
105    }
106
107    /**
108     * Delete the image
109     * @return {@code true} if deletion was successful
110     * @throws UnsupportedOperationException If the implementation does not support deletion.
111     * Use {@link #isDeleteSupported()}} to check for support.
112     * @since 18278
113     */
114    default boolean delete() {
115        throw new UnsupportedOperationException("remove is not supported for " + this.getClass().getSimpleName());
116    }
117
118    /**
119     * Check if image deletion is supported
120     * @return {@code true} if deletion is supported
121     * @since 18278
122     */
123    default boolean isDeleteSupported() {
124        return false;
125    }
126
127    /**
128     * Returns a display name for this entry (shown in image viewer title bar)
129     * @return a display name for this entry
130     */
131    String getDisplayName();
132
133    /**
134     * Reads the image represented by this entry in the given target dimension.
135     * @param target the desired dimension used for {@linkplain IIOParam#setSourceSubsampling subsampling} or {@code null}
136     * @return the read image, or {@code null}
137     * @throws IOException if any I/O error occurs
138     */
139    BufferedImage read(Dimension target) throws IOException;
140
141    /**
142     * Sets the width of this ImageEntry.
143     * @param width set the width of this ImageEntry
144     */
145    void setWidth(int width);
146
147    /**
148     * Sets the height of this ImageEntry.
149     * @param height set the height of this ImageEntry
150     */
151    void setHeight(int height);
152
153    /**
154     * Returns associated file.
155     * @return associated file
156     */
157    File getFile();
158
159    /**
160     * Returns the position value. The position value from the temporary copy
161     * is returned if that copy exists.
162     * @return the position value
163     */
164    ILatLon getPos();
165
166    /**
167     * Returns the speed value. The speed value from the temporary copy is
168     * returned if that copy exists.
169     * @return the speed value
170     */
171    Double getSpeed();
172
173    /**
174     * Returns the elevation value. The elevation value from the temporary
175     * copy is returned if that copy exists.
176     * @return the elevation value
177     */
178    Double getElevation();
179
180    /**
181     * Returns the image direction. The image direction from the temporary
182     * copy is returned if that copy exists.
183     * @return The image camera angle
184     */
185    Double getExifImgDir();
186
187    /**
188     * Convenient way to determine if this entry has a EXIF time, without the cost of building a defensive copy.
189     * @return {@code true} if this entry has a EXIF time
190     * @since 6450
191     */
192    boolean hasExifTime();
193
194    /**
195     * Returns EXIF time
196     * @return EXIF time
197     */
198    Instant getExifInstant();
199
200    /**
201     * Convenient way to determine if this entry has a GPS time, without the cost of building a defensive copy.
202     * @return {@code true} if this entry has a GPS time
203     */
204    boolean hasGpsTime();
205
206    /**
207     * Returns the GPS time value. The GPS time value from the temporary copy
208     * is returned if that copy exists.
209     * @return the GPS time value
210     */
211    Instant getGpsInstant();
212
213    /**
214     * Returns the IPTC caption.
215     * @return the IPTC caption
216     */
217    String getIptcCaption();
218
219    /**
220     * Returns the IPTC headline.
221     * @return the IPTC headline
222     */
223    String getIptcHeadline();
224
225    /**
226     * Returns the IPTC keywords.
227     * @return the IPTC keywords
228     */
229    List<String> getIptcKeywords();
230
231    /**
232     * Returns the IPTC object name.
233     * @return the IPTC object name
234     */
235    String getIptcObjectName();
236
237    /**
238     * Get the camera projection type
239     * @return the camera projection type
240     */
241    default Projections getProjectionType() {
242        return Projections.PERSPECTIVE;
243    }
244}