diff --git a/src/backend/model/fileaccess/MetadataLoader.ts b/src/backend/model/fileaccess/MetadataLoader.ts
index 8feb8427..5a61af21 100644
--- a/src/backend/model/fileaccess/MetadataLoader.ts
+++ b/src/backend/model/fileaccess/MetadataLoader.ts
@@ -139,13 +139,13 @@ export class MetadataLoader {
fullPathWithoutExt + '.xmp',
fullPathWithoutExt + '.XMP',
];
+
for (const sidecarPath of sidecarPaths) {
if (fs.existsSync(sidecarPath)) {
const sidecarData: any = await exifr.sidecar(sidecarPath);
if (sidecarData !== undefined) {
MetadataLoader.mapMetadata(metadata, sidecarData);
}
- break; //Break the loop as soon as a sidecar is found, no need to check the extra sidecar paths
}
}
} catch (err) {
@@ -316,8 +316,6 @@ export class MetadataLoader {
const orientation = MetadataLoader.getOrientation(exif);
MetadataLoader.mapImageDimensions(metadata, exif, orientation);
MetadataLoader.mapKeywords(metadata, exif);
- MetadataLoader.mapTitle(metadata, exif);
- MetadataLoader.mapCaption(metadata, exif);
MetadataLoader.mapTimestampAndOffset(metadata, exif);
MetadataLoader.mapCameraData(metadata, exif);
MetadataLoader.mapGPS(metadata, exif);
@@ -372,15 +370,6 @@ export class MetadataLoader {
}
}
- private static mapTitle(metadata: PhotoMetadata, exif: any) {
- metadata.title = exif.dc?.title?.value || metadata.title || exif.photoshop?.Headline || exif.acdsee?.caption; //acdsee caption holds the title when data is saved by digikam. Used as last resort if iptc and dc do not contain the data
- }
-
- private static mapCaption(metadata: PhotoMetadata, exif: any) {
- metadata.caption = exif.dc?.description?.value || metadata.caption || exif.ifd0?.ImageDescription || exif.exif?.UserComment?.value || exif.Iptc4xmpCore?.ExtDescrAccessibility?.value ||exif.acdsee?.notes;
- }
-
-
private static mapTimestampAndOffset(metadata: PhotoMetadata, exif: any) {
metadata.creationDate = Utils.timestampToMS(exif?.photoshop?.DateCreated, null) ||
Utils.timestampToMS(exif?.xmp?.CreateDate, null) ||
diff --git a/src/common/Utils.ts b/src/common/Utils.ts
index a9a7a862..49a89307 100644
--- a/src/common/Utils.ts
+++ b/src/common/Utils.ts
@@ -132,8 +132,8 @@ export class Utils {
//replace : with - in the yyyy-mm-dd part of the timestamp.
let formattedTimestamp = timestamp.substring(0,9).replaceAll(':', '-') + timestamp.substring(9,timestamp.length);
if (formattedTimestamp.indexOf("Z") > 0) { //replace Z (and what comes after the Z) with offset
- formattedTimestamp = formattedTimestamp.substring(0, formattedTimestamp.indexOf("Z")) + (offset ? offset : '+00:00');
- } else if (formattedTimestamp.indexOf("+") > 0) { //don't do anything
+ formattedTimestamp.substring(0, formattedTimestamp.indexOf("Z")) + (offset ? offset : '+00:00');
+ } else if (formattedTimestamp.indexOf("+") > 0 || timestamp.substring(9,timestamp.length).indexOf("-") > 0) { //don't do anything
} else { //add offset
formattedTimestamp = formattedTimestamp + (offset ? offset : '+00:00');
}
@@ -144,11 +144,11 @@ export class Utils {
//function to extract offset string from timestamp string, returns undefined if timestamp does not contain offset
static timestampToOffsetString(timestamp: string) {
try {
- const idx = timestamp.indexOf("+");
- if (idx > 0) {
- return timestamp.substring(idx, timestamp.length);
- }
- if (timestamp.indexOf("Z") > 0) {
+ const offsetRegex = /[+-]\d{2}:\d{2}$/;
+ const match = timestamp.match(offsetRegex);
+ if (match) {
+ return match[0];
+ } else if (timestamp.indexOf("Z") > 0) {
return '+00:00';
}
return undefined;
diff --git a/test/backend/assets/sidecar/flatxmp.jpg b/test/backend/assets/sidecar/flatxmp.jpg
deleted file mode 100644
index c119808d..00000000
Binary files a/test/backend/assets/sidecar/flatxmp.jpg and /dev/null differ
diff --git a/test/backend/assets/sidecar/flatxmp.json b/test/backend/assets/sidecar/flatxmp.json
deleted file mode 100644
index 008108db..00000000
--- a/test/backend/assets/sidecar/flatxmp.json
+++ /dev/null
@@ -1,33 +0,0 @@
-{
- "size": {
- "width": 10,
- "height": 5
- },
- "caption": "Description of image",
- "creationDate": 328817998000,
- "faces": [
- {
- "box": {
- "height": 1,
- "left": 6,
- "top": 2,
- "width": 2
- },
- "name": "Person1"
- },
- {
- "box": {
- "height": 2,
- "left": 2,
- "top": 1,
- "width": 2
- },
- "name": "Person2"
- }
- ],
- "fileSize": 1430,
- "keywords": [
- "Thing3"
- ],
- "title": "The title"
-}
\ No newline at end of file
diff --git a/test/backend/assets/sidecar/flatxmp.xmp b/test/backend/assets/sidecar/flatxmp.xmp
deleted file mode 100644
index 74506a10..00000000
--- a/test/backend/assets/sidecar/flatxmp.xmp
+++ /dev/null
@@ -1,329 +0,0 @@
-
-
-
-
-
-
- 0, 0
- 32, 22
- 64, 56
- 128, 128
- 192, 196
- 255, 255
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Digitized By Testmaster
-
-
-
-
- The title
-
-
-
-
- © Testmaster 2024
-
-
-
-
- Person1
- Person2
- Thing3
-
-
-
-
- Description of image
-
-
-
-
- All Rights Reserved
-
-
-
-
- User comment
-
-
-
-
- 400
-
-
-
-
-
-
- alt text
-
-
-
-
- extended description
-
-
-
-
- Person1
- Person2
-
-
-
-
- Person1
- Person2
-
-
-
-
- Person1
- Person2
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/test/backend/assets/sidecar/headline.jpg b/test/backend/assets/sidecar/headline.jpg
deleted file mode 100644
index c119808d..00000000
Binary files a/test/backend/assets/sidecar/headline.jpg and /dev/null differ
diff --git a/test/backend/assets/sidecar/headline.json b/test/backend/assets/sidecar/headline.json
deleted file mode 100644
index 7d6cb058..00000000
--- a/test/backend/assets/sidecar/headline.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "size": {
- "width": 10,
- "height": 5
- },
- "creationDate": 1185683698000,
- "creationDateOffset": "+13:45",
- "fileSize": 1430,
- "keywords": ["Person 1", "Person 2"],
- "caption": "XMP description",
- "title": "Photoshop Headline"
-}
\ No newline at end of file
diff --git a/test/backend/assets/sidecar/headline.xmp b/test/backend/assets/sidecar/headline.xmp
deleted file mode 100644
index db1f80cf..00000000
--- a/test/backend/assets/sidecar/headline.xmp
+++ /dev/null
@@ -1,210 +0,0 @@
-
-
-
-
-
-
-
- alt text
-
-
-
- Testville
- Testica
- Testroad 2
- 7357
- Testas
- test@example.com
-
-
-
- extended description
-
-
-
-
-
- 4244
- 28.0-80.0 mm f/2.8
- 28/1 80/1 14/5 14/5
-
-
-
- True
- 0
- 0
- +50
- ACR 3.3
- 0
- 0
- 25
- +58
- False
- -0.35
- 0
- 0
- 0
- False
- True
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 75
- 0
- 0
- 50
- 25
- 0
- family-220.png
- 0
- 0
- -24
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 32
- 25
- 0
- 0
- 0
- 0
- 0
- 4150
- +32
-
-
- 0, 0
- 32, 22
- 64, 56
- 128, 128
- 192, 196
- 255, 255
-
-
- Medium Contrast
- 3.7
- 0
- 0
- Custom
-
-
-
-
-
- XMP Creator
-
-
-
-
- XMP description
-
-
- image/png
-
-
- XMP Creator
-
-
-
-
- Person 1
- Person 2
-
-
-
-
-
- 24361/8200
- 1
- 0
- 0
- 2007-07-29T18:19:58+13:45
- 1/1
- 0221
- 1/1
- 0
- 2
- 1/8
- 14/5
- 3
-
- False
- False
- 0
- False
- 0
-
- 28/1
- 42
- 1
-
-
- 400
-
-
- 0
- 24361/8200
- 3
- 0
- 0
- 1
- 2
- 0
- 3/1
- 0
- 0
-
-
-
-
- Archivalist
- 1980-06-02T18:19:58
- Photoshop Headline
-
-
-
- CamMake
- CamModel
- 1
-
-
-
- 2007-07-29T18:19:58+13:45
- Adobe Photoshop Lightroom 13.2 Classic (Windows)
- 2014-03-23T01:17:49-05:00
- 2014-03-22T19:09:41-05:00
-
-
-
-
-
\ No newline at end of file
diff --git a/test/backend/assets/sidecar/testimagedesc1.jpg b/test/backend/assets/sidecar/testimagedesc1.jpg
deleted file mode 100644
index f0fa299a..00000000
Binary files a/test/backend/assets/sidecar/testimagedesc1.jpg and /dev/null differ
diff --git a/test/backend/assets/sidecar/testimagedesc1.json b/test/backend/assets/sidecar/testimagedesc1.json
deleted file mode 100644
index bc0aac3b..00000000
--- a/test/backend/assets/sidecar/testimagedesc1.json
+++ /dev/null
@@ -1,54 +0,0 @@
-{
- "cameraData": {
- "ISO": 3200,
- "exposure": 0.00125,
- "fStop": 5.6,
- "focalLength": 85,
- "lens": "EF-S15-85mm f/3.5-5.6 IS USM",
- "make": "Canon",
- "model": "óüöúőűáé ÓÜÖÚŐŰÁÉ"
- },
- "caption": "Test caption",
- "creationDate": 1434018566690,
- "faces": [
- {
- "box": {
- "height": 2,
- "width": 2,
- "left": 7,
- "top": 3
- },
- "name": "squirrel"
- },
- {
- "box": {
- "height": 3,
- "width": 2,
- "left": 4,
- "top": 4
- },
- "name": "special_chars űáéúőóüío?._:"
- }
- ],
- "fileSize": 39424,
- "keywords": [
- "Berkley",
- "USA",
- "űáéúőóüö ŰÁÉÚŐÓÜÖ"
- ],
- "positionData": {
- "GPSData": {
- "latitude": 37.871093,
- "longitude": -122.25678
- },
- "city": "test city őúéáűóöí-.,)(=",
- "country": "test country őúéáűóöí-.,)(=/%!+\"'",
- "state": "test state őúéáűóöí-.,)("
- },
- "rating": 3,
- "size": {
- "height": 10,
- "width": 14
- },
- "title": "Test caption"
-}
diff --git a/test/backend/assets/sidecar/testimagedesc1.xmp b/test/backend/assets/sidecar/testimagedesc1.xmp
deleted file mode 100644
index f27c3386..00000000
--- a/test/backend/assets/sidecar/testimagedesc1.xmp
+++ /dev/null
@@ -1,86 +0,0 @@
-
-
-
-
-
-
- Patrik
-
-
-
-
- Test caption
-
-
-
-
-
- Copyright test
-
-
-
-
- Berkley
- USA
- special_chars űáéúőóüío?._:
- squirrel
- űáéúőóüö ŰÁÉÚŐÓÜÖ
-
-
-
-
- Test caption
-
-
-
-
-
-
-
-
-
-
-
-
-
- Berkley
- USA
- űáéúőóüö ŰÁÉÚŐÓÜÖ
-
-
-
-
- Berkley
- USA
- űáéúőóüö ŰÁÉÚŐÓÜÖ
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Berkley
- USA
- special_chars űáéúőóüío?._:
- squirrel
- űáéúőóüö ŰÁÉÚŐÓÜÖ
-
-
-
-
-
\ No newline at end of file
diff --git a/test/backend/assets/sidecar/testimagedesc2.jpg b/test/backend/assets/sidecar/testimagedesc2.jpg
deleted file mode 100644
index f0fa299a..00000000
Binary files a/test/backend/assets/sidecar/testimagedesc2.jpg and /dev/null differ
diff --git a/test/backend/assets/sidecar/testimagedesc2.json b/test/backend/assets/sidecar/testimagedesc2.json
deleted file mode 100644
index 803e2afd..00000000
--- a/test/backend/assets/sidecar/testimagedesc2.json
+++ /dev/null
@@ -1,56 +0,0 @@
-{
- "cameraData": {
- "ISO": 3200,
- "exposure": 0.00125,
- "fStop": 5.6,
- "focalLength": 85,
- "lens": "EF-S15-85mm f/3.5-5.6 IS USM",
- "make": "Canon",
- "model": "óüöúőűáé ÓÜÖÚŐŰÁÉ"
- },
- "caption": "Test caption",
- "creationDate": 1434018566000,
- "faces": [
- {
- "box": {
- "height": 2,
- "width": 2,
- "left": 7,
- "top": 3
- },
- "name": "squirrel"
- },
- {
- "box": {
- "height": 3,
- "width": 2,
- "left": 4,
- "top": 4
- },
- "name": "special_chars űáéúőóüío?._:"
- }
- ],
- "fileSize": 39424,
- "keywords": [
- "Berkley",
- "USA",
- "űáéúőóüö ŰÁÉÚŐÓÜÖ",
- "special_chars űáéúőóüío?._:",
- "squirrel"
- ],
- "positionData": {
- "GPSData": {
- "latitude": 37.871093,
- "longitude": -122.25678
- },
- "city": "test city őúéáűóöí-.,)(=",
- "country": "test country őúéáűóöí-.,)(=/%!+\"'",
- "state": "test state őúéáűóöí-.,)("
- },
- "rating": 3,
- "size": {
- "height": 10,
- "width": 14
- },
- "title": "Test caption"
-}
diff --git a/test/backend/assets/sidecar/testimagedesc2.xmp b/test/backend/assets/sidecar/testimagedesc2.xmp
deleted file mode 100644
index ca499497..00000000
--- a/test/backend/assets/sidecar/testimagedesc2.xmp
+++ /dev/null
@@ -1,139 +0,0 @@
-
-
-
-
-
- US
- Sublocation test
-
-
-
-
-
- Patrik
-
-
-
-
- Test caption
-
-
-
-
- Copyright test
-
-
-
-
- Berkley
- USA
- special_chars űáéúőóüío?._:
- squirrel
- űáéúőóüö ŰÁÉÚŐÓÜÖ
-
-
-
-
- Test caption
-
-
-
-
-
- 40761/8200
- 1
- 0
- 2015-06-11T10:29:26
- 0230
- 0/1
- 0
- 6
- 1/800
- 28/5
-
- False
- False
- 2
- False
- 0
-
- 85/1
- 2
- 1036800/181
- 691200/119
- 90/1
- 37,52.2656N
- 122,15.4068W
- 2.2.0.0
-
-
- 3200
-
-
- 18325/3649
- 5
- 0
- 19307/2002
- 0
-
-
-
- 123063022888
- EF-S15-85mm f/3.5-5.6 IS USM
- 0000129324
-
-
- 15/1
- 85/1
- 0/0
- 0/0
-
-
- 3200
- 2
-
-
-
- test city őúéáűóöí-.,)(=
- test country őúéáűóöí-.,)(=/%!+"'
- 2015-06-11T10:29:26
- test state őúéáűóöí-.,)(
-
-
-
- Patrik
- 6
-
-
- Copyright test
-
-
-
-
- Test caption
-
-
- Canon
- óüöúőűáé ÓÜÖÚŐŰÁÉ
- 1
- 3
- Adobe Photoshop Lightroom 6.1 (Windows)
- 94/1
- 94/1
-
-
-
- 2015-06-11T10:29:26
- Adobe Photoshop Lightroom 6.1 (Windows)
- 2015-07-24T22:45:50
-
-
-
-
\ No newline at end of file
diff --git a/test/backend/assets/title_caption/description.json b/test/backend/assets/title_caption/description.json
deleted file mode 100644
index 677f3940..00000000
--- a/test/backend/assets/title_caption/description.json
+++ /dev/null
@@ -1,35 +0,0 @@
-{
- "size": {
- "width": 3144,
- "height": 2288
- },
- "creationDate": -2195790002000,
- "fileSize": 8909621,
- "keywords": [],
- "faces": [
- {
- "name": "Hulda Stein",
- "box": {
- "width": 645,
- "height": 645,
- "left": 1919,
- "top": 547
- }
- },
- {
- "name": "John Amschler",
- "box": {
- "width": 709,
- "height": 709,
- "left": 544,
- "top": 394
- }
- }
- ],
- "cameraData": {
- "make": "NIKON CORPORATION",
- "model": "NIKON D200"
- },
- "caption": "Hulda and John's Wedding",
- "title": "The Wedding"
-}
\ No newline at end of file
diff --git a/test/backend/assets/title_caption/description.png b/test/backend/assets/title_caption/description.png
deleted file mode 100644
index 6f906d67..00000000
Binary files a/test/backend/assets/title_caption/description.png and /dev/null differ
diff --git a/test/backend/assets/title_caption/digikam.jpg b/test/backend/assets/title_caption/digikam.jpg
deleted file mode 100644
index 534135e4..00000000
Binary files a/test/backend/assets/title_caption/digikam.jpg and /dev/null differ
diff --git a/test/backend/assets/title_caption/digikam.json b/test/backend/assets/title_caption/digikam.json
deleted file mode 100644
index 87a627a1..00000000
--- a/test/backend/assets/title_caption/digikam.json
+++ /dev/null
@@ -1,43 +0,0 @@
-{
- "cameraData": {
- "ISO": 200,
- "exposure": 0.008,
- "fStop": 2.8,
- "focalLength": 9.4,
- "make": "FUJIFILM",
- "model": "FinePix F601 ZOOM"
- },
- "creationDate": 1126423382000,
- "creationDateOffset": "+09:00",
- "fileSize": 14134,
- "size": {
- "height": 5,
- "width": 7
- },
- "title": "Digikam Title field",
- "caption": "Digikam Caption field",
- "faces": [
- {
- "box": {
- "height": 2,
- "left": 3,
- "top": 2,
- "width": 2
- },
- "name": "Æske Øllegård"
- }
- ],
- "keywords": [
- "æÆøØåÅéÉüÜäÄöÖïÏñÑ"
- ],
- "positionData": {
- "GPSData": {
- "latitude": 35.9524,
- "longitude": 139.863355
- },
- "city": "Shimizu",
- "country": "Japan",
- "state": "Chiba Ken"
- },
- "rating": 4
-}
\ No newline at end of file
diff --git a/test/backend/assets/wild-2-small.jpg b/test/backend/assets/wild-2-small.jpg
new file mode 100644
index 00000000..10ec42a6
Binary files /dev/null and b/test/backend/assets/wild-2-small.jpg differ
diff --git a/test/backend/assets/wild-2-small.jpg_original b/test/backend/assets/wild-2-small.jpg_original
new file mode 100644
index 00000000..10ec42a6
Binary files /dev/null and b/test/backend/assets/wild-2-small.jpg_original differ
diff --git a/test/backend/assets/wild-2-small.json b/test/backend/assets/wild-2-small.json
new file mode 100644
index 00000000..6dee39a6
--- /dev/null
+++ b/test/backend/assets/wild-2-small.json
@@ -0,0 +1,20 @@
+{
+ "size": {
+ "width": 306,
+ "height": 204
+ },
+ "creationDate": 1435943085000,
+ "fileSize": 62306,
+ "positionData": {
+ "country": "United States",
+ "state": "Arizona",
+ "city": "Williams"
+ },
+ "keywords": ["Akela the wolf", "Balu the bear", "Bearizona", "Hugin the raven", "USA", "USA Road trip"],
+ "cameraData": {
+ "make": "Canon",
+ "model": "Canon EOS 600D",
+ "lens": "EF-S15-85mm f/3.5-5.6 IS USM"
+ },
+ "creationDateOffset": "-07:00"
+}
\ No newline at end of file
diff --git a/test/backend/unit/model/threading/DiskManagerWorker.spec.ts b/test/backend/unit/model/threading/DiskManagerWorker.spec.ts
index a04ee32f..6f901c8d 100644
--- a/test/backend/unit/model/threading/DiskManagerWorker.spec.ts
+++ b/test/backend/unit/model/threading/DiskManagerWorker.spec.ts
@@ -24,7 +24,7 @@ describe('DiskMangerWorker', () => {
ProjectPath.ImageFolder = path.join(__dirname, '/../../../assets');
const dir = await DiskManager.scanDirectory('/');
// should match the number of media (photo/video) files in the assets folder
- expect(dir.media.length).to.be.equals(15);
+ expect(dir.media.length).to.be.equals(16);
// eslint-disable-next-line @typescript-eslint/no-var-requires
const expected = require(path.join(__dirname, '/../../../assets/test image öüóőúéáű-.,.json'));
const i = dir.media.findIndex(m => m.name === 'test image öüóőúéáű-.,.jpg');
diff --git a/test/backend/unit/model/threading/MetaDataLoader.spec.ts b/test/backend/unit/model/threading/MetaDataLoader.spec.ts
index d52ccd1d..17bc5a44 100644
--- a/test/backend/unit/model/threading/MetaDataLoader.spec.ts
+++ b/test/backend/unit/model/threading/MetaDataLoader.spec.ts
@@ -35,12 +35,6 @@ describe('MetadataLoader', () => {
expect(Utils.clone(data)).to.be.deep.equal(expected);
});
- it('should load png with description', async () => {
- const data = await MetadataLoader.loadPhotoMetadata(path.join(__dirname, '/../../../assets/title_caption/description.png'));
- const expected = require(path.join(__dirname, '/../../../assets/title_caption/description.json'));
- expect(Utils.clone(data)).to.be.deep.equal(expected);
- });
-
it('should load jpg', async () => {
const data = await MetadataLoader.loadPhotoMetadata(path.join(__dirname, '/../../../assets/test image öüóőúéáű-.,.jpg'));
const expected = require(path.join(__dirname, '/../../../assets/test image öüóőúéáű-.,.json'));
@@ -185,9 +179,9 @@ describe('MetadataLoader', () => {
const expected = require(path.join(__dirname, '/../../../assets/wild-1-small.json'));
expect(Utils.clone(data)).to.be.deep.equal(expected);
});
- it('should load image with metadata saved by digikam', async () => {
- const data = await MetadataLoader.loadPhotoMetadata(path.join(__dirname, '/../../../assets/title_caption/digikam.jpg'));
- const expected = require(path.join(__dirname, '/../../../assets/title_caption/digikam.json'));
+ it('should load wild-2-small image with xmp-CreateDate from 2015 and negative offset', async () => {
+ const data = await MetadataLoader.loadPhotoMetadata(path.join(__dirname, '/../../../assets/wild-2-small.jpg'));
+ const expected = require(path.join(__dirname, '/../../../assets/wild-2-small.json'));
expect(Utils.clone(data)).to.be.deep.equal(expected);
});