/
data.go
148 lines (129 loc) Β· 6.38 KB
/
data.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
package meta
import (
"math"
"time"
"github.com/photoprism/photoprism/pkg/media"
"github.com/photoprism/photoprism/pkg/rnd"
"github.com/photoprism/photoprism/pkg/s2"
)
const (
ImageTypeHDR = 3 // see https://exiftool.org/TagNames/Apple.html
)
// Data represents image metadata.
type Data struct {
FileName string `meta:"FileName"`
MimeType string `meta:"MIMEType" report:"-"`
DocumentID string `meta:"ContentIdentifier,MediaGroupUUID,BurstUUID,OriginalDocumentID,DocumentID,ImageUniqueID,DigitalImageGUID"` // see https://exiftool.org/forum/index.php?topic=14874.0
InstanceID string `meta:"InstanceID,DocumentID"`
CreatedAt time.Time `meta:"SubSecCreateDate,CreationDate,CreateDate,MediaCreateDate,ContentCreateDate,TrackCreateDate"`
TakenAt time.Time `meta:"SubSecDateTimeOriginal,SubSecDateTimeCreated,DateTimeOriginal,CreationDate,DateTimeCreated,DateTime,DateTimeDigitized" xmp:"DateCreated"`
TakenAtLocal time.Time `meta:"SubSecDateTimeOriginal,SubSecDateTimeCreated,DateTimeOriginal,CreationDate,DateTimeCreated,DateTime,DateTimeDigitized"`
TakenGps time.Time `meta:"GPSDateTime,GPSDateStamp"`
TakenNs int `meta:"-"`
TimeZone string `meta:"-"`
TimeOffset string `meta:"OffsetTime,OffsetTimeOriginal,OffsetTimeDigitized"`
MediaType media.Type `meta:"-"`
HasThumbEmbedded bool `meta:"ThumbnailImage,PhotoshopThumbnail" report:"-"`
HasVideoEmbedded bool `meta:"EmbeddedVideoFile,MotionPhoto,MotionPhotoVideo,MicroVideo" report:"-"`
Duration time.Duration `meta:"Duration,MediaDuration,TrackDuration,PreviewDuration"`
FPS float64 `meta:"VideoFrameRate,VideoAvgFrameRate"`
Frames int `meta:"FrameCount,AnimationFrames"`
Codec string `meta:"CompressorID,VideoCodecID,CodecID,OtherFormat,FileType"`
Title string `meta:"Title,Headline" xmp:"dc:title" dc:"title,title.Alt"`
Description string `meta:"Description,ImageDescription,Caption,Caption-Abstract" xmp:"Description,Description.Alt"`
Subject string `meta:"Subject,PersonInImage,ObjectName,HierarchicalSubject,CatalogSets" xmp:"Subject"`
Keywords Keywords `meta:"Keywords"`
Favorite bool `meta:"Favorite"`
Notes string `meta:"Comment,UserComment"`
Artist string `meta:"Artist,Creator,By-line,OwnerName,Owner" xmp:"Creator"`
Copyright string `meta:"Rights,Copyright,CopyrightNotice,WebStatement" xmp:"Rights,Rights.Alt"`
License string `meta:"UsageTerms,License"`
Projection string `meta:"ProjectionType"`
ColorProfile string `meta:"ICCProfileName,ProfileDescription"`
CameraMake string `meta:"CameraMake,Make" xmp:"Make"`
CameraModel string `meta:"CameraModel,Model,CameraID,UniqueCameraModel" xmp:"CameraModel,Model"`
CameraOwner string `meta:"OwnerName"`
CameraSerial string `meta:"SerialNumber"`
LensMake string `meta:"LensMake"`
LensModel string `meta:"LensModel,Lens,LensID" xmp:"LensModel,Lens"`
Software string `meta:"Software,CreatorTool,HistorySoftwareAgent,ProcessingSoftware"`
Flash bool `meta:"FlashFired"`
FocalLength int `meta:"FocalLength,FocalLengthIn35mmFormat"`
FocalDistance float64 `meta:"HyperfocalDistance"`
Exposure string `meta:"ExposureTime,ShutterSpeedValue,ShutterSpeed,TargetExposureTime"`
Aperture float32 `meta:"ApertureValue,Aperture"`
FNumber float32 `meta:"FNumber"`
Iso int `meta:"ISO"`
ImageType int `meta:"HDRImageType"`
GPSPosition string `meta:"GPSPosition"`
GPSLatitude string `meta:"GPSLatitude"`
GPSLongitude string `meta:"GPSLongitude"`
Lat float32 `meta:"-"`
Lng float32 `meta:"-"`
Altitude float64 `meta:"GlobalAltitude,GPSAltitude"`
Width int `meta:"ImageWidth,PixelXDimension,ExifImageWidth,SourceImageWidth"`
Height int `meta:"ImageHeight,ImageLength,PixelYDimension,ExifImageHeight,SourceImageHeight"`
Orientation int `meta:"-"`
Rotation int `meta:"Rotation"`
Views int `meta:"-"`
Albums []string `meta:"-"`
Warning string `meta:"Warning" report:"-"`
Error error `meta:"-"`
json map[string]string
exif map[string]string
}
// NewData returns a new Data struct with default values.
func NewData() Data {
return Data{}
}
// AspectRatio returns the aspect ratio based on width and height.
func (data Data) AspectRatio() float32 {
w := float64(data.ActualWidth())
h := float64(data.ActualHeight())
if w <= 0 || h <= 0 {
return 0
}
return float32(math.Round((w/h)*100) / 100)
}
// Portrait returns true if it is a portrait picture or video based on width and height.
func (data Data) Portrait() bool {
return data.ActualWidth() < data.ActualHeight()
}
// IsHDR tests if it is a high dynamic range file.
func (data Data) IsHDR() bool {
return data.ImageType == ImageTypeHDR
}
// Megapixels returns the resolution in megapixels.
func (data Data) Megapixels() int {
return int(math.Round(float64(data.Width*data.Height) / 1000000))
}
// HasDocumentID returns true if a DocumentID exists.
func (data Data) HasDocumentID() bool {
return rnd.IsUUID(data.DocumentID)
}
// HasInstanceID returns true if an InstanceID exists.
func (data Data) HasInstanceID() bool {
return rnd.IsUUID(data.InstanceID)
}
// HasTimeAndPlace if data contains a time and GPS position.
func (data Data) HasTimeAndPlace() bool {
return !data.TakenAt.IsZero() && data.Lat != 0 && data.Lng != 0
}
// ActualWidth is the width after rotating the media file if needed.
func (data Data) ActualWidth() int {
if data.Orientation > 4 {
return data.Height
}
return data.Width
}
// ActualHeight is the height after rotating the media file if needed.
func (data Data) ActualHeight() int {
if data.Orientation > 4 {
return data.Width
}
return data.Height
}
// CellID returns the S2 cell ID.
func (data Data) CellID() string {
return s2.PrefixedToken(float64(data.Lat), float64(data.Lng))
}