source: josm/trunk/src/org/openstreetmap/josm/data/gpx/GpxImageEntry.java

Last change on this file was 19427, checked in by stoecker, 10 months ago

fix PMD

  • Property svn:eol-style set to native
File size: 25.5 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.data.gpx;
3
4import java.awt.Dimension;
5import java.awt.image.BufferedImage;
6import java.io.File;
7import java.io.IOException;
8import java.io.InputStream;
9import java.net.URI;
10import java.nio.file.Files;
11import java.time.Instant;
12import java.util.Date;
13import java.util.List;
14import java.util.Objects;
15
16import javax.imageio.IIOParam;
17
18import org.openstreetmap.josm.data.IQuadBucketType;
19import org.openstreetmap.josm.data.coor.CachedLatLon;
20import org.openstreetmap.josm.data.coor.ILatLon;
21import org.openstreetmap.josm.data.coor.LatLon;
22import org.openstreetmap.josm.data.imagery.street_level.Projections;
23import org.openstreetmap.josm.data.osm.BBox;
24import org.openstreetmap.josm.gui.layer.geoimage.ImageMetadata;
25
26/**
27 * Stores info about each image
28 * @since 14205 (extracted from gui.layer.geoimage.ImageEntry)
29 */
30public class GpxImageEntry implements Comparable<GpxImageEntry>, IQuadBucketType, ImageMetadata {
31 private File file;
32 private Integer exifOrientation;
33 private LatLon exifCoor;
34 private Double exifImgDir;
35 private Double exifGpsTrack;
36 private Double exifHPosErr;
37 private Double exifGpsDop;
38 private Instant exifTime;
39 private Projections cameraProjection = Projections.UNKNOWN;
40 /**
41 * Flag isNewGpsData indicates that the GPS data of the image is new or has changed.
42 * GPS data includes the position, speed, elevation, time (e.g. as extracted from the GPS track).
43 * The flag can used to decide for which image file the EXIF GPS data is (re-)written.
44 */
45 private boolean isNewGpsData;
46 /** Temporary source of GPS time if not correlated with GPX track. */
47 private Instant exifGpsTime;
48
49 private String iptcCaption;
50 private String iptcHeadline;
51 private List<String> iptcKeywords;
52 private String iptcObjectName;
53
54 /**
55 * The following values are computed from the correlation with the gpx track
56 * or extracted from the image EXIF data.
57 */
58 private CachedLatLon pos;
59 /** Speed in kilometer per hour */
60 private Double speed;
61 /** Elevation (altitude) in meters */
62 private Double elevation;
63 /** GPS Differential mode */
64 private Integer gpsDiffMode;
65 /** GPS Measure mode */
66 private Integer gps2d3dMode;
67 /** GPS Datum */
68 private String exifGpsDatum;
69 /** GPS processing method */
70 private String exifGpsProcMethod;
71 /** The time after correlation with a gpx track */
72 private Instant gpsTime;
73
74 private int width;
75 private int height;
76
77 /**
78 * When the correlation dialog is open, we like to show the image position
79 * for the current time offset on the map in real time.
80 * On the other hand, when the user aborts this operation, the old values
81 * should be restored. We have a temporary copy, that overrides
82 * the normal values if it is not null. (This may be not the most elegant
83 * solution for this, but it works.)
84 */
85 private GpxImageEntry tmp;
86
87 /**
88 * Constructs a new {@code GpxImageEntry}.
89 */
90 public GpxImageEntry() {}
91
92 /**
93 * Constructs a new {@code GpxImageEntry} from an existing instance.
94 * @param other existing instance
95 * @since 14624
96 */
97 public GpxImageEntry(GpxImageEntry other) {
98 file = other.file;
99 exifOrientation = other.exifOrientation;
100 exifCoor = other.exifCoor;
101 exifImgDir = other.exifImgDir;
102 exifGpsTrack = other.exifGpsTrack;
103 exifHPosErr = other.exifHPosErr;
104 gpsDiffMode = other.gpsDiffMode;
105 gps2d3dMode = other.gps2d3dMode;
106 exifGpsDop = other.exifGpsDop;
107 exifGpsDatum = other.exifGpsDatum;
108 exifGpsProcMethod = other.exifGpsProcMethod;
109 exifTime = other.exifTime;
110 isNewGpsData = other.isNewGpsData;
111 exifGpsTime = other.exifGpsTime;
112 pos = other.pos;
113 speed = other.speed;
114 elevation = other.elevation;
115 gpsTime = other.gpsTime;
116 width = other.width;
117 height = other.height;
118 tmp = other.tmp;
119 }
120
121 /**
122 * Constructs a new {@code GpxImageEntry}.
123 * @param file Path to image file on disk
124 */
125 public GpxImageEntry(File file) {
126 setFile(file);
127 }
128
129 @Override
130 public URI getImageURI() {
131 return this.getFile().toURI();
132 }
133
134 /**
135 * Returns width of the image this GpxImageEntry represents.
136 * @return width of the image this GpxImageEntry represents
137 * @since 13220
138 */
139 @Override
140 public int getWidth() {
141 return width;
142 }
143
144 /**
145 * Returns height of the image this GpxImageEntry represents.
146 * @return height of the image this GpxImageEntry represents
147 * @since 13220
148 */
149 @Override
150 public int getHeight() {
151 return height;
152 }
153
154 /**
155 * Returns the position value. The position value from the temporary copy
156 * is returned if that copy exists.
157 * @return the position value
158 */
159 @Override
160 public CachedLatLon getPos() {
161 if (tmp != null)
162 return tmp.pos;
163 return pos;
164 }
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 @Override
172 public Double getSpeed() {
173 if (tmp != null)
174 return tmp.speed;
175 return speed;
176 }
177
178 /**
179 * Returns the elevation value. The elevation value from the temporary
180 * copy is returned if that copy exists.
181 * @return the elevation value
182 */
183 @Override
184 public Double getElevation() {
185 if (tmp != null)
186 return tmp.elevation;
187 return elevation;
188 }
189
190 /**
191 * Return the GPS Differential mode value. The GPS Differential mode value from the temporary
192 * copy is returned if that copy exists.
193 * @return the differential mode value
194 * @since 19387
195 */
196 @Override
197 public Integer getGpsDiffMode() {
198 if (tmp != null)
199 return tmp.gpsDiffMode;
200 return gpsDiffMode;
201 }
202
203 /**
204 * Return the GPS 2d or 3d mode value. The GPS mode value form the temporary
205 * copy is returned if that copy exists.
206 * @return the GPS 2d/3d mode value
207 * @since 19387
208 */
209 @Override
210 public Integer getGps2d3dMode() {
211 if (tmp != null)
212 return tmp.gps2d3dMode;
213 return gps2d3dMode;
214 }
215
216 /**
217 * Return the GPS DOP value. The GPS DOP value from the temporary
218 * copy is returned if that copy exists.
219 * @return the DOP value
220 * @since 19387
221 */
222 @Override
223 public Double getExifGpsDop() {
224 if (tmp != null)
225 return tmp.exifGpsDop;
226 return exifGpsDop;
227 }
228
229 /**
230 * Return the EXIF GPS coordinates datum value.
231 * @return The datum value
232 * @since 19387
233 */
234 @Override
235 public String getExifGpsDatum() {
236 if (tmp != null)
237 return tmp.exifGpsDatum;
238 return exifGpsDatum;
239 }
240
241 /**
242 * Return the EXIF GPS processing method string
243 * @return the processing method string
244 * @since 19387
245 */
246 @Override
247 public String getExifGpsProcMethod() {
248 if (tmp != null)
249 return tmp.exifGpsProcMethod;
250 return exifGpsProcMethod;
251 }
252
253 /**
254 * Returns the GPS time value. The GPS time value from the temporary copy
255 * is returned if that copy exists.
256 * @return the GPS time value
257 */
258 @Override
259 public Instant getGpsInstant() {
260 return tmp != null ? tmp.gpsTime : gpsTime;
261 }
262
263 /**
264 * Convenient way to determine if this entry has a GPS time, without the cost of building a defensive copy.
265 * @return {@code true} if this entry has a GPS time
266 * @since 6450
267 */
268 @Override
269 public boolean hasGpsTime() {
270 return (tmp != null && tmp.gpsTime != null) || gpsTime != null;
271 }
272
273 /**
274 * Returns associated file.
275 * @return associated file
276 */
277 public File getFile() {
278 return file;
279 }
280
281 /**
282 * Returns a display name for this entry
283 * @return a display name for this entry
284 */
285 @Override
286 public String getDisplayName() {
287 return file == null ? "" : file.getName();
288 }
289
290 /**
291 * Returns EXIF orientation
292 * @return EXIF orientation
293 */
294 @Override
295 public Integer getExifOrientation() {
296 return exifOrientation != null ? exifOrientation : 1;
297 }
298
299 /**
300 * Returns EXIF time
301 * @return EXIF time
302 * @since 17715
303 */
304 @Override
305 public Instant getExifInstant() {
306 return exifTime;
307 }
308
309 /**
310 * Convenient way to determine if this entry has a EXIF time, without the cost of building a defensive copy.
311 * @return {@code true} if this entry has a EXIF time
312 * @since 6450
313 */
314 @Override
315 public boolean hasExifTime() {
316 return exifTime != null;
317 }
318
319 /**
320 * Returns the EXIF GPS time.
321 * @return the EXIF GPS time
322 * @since 17715
323 */
324 @Override
325 public Instant getExifGpsInstant() {
326 return exifGpsTime;
327 }
328
329 /**
330 * Convenient way to determine if this entry has a EXIF GPS time, without the cost of building a defensive copy.
331 * @return {@code true} if this entry has a EXIF GPS time
332 * @since 6450
333 */
334 @Override
335 public boolean hasExifGpsTime() {
336 return exifGpsTime != null;
337 }
338
339 /**
340 * Return the time value selected with the parameter.
341 * @param timeSource the wanted time value, exifCamTime or exifGpsTime
342 * @return exifInstant or exifGpsInstant value
343 * @since 19426
344 */
345 @Override
346 public Instant getTimeSourceInstant(TimeSource timeSource) {
347 if (timeSource == TimeSource.EXIFGPSTIME)
348 return getExifGpsInstant();
349 else if (timeSource == TimeSource.EXIFCAMTIME)
350 return getExifInstant();
351 return null;
352 }
353
354 private static Date getDefensiveDate(Instant date) {
355 if (date == null)
356 return null;
357 return Date.from(date);
358 }
359
360 @Override
361 public LatLon getExifCoor() {
362 return exifCoor;
363 }
364
365 @Override
366 public Double getExifImgDir() {
367 if (tmp != null)
368 return tmp.exifImgDir;
369 return exifImgDir;
370 }
371
372 /**
373 * Convenient way to determine if this entry has a EXIF GPS track angle value,
374 * without the cost of building a defensive copy.
375 * @return {@code true} if this entry has a EXIF track angle value
376 * @since 19387
377 */
378 @Override
379 public Double getExifGpsTrack() {
380 if (tmp != null)
381 return tmp.exifGpsTrack;
382 return exifGpsTrack;
383 }
384
385 /**
386 * Convenient way to determine if this entry has a EXIF GPS horizontal positionning error value,
387 * without the cost of building a defensive copy.
388 * @return {@code true} if this entry has a EXIF GPS horizontal positionning error value
389 * @since 19387
390 */
391 @Override
392 public Double getExifHPosErr() {
393 if (tmp != null)
394 return tmp.exifHPosErr;
395 return exifHPosErr;
396 }
397
398 @Override
399 public Instant getLastModified() {
400 return Instant.ofEpochMilli(this.getFile().lastModified());
401 }
402
403 /**
404 * Sets the width of this GpxImageEntry.
405 * @param width set the width of this GpxImageEntry
406 * @since 13220
407 */
408 @Override
409 public void setWidth(int width) {
410 this.width = width;
411 }
412
413 /**
414 * Sets the height of this GpxImageEntry.
415 * @param height set the height of this GpxImageEntry
416 * @since 13220
417 */
418 @Override
419 public void setHeight(int height) {
420 this.height = height;
421 }
422
423 /**
424 * Sets the position.
425 * @param pos cached position
426 */
427 public void setPos(CachedLatLon pos) {
428 this.pos = pos;
429 }
430
431 /**
432 * Sets the position.
433 * @param pos position (will be cached)
434 */
435 public void setPos(LatLon pos) {
436 setPos(pos != null ? new CachedLatLon(pos) : null);
437 }
438
439 @Override
440 public void setPos(ILatLon pos) {
441 if (pos instanceof CachedLatLon) {
442 this.setPos((CachedLatLon) pos);
443 } else if (pos instanceof LatLon) {
444 this.setPos((LatLon) pos);
445 } else if (pos != null) {
446 this.setPos(new LatLon(pos));
447 } else {
448 this.setPos(null);
449 }
450 }
451
452 /**
453 * Sets the speed.
454 * @param speed speed
455 */
456 @Override
457 public void setSpeed(Double speed) {
458 this.speed = speed;
459 }
460
461 /**
462 * Sets the elevation.
463 * @param elevation elevation
464 */
465 @Override
466 public void setElevation(Double elevation) {
467 this.elevation = elevation;
468 }
469
470 /**
471 * Sets GPS Differential mode.
472 * @param gpsDiffMode GPS Differential mode
473 * @since 19387
474 */
475 @Override
476 public void setGpsDiffMode(Integer gpsDiffMode) {
477 this.gpsDiffMode = gpsDiffMode;
478 }
479
480 /**
481 * Sets GPS 2d/3d mode.
482 * @param gps2d3dMode GPS 2d/3d mode value
483 * @since 19387
484 */
485 @Override
486 public void setGps2d3dMode(Integer gps2d3dMode) {
487 this.gps2d3dMode = gps2d3dMode;
488 }
489
490 /**
491 * Sets GPS DOP value.
492 * @param exifGpsDop GPS DOP value
493 * @since 19387
494 */
495 @Override
496 public void setExifGpsDop(Double exifGpsDop) {
497 this.exifGpsDop = exifGpsDop;
498 }
499
500 /**
501 * Sets the GPS Datum.
502 * @param exifGpsDatum GPS Datum
503 * @since 19387
504 */
505 @Override
506 public void setExifGpsDatum(String exifGpsDatum) {
507 this.exifGpsDatum = exifGpsDatum;
508 }
509
510 /**
511 * Sets the GPS Processing Method.
512 * @param exifGpsProcMethod GPS Processing Method
513 * @since 19387
514 */
515 @Override
516 public void setExifGpsProcMethod(String exifGpsProcMethod) {
517 this.exifGpsProcMethod = exifGpsProcMethod;
518 }
519
520 /**
521 * Sets associated file.
522 * @param file associated file
523 */
524 public void setFile(File file) {
525 this.file = file;
526 }
527
528 /**
529 * Sets EXIF orientation.
530 * @param exifOrientation EXIF orientation
531 */
532 @Override
533 public void setExifOrientation(Integer exifOrientation) {
534 this.exifOrientation = exifOrientation;
535 }
536
537 /**
538 * Sets EXIF time.
539 * @param exifTime EXIF time
540 * @since 17715
541 */
542 @Override
543 public void setExifTime(Instant exifTime) {
544 this.exifTime = exifTime;
545 }
546
547 /**
548 * Sets the EXIF GPS time.
549 * @param exifGpsTime the EXIF GPS time
550 * @since 17715
551 */
552 @Override
553 public void setExifGpsTime(Instant exifGpsTime) {
554 this.exifGpsTime = exifGpsTime;
555 }
556
557 /**
558 * Sets the GPS time.
559 * @param gpsTime the GPS time
560 * @since 17715
561 */
562 @Override
563 public void setGpsTime(Instant gpsTime) {
564 this.gpsTime = gpsTime;
565 }
566
567 /**
568 * Sets the EXIF coordinate.
569 * @param exifCoor the coordinate
570 */
571 public void setExifCoor(LatLon exifCoor) {
572 this.exifCoor = exifCoor;
573 }
574
575 @Override
576 public void setExifCoor(ILatLon exifCoor) {
577 if (exifCoor instanceof LatLon) {
578 this.exifCoor = (LatLon) exifCoor;
579 } else if (exifCoor != null) {
580 this.exifCoor = new LatLon(exifCoor);
581 } else {
582 this.exifCoor = null;
583 }
584 }
585
586 @Override
587 public void setExifImgDir(Double exifDir) {
588 this.exifImgDir = exifDir;
589 }
590
591 /**
592 * Sets the EXIF GPS track (move direction angle)
593 * @param exifGpsTrack the EXIF GPS track angle
594 * @since 19387
595 */
596 @Override
597 public void setExifGpsTrack(Double exifGpsTrack) {
598 this.exifGpsTrack = exifGpsTrack;
599 }
600
601 /**
602 * Sets the EXIF horizontal positioning error
603 * @param exifHPosErr the EXIF horizontal positionning error
604 * @since 19387
605 */
606 @Override
607 public void setExifHPosErr(Double exifHPosErr) {
608 this.exifHPosErr = exifHPosErr;
609 }
610
611 /**
612 * Sets the IPTC caption.
613 * @param iptcCaption the IPTC caption
614 * @since 15219
615 */
616 @Override
617 public void setIptcCaption(String iptcCaption) {
618 this.iptcCaption = iptcCaption;
619 }
620
621 /**
622 * Sets the IPTC headline.
623 * @param iptcHeadline the IPTC headline
624 * @since 15219
625 */
626 @Override
627 public void setIptcHeadline(String iptcHeadline) {
628 this.iptcHeadline = iptcHeadline;
629 }
630
631 /**
632 * Sets the IPTC keywords.
633 * @param iptcKeywords the IPTC keywords
634 * @since 15219
635 */
636 @Override
637 public void setIptcKeywords(List<String> iptcKeywords) {
638 this.iptcKeywords = iptcKeywords;
639 }
640
641 /**
642 * Sets the IPTC object name.
643 * @param iptcObjectName the IPTC object name
644 * @since 15219
645 */
646 @Override
647 public void setIptcObjectName(String iptcObjectName) {
648 this.iptcObjectName = iptcObjectName;
649 }
650
651 /**
652 * Returns the IPTC caption.
653 * @return the IPTC caption
654 * @since 15219
655 */
656 @Override
657 public String getIptcCaption() {
658 return iptcCaption;
659 }
660
661 /**
662 * Returns the IPTC headline.
663 * @return the IPTC headline
664 * @since 15219
665 */
666 @Override
667 public String getIptcHeadline() {
668 return iptcHeadline;
669 }
670
671 /**
672 * Returns the IPTC keywords.
673 * @return the IPTC keywords
674 * @since 15219
675 */
676 @Override
677 public List<String> getIptcKeywords() {
678 return iptcKeywords;
679 }
680
681 /**
682 * Returns the IPTC object name.
683 * @return the IPTC object name
684 * @since 15219
685 */
686 @Override
687 public String getIptcObjectName() {
688 return iptcObjectName;
689 }
690
691 @Override
692 public int compareTo(GpxImageEntry image) {
693 if (exifTime != null && image.exifTime != null)
694 return exifTime.compareTo(image.exifTime);
695 else if (exifTime == null && image.exifTime == null)
696 return 0;
697 else if (exifTime == null)
698 return -1;
699 else
700 return 1;
701 }
702
703 @Override
704 public int hashCode() {
705 return Objects.hash(height, width, isNewGpsData,
706 elevation, exifCoor, exifGpsTime, exifImgDir, exifGpsTrack, exifHPosErr,
707 exifGpsDop, gpsDiffMode, gps2d3dMode, exifGpsDatum, exifGpsProcMethod,
708 exifOrientation, exifTime, iptcCaption, iptcHeadline, iptcKeywords,
709 iptcObjectName, file, gpsTime, pos, speed, tmp, cameraProjection);
710 }
711
712 @Override
713 public boolean equals(Object obj) {
714 if (this == obj)
715 return true;
716 if (obj == null || getClass() != obj.getClass())
717 return false;
718 GpxImageEntry other = (GpxImageEntry) obj;
719 return height == other.height
720 && width == other.width
721 && isNewGpsData == other.isNewGpsData
722 && Objects.equals(elevation, other.elevation)
723 && Objects.equals(exifCoor, other.exifCoor)
724 && Objects.equals(exifGpsTime, other.exifGpsTime)
725 && Objects.equals(exifImgDir, other.exifImgDir)
726 && Objects.equals(exifGpsTrack, other.exifGpsTrack)
727 && Objects.equals(exifHPosErr, other.exifHPosErr)
728 && Objects.equals(gpsDiffMode, other.gpsDiffMode)
729 && Objects.equals(gps2d3dMode, other.gps2d3dMode)
730 && Objects.equals(exifGpsDop, other.exifGpsDop)
731 && Objects.equals(exifGpsDatum, other.exifGpsDatum)
732 && Objects.equals(exifGpsProcMethod, other.exifGpsProcMethod)
733 && Objects.equals(exifOrientation, other.exifOrientation)
734 && Objects.equals(exifTime, other.exifTime)
735 && Objects.equals(iptcCaption, other.iptcCaption)
736 && Objects.equals(iptcHeadline, other.iptcHeadline)
737 && Objects.equals(iptcKeywords, other.iptcKeywords)
738 && Objects.equals(iptcObjectName, other.iptcObjectName)
739 && Objects.equals(file, other.file)
740 && Objects.equals(gpsTime, other.gpsTime)
741 && Objects.equals(pos, other.pos)
742 && Objects.equals(speed, other.speed)
743 && Objects.equals(tmp, other.tmp)
744 && cameraProjection == other.cameraProjection;
745 }
746
747 /**
748 * Make a fresh copy and save it in the temporary variable. Use
749 * {@link #applyTmp()} or {@link #discardTmp()} if the temporary variable
750 * is not needed anymore.
751 * @return the fresh copy.
752 */
753 public GpxImageEntry createTmp() {
754 tmp = new GpxImageEntry(this);
755 tmp.tmp = null;
756 return tmp;
757 }
758
759 /**
760 * Get temporary variable that is used for real time parameter
761 * adjustments. The temporary variable is created if it does not exist
762 * yet. Use {@link #applyTmp()} or {@link #discardTmp()} if the temporary
763 * variable is not needed anymore.
764 * @return temporary variable
765 */
766 public GpxImageEntry getTmp() {
767 if (tmp == null) {
768 createTmp();
769 }
770 return tmp;
771 }
772
773 /**
774 * Copy the values from the temporary variable to the main instance. The
775 * temporary variable is deleted.
776 * @see #discardTmp()
777 * @since 19387 exifGpsTrack, exifHPosErr, gpsDiffMode, gps2d3dMode, exifGpsDop, exifGpsDatum, exifGpsProcMethod added
778 */
779 public void applyTmp() {
780 if (tmp != null) {
781 pos = tmp.pos;
782 speed = tmp.speed;
783 elevation = tmp.elevation;
784 gpsTime = tmp.gpsTime;
785 exifImgDir = tmp.exifImgDir;
786 exifGpsTrack = tmp.exifGpsTrack;
787 exifHPosErr = tmp.exifHPosErr;
788 gpsDiffMode = tmp.gpsDiffMode;
789 gps2d3dMode = tmp.gps2d3dMode;
790 exifGpsDop = tmp.exifGpsDop;
791 exifGpsDatum = tmp.exifGpsDatum;
792 exifGpsProcMethod = tmp.exifGpsProcMethod;
793 isNewGpsData = isNewGpsData || tmp.isNewGpsData;
794 tmp = null;
795 }
796 tmpUpdated();
797 }
798
799 /**
800 * Delete the temporary variable. Temporary modifications are lost.
801 * @see #applyTmp()
802 */
803 public void discardTmp() {
804 tmp = null;
805 tmpUpdated();
806 }
807
808 /**
809 * If it has been tagged i.e. matched to a gpx track or retrieved lat/lon from exif
810 * @return {@code true} if it has been tagged
811 */
812 public boolean isTagged() {
813 return pos != null;
814 }
815
816 /**
817 * String representation. (only partial info)
818 */
819 @Override
820 public String toString() {
821 return file.getName()+": "+
822 "pos = "+pos+" | "+
823 "exifCoor = "+exifCoor+" | "+
824 (tmp == null ? " tmp==null" :
825 " [tmp] pos = "+tmp.pos);
826 }
827
828 /**
829 * Indicates that the image has new GPS data.
830 * That flag is set by new GPS data providers. It is used e.g. by the photo_geotagging plugin
831 * to decide for which image file the EXIF GPS data needs to be (re-)written.
832 * @since 6392
833 */
834 public void flagNewGpsData() {
835 isNewGpsData = true;
836 }
837
838 /**
839 * Indicate that the temporary copy has been updated. Mostly used to prevent UI issues.
840 * By default, this is a no-op. Override when needed in subclasses.
841 * @since 17579
842 */
843 protected void tmpUpdated() {
844 // No-op by default
845 }
846
847 @Override
848 public BBox getBBox() {
849 // new BBox(LatLon) is null safe.
850 // Use `getPos` instead of `getExifCoor` since the image may be correlated against a GPX track
851 return new BBox(this.getPos());
852 }
853
854 /**
855 * Remove the flag that indicates new GPS data.
856 * The flag is cleared by a new GPS data consumer.
857 */
858 public void unflagNewGpsData() {
859 isNewGpsData = false;
860 }
861
862 /**
863 * Queries whether the GPS data changed. The flag value from the temporary
864 * copy is returned if that copy exists.
865 * @return {@code true} if GPS data changed, {@code false} otherwise
866 * @since 6392
867 */
868 public boolean hasNewGpsData() {
869 if (tmp != null)
870 return tmp.isNewGpsData;
871 return isNewGpsData;
872 }
873
874 /**
875 * Extract GPS metadata from image EXIF. Has no effect if the image file is not set
876 *
877 * If successful, fills in the LatLon, speed, elevation, image direction, and other attributes
878 * @since 9270
879 */
880 @Override
881 public void extractExif() {
882 ImageMetadata.super.extractExif();
883 }
884
885 @Override
886 public InputStream getInputStream() throws IOException {
887 return Files.newInputStream(this.getFile().toPath());
888 }
889
890 /**
891 * Reads the image represented by this entry in the given target dimension.
892 * @param target the desired dimension used for {@linkplain IIOParam#setSourceSubsampling subsampling} or {@code null}
893 * @return the read image, or {@code null}
894 * @throws IOException if any I/O error occurs
895 * @since 18246
896 */
897 public BufferedImage read(Dimension target) throws IOException {
898 throw new UnsupportedOperationException("read not implemented for " + this.getClass().getSimpleName());
899 }
900
901 /**
902 * Get the projection type for this entry
903 * @return The projection type
904 * @since 18246
905 */
906 @Override
907 public Projections getProjectionType() {
908 return this.cameraProjection;
909 }
910
911 @Override
912 public void setProjectionType(Projections newProjection) {
913 this.cameraProjection = newProjection;
914 }
915
916 /**
917 * Returns a {@link WayPoint} representation of this GPX image entry.
918 * @return a {@code WayPoint} representation of this GPX image entry (containing position, instant and elevation)
919 * @since 18065
920 */
921 public WayPoint asWayPoint() {
922 CachedLatLon position = getPos();
923 WayPoint wpt = null;
924 if (position != null) {
925 wpt = new WayPoint(position);
926 wpt.setInstant(exifTime);
927 Double ele = getElevation();
928 if (ele != null) {
929 wpt.put(GpxConstants.PT_ELE, ele.toString());
930 }
931 }
932 return wpt;
933 }
934}
Note: See TracBrowser for help on using the repository browser.