Scans: Add support for "KODAK Slide N Scan" digital film scanner #4581

Signed-off-by: Michael Mayer <michael@photoprism.app>
This commit is contained in:
Michael Mayer
2024-10-17 19:27:10 +02:00
parent ba5ea6b518
commit 355b3d352c
9 changed files with 259 additions and 90 deletions

View File

@@ -51,6 +51,7 @@ func CreateUnknownCamera() {
func NewCamera(makeName string, modelName string) *Camera {
makeName = strings.TrimSpace(makeName)
modelName = strings.TrimSpace(modelName)
cameraType := CameraTypes[strings.TrimSpace(modelName)]
if modelName == "" && makeName == "" {
return &UnknownCamera
@@ -89,6 +90,7 @@ func NewCamera(makeName string, modelName string) *Camera {
CameraName: txt.Clip(cameraName, txt.ClipName),
CameraMake: txt.Clip(makeName, txt.ClipName),
CameraModel: txt.Clip(modelName, txt.ClipName),
CameraType: txt.Clip(cameraType, txt.ClipType),
}
return result
@@ -131,7 +133,7 @@ func FirstOrCreateCamera(m *Camera) *Camera {
cameraCache.SetDefault(m.CameraSlug, m)
return m
} else if res := Db().Where("camera_slug = ?", m.CameraSlug).First(&result); res.Error == nil {
} else if res = Db().Where("camera_slug = ?", m.CameraSlug).First(&result); res.Error == nil {
cameraCache.SetDefault(m.CameraSlug, &result)
return &result
} else {
@@ -152,7 +154,9 @@ func (m *Camera) String() string {
// Scanner checks whether the model appears to be a scanner.
func (m *Camera) Scanner() bool {
if m.CameraSlug == "" {
if m.CameraType == CameraScanner {
return true
} else if m.CameraSlug == "" {
return false
}

View File

@@ -26,6 +26,7 @@ var CameraMakes = map[string]string{
"Kodak": "KODAK",
"EASTMAN KODAK": "KODAK",
"EASTMAN KODAK COMPANY": "KODAK",
"GCMC": "KODAK",
"Leica Camera AG": "Leica",
"LEICA": "Leica",
"LG Electronics": "LG",

View File

@@ -2,6 +2,7 @@ package entity
// CameraModels maps internal model identifiers to normalized names.
var CameraModels = map[string]string{
// Mobile Devices:
"Z00AD": "ZenFone 2",
"AI2302": "Zenfone 10",
"_AI2302": "Zenfone 10",
@@ -155,57 +156,66 @@ var CameraModels = map[string]string{
"A6013": "6T", // OnePlus
"PH-1": "Essential Phone",
"PC36100": "Evo 4G",
"LG-R105": "360 CAM",
"LG-V521": "G Pad X 8.0",
"LGUS991": "G4",
"QJXJ01FJ": "Mi Sphere",
"DSC-W30": "Cybershot DSC-W30",
"170 7472F20EEC14": "PhotoScan",
"SLT-A58": "Alpha 58",
"ILCE-1": "Alpha 1",
"ILCE-7C": "Alpha 7C",
"ILCE-7CL": "Alpha 7C",
"ILCE-7SM3": "Alpha 7S III",
"ILCA-77": "Alpha 77",
"ILCA-77M2": "Alpha 77 II",
"ILCA-99": "Alpha 99",
"ILCA-99M2": "Alpha 99 II",
"ILCE-5000": "Alpha 5000",
"ILCE-5100L": "Alpha 5100",
"ILCE-5100Y": "Alpha 5100",
"ILCE-6000": "Alpha 6000",
"ILCE-6100": "Alpha 6100",
"ILCE-6100L": "Alpha 6100",
"ILCE-6100Y": "Alpha 6100",
"ILCE-6300": "Alpha 6300",
"ILCE-6300L": "Alpha 6300",
"ILCE-6300M": "Alpha 6300",
"ILCE-6400": "Alpha 6400",
"ILCE-6400L": "Alpha 6400",
"ILCE-6400M": "Alpha 6400",
"ILCE-6600": "Alpha 6600",
"ILCE-6600M": "Alpha 6600",
"ILCE-6700": "Alpha 6700",
"ILCE-7S": "Alpha 7S",
"ILCE-7R": "Alpha 7R",
"ILCE-7RM4A": "Alpha 7R IV",
"ILCE-7RM3A": "Alpha 7R III",
"ILCE-7RM3": "Alpha 7R III",
"ILCE-7RM2": "Alpha 7R II",
"ILCE-7M3": "Alpha 7 III",
"ILCE-7M3G": "Alpha 7 III",
"ILCE-7M3K": "Alpha 7 III",
"ILCE-7M2": "Alpha 7 II",
"ILCE-7": "Alpha 7",
"ILCE-7K": "Alpha 7",
"ILCE-7CR": "Alpha 7CR",
"ILCE-7CM2": "Alpha 7C II",
"ILCE-7RM5": "Alpha 7R V",
"ILCE-7M4": "Alpha 7 IV",
"ILCE-7M4K": "Alpha 7 IV",
"ILCE-9": "Alpha 9",
"ILME-FX6T": "FX6 Cinema Line",
"ILME-FX6TK": "FX6 Cinema Line",
"ILME-FX6V": "FX6 Cinema Line",
"ILME-FX6VK": "FX6 Cinema Line",
// Digital Cameras:
"LG-R105": "360 CAM",
"LGUS991": "G4",
"QJXJ01FJ": "Mi Sphere",
"DSC-W30": "Cybershot DSC-W30",
"SLT-A58": "Alpha 58",
"ILCE-1": "Alpha 1",
"ILCE-7C": "Alpha 7C",
"ILCE-7CL": "Alpha 7C",
"ILCE-7SM3": "Alpha 7S III",
"ILCA-77": "Alpha 77",
"ILCA-77M2": "Alpha 77 II",
"ILCA-99": "Alpha 99",
"ILCA-99M2": "Alpha 99 II",
"ILCE-5000": "Alpha 5000",
"ILCE-5100L": "Alpha 5100",
"ILCE-5100Y": "Alpha 5100",
"ILCE-6000": "Alpha 6000",
"ILCE-6100": "Alpha 6100",
"ILCE-6100L": "Alpha 6100",
"ILCE-6100Y": "Alpha 6100",
"ILCE-6300": "Alpha 6300",
"ILCE-6300L": "Alpha 6300",
"ILCE-6300M": "Alpha 6300",
"ILCE-6400": "Alpha 6400",
"ILCE-6400L": "Alpha 6400",
"ILCE-6400M": "Alpha 6400",
"ILCE-6600": "Alpha 6600",
"ILCE-6600M": "Alpha 6600",
"ILCE-6700": "Alpha 6700",
"ILCE-7S": "Alpha 7S",
"ILCE-7R": "Alpha 7R",
"ILCE-7RM4A": "Alpha 7R IV",
"ILCE-7RM3A": "Alpha 7R III",
"ILCE-7RM3": "Alpha 7R III",
"ILCE-7RM2": "Alpha 7R II",
"ILCE-7M3": "Alpha 7 III",
"ILCE-7M3G": "Alpha 7 III",
"ILCE-7M3K": "Alpha 7 III",
"ILCE-7M2": "Alpha 7 II",
"ILCE-7": "Alpha 7",
"ILCE-7K": "Alpha 7",
"ILCE-7CR": "Alpha 7CR",
"ILCE-7CM2": "Alpha 7C II",
"ILCE-7RM5": "Alpha 7R V",
"ILCE-7M4": "Alpha 7 IV",
"ILCE-7M4K": "Alpha 7 IV",
"ILCE-9": "Alpha 9",
"ILME-FX6T": "FX6 Cinema Line",
"ILME-FX6TK": "FX6 Cinema Line",
"ILME-FX6V": "FX6 Cinema Line",
"ILME-FX6VK": "FX6 Cinema Line",
// Film Scanners:
"170 7472F20EEC14": "PhotoScan",
"RODFS40": "Slide N Scan",
"RODFS50": "Slide N Scan",
"RODFS60": "Slide N Scan",
"RODFS70": "Slide N Scan",
"RODFS80": "Slide N Scan",
"RODFS90": "Slide N Scan",
"SLIDE N SCAN": "Slide N Scan",
}

View File

@@ -148,4 +148,10 @@ func TestCamera_Scanner(t *testing.T) {
camera := NewCamera("", "MS Scanner")
assert.True(t, camera.Scanner())
})
t.Run("KODAKSlideNScan", func(t *testing.T) {
camera := NewCamera("GCMC", "RODFS50")
assert.True(t, camera.Scanner())
assert.Equal(t, "KODAK", camera.CameraMake)
assert.Equal(t, "Slide N Scan", camera.CameraModel)
})
}

View File

@@ -0,0 +1,46 @@
package entity
type CameraType = string
const (
CameraUnknown CameraType = ""
CameraZLR CameraType = "zlr"
CameraSLR CameraType = "slr"
CameraDSLR CameraType = "dslr"
CameraMirrorless CameraType = "mirrorless"
CameraCCTV CameraType = "cctv"
CameraSpy CameraType = "spy"
CameraAction CameraType = "action"
CameraWebcam CameraType = "webcam"
CameraDashcam CameraType = "dashcam"
CameraAnalog CameraType = "analog"
CameraBridge CameraType = "bridge"
CameraCompact CameraType = "compact"
CameraInstant CameraType = "instant" // Polaroid
CameraStereo CameraType = "stereo" // 3D
CameraOmni CameraType = "omni" // 360 Degree
CameraPhone CameraType = "phone"
CameraTablet CameraType = "tablet"
CameraMobile CameraType = "mobile"
CameraScanner CameraType = "scanner"
CameraMovie CameraType = "movie"
CameraVideo CameraType = "video"
CameraSoftware CameraType = "software"
CameraOther CameraType = "other"
)
// CameraTypes maps internal model identifiers to camera types.
var CameraTypes = map[string]CameraType{
"Scan": CameraScanner,
"Scanner": CameraScanner,
"MS Scanner": CameraScanner,
"PhotoScan": CameraScanner,
"170 7472F20EEC14": CameraScanner,
"Slide N Scan": CameraScanner,
"RODFS40": CameraScanner,
"RODFS50": CameraScanner,
"RODFS60": CameraScanner,
"RODFS70": CameraScanner,
"RODFS80": CameraScanner,
"RODFS90": CameraScanner,
}

View File

@@ -35,8 +35,8 @@ func TestJSON(t *testing.T) {
assert.Equal(t, 1920, data.ActualWidth())
assert.Equal(t, 1440, data.ActualHeight())
assert.Equal(t, 1, data.Orientation)
assert.InEpsilon(t, 52.5035, data.Lat, 0.00001)
assert.InEpsilon(t, 13.4098, data.Lng, 0.00001)
assert.InDelta(t, 52.5035, data.Lat, 0.00001)
assert.InDelta(t, 13.4098, data.Lng, 0.00001)
assert.Equal(t, "Apple", data.CameraMake)
assert.Equal(t, "iPhone 12 mini", data.CameraModel)
assert.Equal(t, "", data.LensModel)
@@ -65,8 +65,8 @@ func TestJSON(t *testing.T) {
assert.Equal(t, 1080, data.ActualWidth())
assert.Equal(t, 1920, data.ActualHeight())
assert.Equal(t, 6, data.Orientation)
assert.InEpsilon(t, 52.4587, data.Lat, 0.00001)
assert.InEpsilon(t, 13.4593, data.Lng, 0.00001)
assert.InDelta(t, 52.4587, data.Lat, 0.00001)
assert.InDelta(t, 13.4593, data.Lng, 0.00001)
assert.Equal(t, "Apple", data.CameraMake)
assert.Equal(t, "iPhone SE", data.CameraModel)
assert.Equal(t, "", data.LensModel)
@@ -200,8 +200,8 @@ func TestJSON(t *testing.T) {
assert.Equal(t, 1920, data.ActualHeight())
assert.Equal(t, float32(0.56), data.AspectRatio())
assert.Equal(t, 6, data.Orientation)
assert.InEpsilon(t, 52.4596, data.Lat, 0.00001)
assert.InEpsilon(t, 13.3218, data.Lng, 0.00001)
assert.InDelta(t, 52.4596, data.Lat, 0.00001)
assert.InDelta(t, 13.3218, data.Lng, 0.00001)
assert.Equal(t, "", data.CameraMake)
assert.Equal(t, "", data.CameraModel)
assert.Equal(t, "", data.LensModel)
@@ -225,8 +225,8 @@ func TestJSON(t *testing.T) {
assert.Equal(t, 1920, data.Width)
assert.Equal(t, 1080, data.Height)
assert.Equal(t, 1, data.Orientation)
assert.InEpsilon(t, 52.4649, data.Lat, 0.00001)
assert.InEpsilon(t, 13.3148, data.Lng, 0.00001)
assert.InDelta(t, 52.4649, data.Lat, 0.00001)
assert.InDelta(t, 13.3148, data.Lng, 0.00001)
assert.Equal(t, "", data.CameraMake)
assert.Equal(t, "", data.CameraModel)
assert.Equal(t, "", data.LensModel)
@@ -264,8 +264,8 @@ func TestJSON(t *testing.T) {
assert.Equal(t, "photoshop.xmp", data.FileName)
assert.Equal(t, CodecXMP, data.Codec)
assert.Equal(t, "0s", data.Duration.String())
assert.InEpsilon(t, 52.45969, data.Lat, 0.00001)
assert.InEpsilon(t, 13.321831, data.Lng, 0.00001)
assert.InDelta(t, 52.45969, data.Lat, 0.00001)
assert.InDelta(t, 13.321831, data.Lng, 0.00001)
assert.Equal(t, "2020-01-01 16:28:23 +0000 UTC", data.TakenAt.String())
assert.Equal(t, "2020-01-01 17:28:23 +0000 UTC", data.TakenAtLocal.String())
assert.Equal(t, 899614000, data.TakenNs)
@@ -383,8 +383,8 @@ func TestJSON(t *testing.T) {
assert.Equal(t, 3024, data.Width)
assert.Equal(t, 4032, data.Height)
assert.Equal(t, 1, data.Orientation)
assert.InEpsilon(t, 48.300003, data.Lat, 0.00001)
assert.InEpsilon(t, 8.929067, data.Lng, 0.00001)
assert.InDelta(t, 48.300003, data.Lat, 0.00001)
assert.InDelta(t, 8.929067, data.Lng, 0.00001)
assert.Equal(t, "Apple", data.CameraMake)
assert.Equal(t, "iPhone SE", data.CameraModel)
assert.Equal(t, "iPhone SE back camera 4.15mm f/2.2", data.LensModel)
@@ -409,8 +409,8 @@ func TestJSON(t *testing.T) {
assert.Equal(t, 1024, data.Width)
assert.Equal(t, 1365, data.Height)
assert.Equal(t, 1, data.Orientation)
assert.InEpsilon(t, 48.300003, data.Lat, 0.00001)
assert.InEpsilon(t, 8.929067, data.Lng, 0.00001)
assert.InDelta(t, 48.300003, data.Lat, 0.00001)
assert.InDelta(t, 8.929067, data.Lng, 0.00001)
assert.Equal(t, "Apple", data.CameraMake)
assert.Equal(t, "iPhone SE", data.CameraModel)
assert.Equal(t, "iPhone SE back camera 4.15mm f/2.2", data.LensModel)
@@ -435,8 +435,8 @@ func TestJSON(t *testing.T) {
assert.Equal(t, 1125, data.Width)
assert.Equal(t, 1500, data.Height)
assert.Equal(t, 1, data.Orientation)
assert.InEpsilon(t, 48.300003, data.Lat, 0.00001)
assert.InEpsilon(t, 8.929067, data.Lng, 0.00001)
assert.InDelta(t, 48.300003, data.Lat, 0.00001)
assert.InDelta(t, 8.929067, data.Lng, 0.00001)
assert.Equal(t, "Apple", data.CameraMake)
assert.Equal(t, "iPhone SE", data.CameraModel)
assert.Equal(t, "iPhone SE back camera 4.15mm f/2.2", data.LensModel)
@@ -466,8 +466,8 @@ func TestJSON(t *testing.T) {
assert.Equal(t, "2015-12-06 16:18:30 +0000 UTC", data.TakenAtLocal.String())
assert.Equal(t, "2015-12-06 15:18:30 +0000 UTC", data.TakenAt.String())
assert.Equal(t, "Europe/Berlin", data.TimeZone)
assert.InEpsilon(t, 52.508522, data.Lat, 0.00001)
assert.InEpsilon(t, 13.443206, data.Lng, 0.00001)
assert.InDelta(t, 52.508522, data.Lat, 0.00001)
assert.InDelta(t, 13.443206, data.Lng, 0.00001)
assert.Equal(t, 40, clean.Altitude(data.Altitude))
assert.Equal(t, 0, data.Views)
@@ -495,8 +495,8 @@ func TestJSON(t *testing.T) {
assert.Equal(t, "2019-05-18 12:06:45 +0000 UTC", data.TakenAtLocal.String())
assert.Equal(t, "2019-05-18 10:06:45 +0000 UTC", data.TakenAt.String())
assert.Equal(t, "Europe/Berlin", data.TimeZone)
assert.InEpsilon(t, 52.510796, data.Lat, 0.00001)
assert.InEpsilon(t, 13.456387, data.Lng, 0.00001)
assert.InDelta(t, 52.510796, data.Lat, 0.00001)
assert.InDelta(t, 13.456387, data.Lng, 0.00001)
assert.Equal(t, 0.0, data.Altitude)
assert.Equal(t, 1118, data.Views)
})
@@ -531,8 +531,8 @@ func TestJSON(t *testing.T) {
assert.Equal(t, "2012-12-11 00:07:15 +0000 UTC", data.TakenAtLocal.String())
assert.Equal(t, "2012-12-10 23:07:15 +0000 UTC", data.TakenAt.String())
assert.Equal(t, "Europe/Berlin", data.TimeZone)
assert.InEpsilon(t, 52.49967, data.Lat, 0.00001)
assert.InEpsilon(t, 13.422334, data.Lng, 0.00001)
assert.InDelta(t, 52.49967, data.Lat, 0.00001)
assert.InDelta(t, 13.422334, data.Lng, 0.00001)
assert.Equal(t, 0.0, data.Altitude)
assert.Equal(t, 0, data.Views)
})
@@ -573,7 +573,7 @@ func TestJSON(t *testing.T) {
assert.Equal(t, "", data.Copyright)
assert.Equal(t, 3600, data.Height)
assert.Equal(t, 7200, data.Width)
assert.InEpsilon(t, 59.84083, data.Lat, 0.00001)
assert.InDelta(t, 59.84083, data.Lat, 0.00001)
assert.Equal(t, 30.51, data.Lng)
assert.Equal(t, 0.0, data.Altitude)
assert.Equal(t, "1/1250", data.Exposure)
@@ -660,8 +660,8 @@ func TestJSON(t *testing.T) {
assert.Equal(t, "", data.Copyright)
assert.Equal(t, 375, data.Height)
assert.Equal(t, 500, data.Width)
assert.InEpsilon(t, 52.46052, data.Lat, 0.00001)
assert.InEpsilon(t, 13.331403, data.Lng, 0.00001)
assert.InDelta(t, 52.46052, data.Lat, 0.00001)
assert.InDelta(t, 13.331403, data.Lng, 0.00001)
assert.Equal(t, 84, clean.Altitude(data.Altitude))
assert.Equal(t, "1/50", data.Exposure)
assert.Equal(t, "HUAWEI", data.CameraMake)
@@ -691,8 +691,8 @@ func TestJSON(t *testing.T) {
assert.Equal(t, 1080, data.ActualWidth())
assert.Equal(t, 1920, data.ActualHeight())
assert.Equal(t, 6, data.Orientation)
assert.InEpsilon(t, 55.5636, data.Lat, 0.00001)
assert.InEpsilon(t, 37.9824, data.Lng, 0.00001)
assert.InDelta(t, 55.5636, data.Lat, 0.00001)
assert.InDelta(t, 37.9824, data.Lng, 0.00001)
assert.Equal(t, "Apple", data.CameraMake)
assert.Equal(t, "iPhone 6 Plus", data.CameraModel)
assert.Equal(t, "", data.LensModel)
@@ -716,8 +716,8 @@ func TestJSON(t *testing.T) {
assert.Equal(t, 1920, data.ActualWidth())
assert.Equal(t, 1080, data.ActualHeight())
assert.Equal(t, 1, data.Orientation)
assert.InEpsilon(t, 55.7579, data.Lat, 0.00001)
assert.InEpsilon(t, 37.6197, data.Lng, 0.00001)
assert.InDelta(t, 55.7579, data.Lat, 0.00001)
assert.InDelta(t, 37.6197, data.Lng, 0.00001)
assert.Equal(t, "Apple", data.CameraMake)
assert.Equal(t, "iPhone 6 Plus", data.CameraModel)
assert.Equal(t, "", data.LensModel)
@@ -760,8 +760,8 @@ func TestJSON(t *testing.T) {
assert.Equal(t, "2019-12-13 01:47:21 +0000 UTC", data.TakenAt.String())
assert.Equal(t, "America/New_York", data.TimeZone)
assert.Equal(t, 1, data.Orientation)
assert.InEpsilon(t, 40.7696, data.Lat, 0.00001)
assert.InEpsilon(t, -73.9964, data.Lng, 0.00001)
assert.InDelta(t, 40.7696, data.Lat, 0.00001)
assert.InDelta(t, -73.9964, data.Lng, 0.00001)
assert.Equal(t, "Apple", data.CameraMake)
assert.Equal(t, "iPhone X", data.CameraModel)
assert.Equal(t, "", data.LensModel)
@@ -975,8 +975,8 @@ func TestJSON(t *testing.T) {
assert.Equal(t, "2012-07-11 05:16:01 +0000 UTC", data.TakenAt.String())
assert.Equal(t, "Europe/Paris", data.TimeZone)
assert.Equal(t, 1, data.Orientation)
assert.InEpsilon(t, 43.5683, data.Lat, 0.00001)
assert.InEpsilon(t, 4.5645, data.Lng, 0.00001)
assert.InDelta(t, 43.5683, data.Lat, 0.00001)
assert.InDelta(t, 4.5645, data.Lng, 0.00001)
})
t.Run("quicktimeutc_off.json", func(t *testing.T) {
@@ -1126,7 +1126,7 @@ func TestJSON(t *testing.T) {
assert.Equal(t, "", data.CameraOwner)
assert.Equal(t, "6001440", data.CameraSerial)
assert.Equal(t, 16, data.FocalLength)
assert.InEpsilon(t, 1.0650, data.FocalDistance, 0.01)
assert.InDelta(t, 1.0650, data.FocalDistance, 0.01)
assert.Equal(t, 1, data.Orientation)
assert.Equal(t, "", data.Projection)
assert.Equal(t, "Display P3", data.ColorProfile)
@@ -1159,7 +1159,7 @@ func TestJSON(t *testing.T) {
assert.Equal(t, "", data.CameraOwner)
assert.Equal(t, "6001440", data.CameraSerial)
assert.Equal(t, 16, data.FocalLength)
assert.InEpsilon(t, 1.0650, data.FocalDistance, 0.01)
assert.InDelta(t, 1.0650, data.FocalDistance, 0.01)
assert.Equal(t, 1, data.Orientation)
assert.Equal(t, "", data.Projection)
assert.Equal(t, "Display P3", data.ColorProfile)
@@ -1327,7 +1327,7 @@ func TestJSON(t *testing.T) {
assert.Equal(t, "", data.LensModel)
assert.Equal(t, float32(45.75285), float32(data.Lat))
assert.Equal(t, float32(33.221977), float32(data.Lng))
assert.InEpsilon(t, 4294967284, data.Altitude, 1000)
assert.InDelta(t, 4294967284, data.Altitude, 1000)
assert.Equal(t, 0, clean.Altitude(data.Altitude))
})
@@ -1352,4 +1352,30 @@ func TestJSON(t *testing.T) {
assert.Equal(t, "iPhone 13", data.CameraModel)
assert.Equal(t, "iPhone 13 back dual wide camera 5.1mm f/1.6", data.LensModel)
})
t.Run("kodak-slide-n-scan.json", func(t *testing.T) {
data, err := JSON("testdata/kodak-slide-n-scan.json", "")
if err != nil {
t.Fatal(err)
}
// t.Logf("DATA: %+v", data)
assert.Equal(t, "", data.DocumentID)
assert.Equal(t, "", data.InstanceID)
assert.Equal(t, CodecJpeg, data.Codec)
assert.Equal(t, "0s", data.Duration.String())
assert.Equal(t, "1990-08-01 12:11:50 +0000 UTC", data.TakenAtLocal.String())
assert.Equal(t, "1990-08-01 12:11:50 +0000 UTC", data.TakenAt.String())
assert.Equal(t, "", data.TimeZone)
assert.Equal(t, 5728, data.Width)
assert.Equal(t, 3824, data.Height)
assert.Equal(t, 1, data.Orientation)
assert.InDelta(t, 0, data.Lat, 0.0001)
assert.InDelta(t, 0, data.Lng, 0.0001)
assert.Equal(t, "GCMC", data.CameraMake)
assert.Equal(t, "RODFS50", data.CameraModel)
assert.Equal(t, "", data.LensModel)
})
}

View File

@@ -18,6 +18,7 @@ var UnwantedDescriptions = map[string]bool{
"SAMSUNG CAMERA PICTURES": true,
"<Digimax i5, Samsung #1>": true,
"SONY DSC": true, // Sony
"Scanner": true, // KODAK Slide N Scan
"rhdr": true, // Huawei
"hdrpl": true,
"oznorWO": true,

View File

@@ -0,0 +1,74 @@
[{
"SourceFile": "IMAG0030.JPG",
"ExifToolVersion": 12.76,
"FileName": "IMAG0030.JPG",
"Directory": ".",
"FileSize": 5610200,
"FileModifyDate": "1990:08:01 12:11:52+02:00",
"FileAccessDate": "1990:08:01 00:00:00+02:00",
"FileInodeChangeDate": "1990:08:01 12:11:52+02:00",
"FilePermissions": 100700,
"FileType": "JPEG",
"FileTypeExtension": "JPG",
"MIMEType": "image/jpeg",
"ExifByteOrder": "II",
"ImageDescription": "Scanner",
"Make": "GCMC",
"Model": "RODFS50",
"Orientation": 1,
"XResolution": 72,
"YResolution": 72,
"ResolutionUnit": 2,
"Software": "UF22 21/10/19 v1.59",
"ModifyDate": "1990:08:01 12:11:50",
"YCbCrPositioning": 2,
"ExposureTime": 0.03225806452,
"FNumber": 3.5,
"ExposureProgram": 2,
"ISO": 50,
"ExifVersion": "0220",
"DateTimeOriginal": "1990:08:01 12:11:50",
"CreateDate": "1990:08:01 12:11:50",
"ComponentsConfiguration": "1 2 3 0",
"ApertureValue": 3.4822022531845,
"BrightnessValue": 1,
"ExposureCompensation": 0,
"MaxApertureValue": 3.4822022531845,
"MeteringMode": 1,
"LightSource": 0,
"Flash": 16,
"FocalLength": 4,
"Warning": "[minor] Unrecognized MakerNotes",
"UserComment": "",
"FlashpixVersion": "0100",
"ColorSpace": 1,
"ExifImageWidth": 5728,
"ExifImageHeight": 3824,
"InteropIndex": "R98",
"InteropVersion": "0100",
"SensingMethod": 2,
"FileSource": 3,
"SceneType": 1,
"CustomRendered": 0,
"ExposureMode": 1,
"WhiteBalance": 0,
"DigitalZoomRatio": 1,
"SceneCaptureType": 0,
"Sharpness": 0,
"Compression": 6,
"ThumbnailOffset": 890,
"ThumbnailLength": 12630,
"ImageWidth": 5728,
"ImageHeight": 3824,
"EncodingProcess": 0,
"BitsPerSample": 8,
"ColorComponents": 3,
"YCbCrSubSampling": "2 1",
"Aperture": 3.5,
"ImageSize": "5728 3824",
"Megapixels": 21.903872,
"ShutterSpeed": 0.03225806452,
"ThumbnailImage": "(Binary data 12630 bytes, use -b option to extract)",
"FocalLength35efl": 4,
"LightValue": 9.56890615432896
}]

View File

@@ -15,6 +15,7 @@ const (
ClipUsername = 64
ClipPassword = 72
ClipSlug = 80
ClipType = 100
ClipCategory = 100
ClipTokenName = 128
ClipDefault = 160