1
0
mirror of https://github.com/bpatrik/pigallery2.git synced 2024-12-23 01:27:14 +02:00

Merge remote-tracking branch 'origin/master'

# Conflicts:
#	src/backend/model/extension/ExtensionConfigWrapper.ts
This commit is contained in:
Patrik J. Braun 2024-03-25 21:39:41 +01:00
commit 743d29b208
42 changed files with 1445 additions and 70 deletions

View File

@ -82,9 +82,14 @@ export class MetadataLoader {
if (Utils.isInt32(parseInt(stream.avg_frame_rate, 10))) {
metadata.fps = parseInt(stream.avg_frame_rate, 10) || null;
}
metadata.creationDate =
Date.parse(stream.tags.creation_time) ||
metadata.creationDate;
if (
stream.tags !== undefined &&
typeof stream.tags.creation_time === 'string'
) {
metadata.creationDate =
Date.parse(stream.tags.creation_time) ||
metadata.creationDate;
}
break;
}
}
@ -127,7 +132,7 @@ export class MetadataLoader {
try {
// search for sidecar and merge metadata
const fullPathWithoutExt = path.parse(fullPath).name;
const fullPathWithoutExt = path.join(path.parse(fullPath).dir, path.parse(fullPath).name);
const sidecarPaths = [
fullPath + '.xmp',
fullPath + '.XMP',
@ -139,18 +144,54 @@ export class MetadataLoader {
if (fs.existsSync(sidecarPath)) {
const sidecarData = await exifr.sidecar(sidecarPath);
if (sidecarData !== undefined) {
if ((sidecarData as SideCar).dc.subject !== undefined) {
if (metadata.keywords === undefined) {
metadata.keywords = [];
}
for (const kw of (sidecarData as SideCar).dc.subject) {
if (metadata.keywords.indexOf(kw) === -1) {
metadata.keywords.push(kw);
if ((sidecarData as SideCar).dc !== undefined) {
if ((sidecarData as SideCar).dc.subject !== undefined) {
if (metadata.keywords === undefined) {
metadata.keywords = [];
}
let keywords = (sidecarData as SideCar).dc.subject || [];
if (typeof keywords === 'string') {
keywords = [keywords];
}
for (const kw of keywords) {
if (metadata.keywords.indexOf(kw) === -1) {
metadata.keywords.push(kw);
}
}
}
}
if ((sidecarData as SideCar).xmp.Rating !== undefined) {
metadata.rating = (sidecarData as SideCar).xmp.Rating;
let hasPhotoshopDate = false;
if ((sidecarData as SideCar).photoshop !== undefined) {
if ((sidecarData as SideCar).photoshop.DateCreated !== undefined) {
const date = Utils.timestampToMS((sidecarData as SideCar).photoshop.DateCreated, null);
if (date) {
metadata.creationDate = date;
hasPhotoshopDate = true;
}
}
}
if (Object.hasOwn(sidecarData, 'xap')) {
(sidecarData as any)['xmp'] = (sidecarData as any)['xap'];
delete (sidecarData as any)['xap'];
}
if ((sidecarData as SideCar).xmp !== undefined) {
if (
(sidecarData as SideCar).xmp.Rating !== undefined &&
(sidecarData as SideCar).xmp.Rating > 0
) {
metadata.rating = (sidecarData as SideCar).xmp.Rating;
}
if (
!hasPhotoshopDate && (
(sidecarData as SideCar).xmp.CreateDate !== undefined ||
(sidecarData as SideCar).xmp.ModifyDate !== undefined
)
) {
metadata.creationDate =
Utils.timestampToMS((sidecarData as SideCar).xmp.CreateDate, null) ||
Utils.timestampToMS((sidecarData as SideCar).xmp.ModifyDate, null) ||
metadata.creationDate;
}
}
}
}
@ -194,43 +235,6 @@ export class MetadataLoader {
translateValues: false, //don't translate orientation from numbers to strings etc.
mergeOutput: false //don't merge output, because things like Microsoft Rating (percent) and xmp.rating will be merged
};
//function to convert timestamp into milliseconds taking offset into account
const timestampToMS = (timestamp: string, offset: string) => {
if (!timestamp) {
return undefined;
}
//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.substring(0, formattedTimestamp.indexOf("Z")) + (offset ? offset : '+00:00');
} else if (formattedTimestamp.indexOf("+") > 0) { //don't do anything
} else { //add offset
formattedTimestamp = formattedTimestamp + (offset ? offset : '+00:00');
}
//parse into MS and return
return Date.parse(formattedTimestamp);
}
//function to calculate offset from exif.exif.gpsTimeStamp or exif.gps.GPSDateStamp + exif.gps.GPSTimestamp
const getTimeOffsetByGPSStamp = (timestamp: string, gpsTimeStamp: string, gps: any) => {
let UTCTimestamp = gpsTimeStamp;
if (!UTCTimestamp &&
gps &&
gps.GPSDateStamp &&
gps.GPSTimeStamp) { //else use exif.gps.GPS*Stamp if available
//GPS timestamp is always UTC (+00:00)
UTCTimestamp = gps.GPSDateStamp.replaceAll(':', '-') + gps.GPSTimeStamp.join(':');
}
if (UTCTimestamp && timestamp) {
//offset in minutes is the difference between gps timestamp and given timestamp
//to calculate this correctly, we have to work with the same offset
const offsetMinutes = (timestampToMS(timestamp, '+00:00')- timestampToMS(UTCTimestamp, '+00:00')) / 1000 / 60;
return Utils.getOffsetString(offsetMinutes);
} else {
return undefined;
}
}
//Function to convert html code for special characters into their corresponding character (used in exif.photoshop-section)
const unescape = (tag: string) => {
@ -364,32 +368,32 @@ export class MetadataLoader {
//DateTimeOriginal is when the camera shutter closed
let offset = exif.exif.OffsetTimeOriginal; //OffsetTimeOriginal is the corresponding offset
if (!offset) { //Find offset among other options if possible
offset = exif.exif.OffsetTimeDigitized || exif.exif.OffsetTime || getTimeOffsetByGPSStamp(exif.exif.DateTimeOriginal, exif.exif.GPSTimeStamp, exif.gps);
offset = exif.exif.OffsetTimeDigitized || exif.exif.OffsetTime || Utils.getTimeOffsetByGPSStamp(exif.exif.DateTimeOriginal, exif.exif.GPSTimeStamp, exif.gps);
}
metadata.creationDate = timestampToMS(exif.exif.DateTimeOriginal, offset);
metadata.creationDate = Utils.timestampToMS(exif.exif.DateTimeOriginal, offset);
metadata.creationDateOffset = offset;
} else if (exif.exif.CreateDate) { //using else if here, because DateTimeOriginal has preceedence
//Create is when the camera wrote the file (typically within the same ms as shutter close)
let offset = exif.exif.OffsetTimeDigitized; //OffsetTimeDigitized is the corresponding offset
if (!offset) { //Find offset among other options if possible
offset = exif.exif.OffsetTimeOriginal || exif.exif.OffsetTime || getTimeOffsetByGPSStamp(exif.exif.DateTimeOriginal, exif.exif.GPSTimeStamp, exif.gps);
offset = exif.exif.OffsetTimeOriginal || exif.exif.OffsetTime || Utils.getTimeOffsetByGPSStamp(exif.exif.DateTimeOriginal, exif.exif.GPSTimeStamp, exif.gps);
}
metadata.creationDate = timestampToMS(exif.exif.CreateDate, offset);
metadata.creationDate = Utils.timestampToMS(exif.exif.CreateDate, offset);
metadata.creationDateOffset = offset;
} else if (exif.ifd0?.ModifyDate) { //using else if here, because DateTimeOriginal and CreatDate have preceedence
let offset = exif.exif.OffsetTime; //exif.Offsettime is the offset corresponding to ifd0.ModifyDate
if (!offset) { //Find offset among other options if possible
offset = exif.exif.DateTimeOriginal || exif.exif.OffsetTimeDigitized || getTimeOffsetByGPSStamp(exif.ifd0.ModifyDate, exif.exif.GPSTimeStamp, exif.gps);
offset = exif.exif.DateTimeOriginal || exif.exif.OffsetTimeDigitized || Utils.getTimeOffsetByGPSStamp(exif.ifd0.ModifyDate, exif.exif.GPSTimeStamp, exif.gps);
}
metadata.creationDate = timestampToMS(exif.ifd0.ModifyDate, offset);
metadata.creationDate = Utils.timestampToMS(exif.ifd0.ModifyDate, offset);
metadata.creationDateOffset = offset
} else if (exif.ihdr && exif.ihdr["Creation Time"]) {// again else if (another fallback date if the good ones aren't there) {
const any_offset = exif.exif.DateTimeOriginal || exif.exif.OffsetTimeDigitized || exif.exif.OffsetTime || getTimeOffsetByGPSStamp(exif.ifd0.ModifyDate, exif.exif.GPSTimeStamp, exif.gps);
metadata.creationDate = timestampToMS(exif.ihdr["Creation Time"], any_offset);
const any_offset = exif.exif.DateTimeOriginal || exif.exif.OffsetTimeDigitized || exif.exif.OffsetTime || Utils.getTimeOffsetByGPSStamp(exif.ifd0.ModifyDate, exif.exif.GPSTimeStamp, exif.gps);
metadata.creationDate = Utils.timestampToMS(exif.ihdr["Creation Time"], any_offset);
metadata.creationDateOffset = any_offset;
} else if (exif.xmp?.MetadataDate) {// again else if (another fallback date if the good ones aren't there - metadata date is probably later than actual creation date, but much better than file time) {
const any_offset = exif.exif.DateTimeOriginal || exif.exif.OffsetTimeDigitized || exif.exif.OffsetTime || getTimeOffsetByGPSStamp(exif.ifd0.ModifyDate, exif.exif.GPSTimeStamp, exif.gps);
metadata.creationDate = timestampToMS(exif.xmp.MetadataDate, any_offset);
const any_offset = exif.exif.DateTimeOriginal || exif.exif.OffsetTimeDigitized || exif.exif.OffsetTime || Utils.getTimeOffsetByGPSStamp(exif.ifd0.ModifyDate, exif.exif.GPSTimeStamp, exif.gps);
metadata.creationDate = Utils.timestampToMS(exif.xmp.MetadataDate, any_offset);
metadata.creationDateOffset = any_offset;
}
if (exif.exif.LensModel && exif.exif.LensModel !== '') {
@ -606,7 +610,7 @@ export class MetadataLoader {
try {
// search for sidecar and merge metadata
const fullPathWithoutExt = path.parse(fullPath).name;
const fullPathWithoutExt = path.join(path.parse(fullPath).dir, path.parse(fullPath).name);
const sidecarPaths = [
fullPath + '.xmp',
fullPath + '.XMP',
@ -619,18 +623,70 @@ export class MetadataLoader {
const sidecarData = await exifr.sidecar(sidecarPath);
if (sidecarData !== undefined) {
if ((sidecarData as SideCar).dc.subject !== undefined) {
if (metadata.keywords === undefined) {
metadata.keywords = [];
}
for (const kw of (sidecarData as SideCar).dc.subject) {
if (metadata.keywords.indexOf(kw) === -1) {
metadata.keywords.push(kw);
if ((sidecarData as SideCar).dc !== undefined) {
if ((sidecarData as SideCar).dc.subject !== undefined) {
if (metadata.keywords === undefined) {
metadata.keywords = [];
}
let keywords = (sidecarData as SideCar).dc.subject || [];
if (typeof keywords === 'string') {
keywords = [keywords];
}
for (const kw of keywords) {
if (metadata.keywords.indexOf(kw) === -1) {
metadata.keywords.push(kw);
}
}
}
}
if ((sidecarData as SideCar).xmp.Rating !== undefined) {
metadata.rating = (sidecarData as SideCar).xmp.Rating;
let hasPhotoshopDate = false;
if ((sidecarData as SideCar).photoshop !== undefined) {
if ((sidecarData as SideCar).photoshop.DateCreated !== undefined) {
const date = Utils.timestampToMS((sidecarData as SideCar).photoshop.DateCreated, null);
if (date) {
metadata.creationDate = date;
hasPhotoshopDate = true;
}
}
}
if (Object.hasOwn(sidecarData, 'xap')) {
(sidecarData as any)['xmp'] = (sidecarData as any)['xap'];
delete (sidecarData as any)['xap'];
}
if ((sidecarData as SideCar).xmp !== undefined) {
if (
(sidecarData as SideCar).xmp.Rating !== undefined &&
(sidecarData as SideCar).xmp.Rating > 0
) {
metadata.rating = (sidecarData as SideCar).xmp.Rating;
}
if (
!hasPhotoshopDate && (
(sidecarData as SideCar).xmp.CreateDate !== undefined ||
(sidecarData as SideCar).xmp.ModifyDate !== undefined
)
) {
metadata.creationDate =
Utils.timestampToMS((sidecarData as SideCar).xmp.CreateDate, null) ||
Utils.timestampToMS((sidecarData as SideCar).xmp.ModifyDate, null) ||
metadata.creationDate;
}
}
if ((sidecarData as SideCar).exif !== undefined) {
if (
(sidecarData as SideCar).exif.GPSLatitude !== undefined &&
(sidecarData as SideCar).exif.GPSLongitude !== undefined
) {
metadata.positionData = metadata.positionData || {};
metadata.positionData.GPSData = {};
metadata.positionData.GPSData.longitude = Utils.xmpExifGpsCoordinateToDecimalDegrees(
(sidecarData as SideCar).exif.GPSLongitude
);
metadata.positionData.GPSData.latitude = Utils.xmpExifGpsCoordinateToDecimalDegrees(
(sidecarData as SideCar).exif.GPSLatitude
);
}
}
}
}

View File

@ -124,6 +124,43 @@ export class Utils {
return new Date(new Date(d).toISOString().substring(0,19) + (offset ? offset : '')).getFullYear();
}
//function to convert timestamp into milliseconds taking offset into account
static timestampToMS(timestamp: string, offset: string) {
if (!timestamp) {
return undefined;
}
//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.substring(0, formattedTimestamp.indexOf("Z")) + (offset ? offset : '+00:00');
} else if (formattedTimestamp.indexOf("+") > 0) { //don't do anything
} else { //add offset
formattedTimestamp = formattedTimestamp + (offset ? offset : '+00:00');
}
//parse into MS and return
return Date.parse(formattedTimestamp);
}
//function to calculate offset from exif.exif.gpsTimeStamp or exif.gps.GPSDateStamp + exif.gps.GPSTimestamp
static getTimeOffsetByGPSStamp(timestamp: string, gpsTimeStamp: string, gps: any) {
let UTCTimestamp = gpsTimeStamp;
if (!UTCTimestamp &&
gps &&
gps.GPSDateStamp &&
gps.GPSTimeStamp) { //else use exif.gps.GPS*Stamp if available
//GPS timestamp is always UTC (+00:00)
UTCTimestamp = gps.GPSDateStamp.replaceAll(':', '-') + gps.GPSTimeStamp.join(':');
}
if (UTCTimestamp && timestamp) {
//offset in minutes is the difference between gps timestamp and given timestamp
//to calculate this correctly, we have to work with the same offset
const offsetMinutes = (Utils.timestampToMS(timestamp, '+00:00')- Utils.timestampToMS(UTCTimestamp, '+00:00')) / 1000 / 60;
return Utils.getOffsetString(offsetMinutes);
} else {
return undefined;
}
}
static getOffsetString(offsetMinutes: number) {
if (-720 <= offsetMinutes && offsetMinutes <= 840) {
//valid offset is within -12 and +14 hrs (https://en.wikipedia.org/wiki/List_of_UTC_offsets)
@ -344,6 +381,14 @@ export class Utils {
}
return ret;
}
public static xmpExifGpsCoordinateToDecimalDegrees(text: string): number {
const parts = text.match(/^([0-9]+),([0-9.]+)([EWNS])$/);
const degrees: number = parseInt(parts[1], 10);
const minutes: number = parseFloat(parts[2]);
const sign = (parts[3] === "N" || parts[3] === "E") ? 1 : -1;
return sign * (degrees + (minutes / 60.0))
}
}
export class LRU<V> {

View File

@ -30,8 +30,15 @@ export interface MediaDimension {
}
export interface SideCar {
exif?: SideCarExif;
dc?: SideCarDc;
xmp?: SideCarXmp;
photoshop?: SideCarPhotoshop;
}
export interface SideCarExif {
GPSLatitude?: string;
GPSLongitude?: string;
}
export interface SideCarDc {
@ -40,6 +47,14 @@ export interface SideCarDc {
export interface SideCarXmp {
Rating?: RatingTypes;
CreateDate?: string;
ModifyDate?: string;
}
export interface SideCarPhotoshop {
// Corresponds to Exif.Photo.DateTimeOriginal. No corresponding key exists in
// the xmp namespace!
DateCreated?: string;
}
export const MediaDTOUtils = {

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -0,0 +1,73 @@
<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 4.4.0-Exiv2">
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<rdf:Description rdf:about=""
xmlns:xap="http://ns.adobe.com/xap/1.0/"
xmlns:exif="http://ns.adobe.com/exif/1.0/"
xmlns:digiKam="http://www.digikam.org/ns/1.0/"
xmlns:tiff="http://ns.adobe.com/tiff/1.0/"
xmlns:photoshop="http://ns.adobe.com/photoshop/1.0/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xap:Rating="3"
xap:CreatorTool="digiKam-8.2.0"
xap:ModifyDate="2024-01-07T11:02:59.177"
xap:CreateDate="2024-01-07T11:02:59.177"
exif:GPSVersionID="2.0.0.0"
exif:GPSLatitude="50,5.3752490N"
exif:GPSLongitude="14,23.8445710E"
exif:GPSMapDatum="WGS-84"
exif:ExifVersion="0220"
exif:PixelXDimension="10"
exif:PixelYDimension="13"
exif:ExposureTime="1/105"
exif:FNumber="220/100"
exif:ExposureProgram="2"
exif:ShutterSpeedValue="1/105"
exif:ApertureValue="227/100"
exif:BrightnessValue="0/100"
exif:ExposureBiasValue="0/100"
exif:MaxApertureValue="227/100"
exif:MeteringMode="2"
exif:FocalLength="375/100"
exif:ExposureMode="0"
exif:WhiteBalance="0"
exif:DigitalZoomRatio="100/100"
exif:FocalLengthIn35mmFilm="25"
exif:SceneCaptureType="0"
exif:ImageUniqueID="A64QLMD00YM"
tiff:ImageWidth="10"
tiff:ImageLength="13"
tiff:Orientation="1"
tiff:YCbCrPositioning="1"
tiff:XResolution="72/1"
tiff:YResolution="72/1"
tiff:ResolutionUnit="2"
tiff:Make="samsung"
tiff:Model="SM-A715F"
tiff:Software="digiKam-8.2.0"
photoshop:DateCreated="2024-01-07T11:02:59.177">
<exif:Flash
exif:Fired="False"
exif:Return="0"
exif:Mode="0"
exif:Function="False"
exif:RedEyeMode="False"/>
<exif:ISOSpeedRatings>
<rdf:Seq>
<rdf:li>40</rdf:li>
</rdf:Seq>
</exif:ISOSpeedRatings>
<digiKam:TagsList>
<rdf:Seq>
<rdf:li>Travel</rdf:li>
</rdf:Seq>
</digiKam:TagsList>
<dc:subject>
<rdf:Bag>
<rdf:li>Travel</rdf:li>
</rdf:Bag>
</dc:subject>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>
<?xpacket end="w"?>

View File

@ -0,0 +1,28 @@
{
"cameraData": {
"ISO": 40,
"exposure": 0.009524,
"fStop": 2.2,
"focalLength": 3.75,
"make": "samsung",
"model": "SM-A715F"
},
"creationDate": 1704625379177,
"creationDateOffset": "+01:00",
"fileSize": 15126,
"size": {
"height": 13,
"width": 10
},
"keywords": [
"Výlet",
"Travel"
],
"positionData": {
"GPSData": {
"latitude": 50.08958748333333,
"longitude": 14.397409516666666
}
},
"rating": 3
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View File

@ -0,0 +1,91 @@
<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 4.4.0-Exiv2">
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<rdf:Description rdf:about=""
xmlns:xmp="http://ns.adobe.com/xap/1.0/"
xmlns:exif="http://ns.adobe.com/exif/1.0/"
xmlns:digiKam="http://www.digikam.org/ns/1.0/"
xmlns:tiff="http://ns.adobe.com/tiff/1.0/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:photoshop="http://ns.adobe.com/photoshop/1.0/"
xmp:CreatorTool="NIKON Z 30 Ver.01.00 "
xmp:Rating="3"
xmp:ModifyDate="2024-03-04T12:03:45.65"
xmp:CreateDate="2024-03-04T12:03:45.65"
exif:GPSLatitude="50,5.3752490N"
exif:GPSLongitude="14,23.8445710E"
exif:GPSMapDatum="WGS-84"
exif:ExifVersion="0231"
exif:FlashpixVersion="0100"
exif:CompressedBitsPerPixel="4/1"
exif:PixelXDimension="15"
exif:PixelYDimension="10"
exif:ExposureTime="10/3200"
exif:FNumber="630/100"
exif:ExposureProgram="0"
exif:ExposureBiasValue="4/6"
exif:MeteringMode="5"
exif:LightSource="11"
exif:FocalLength="160/10"
exif:SensingMethod="2"
exif:FileSource="3"
exif:SceneType="1"
exif:CFAPattern="2 0 2 0 0 1 1 2"
exif:CustomRendered="1"
exif:ExposureMode="0"
exif:WhiteBalance="1"
exif:FocalLengthIn35mmFilm="24"
exif:SceneCaptureType="0"
exif:GainControl="0"
exif:Contrast="0"
exif:Saturation="0"
exif:Sharpness="0"
exif:SubjectDistanceRange="0"
exif:GPSVersionID="2.3.0.0"
tiff:ImageWidth="15"
tiff:ImageLength="10"
tiff:Orientation="1"
tiff:YCbCrPositioning="2"
tiff:XResolution="300/1"
tiff:YResolution="300/1"
tiff:ResolutionUnit="2"
tiff:Make="NIKON CORPORATION"
tiff:Model="NIKON Z 30"
tiff:Software="digiKam-8.2.0"
photoshop:DateCreated="2024-01-21T10:24:00.93">
<exif:Flash
exif:Fired="False"
exif:Return="0"
exif:Mode="0"
exif:Function="False"
exif:RedEyeMode="False"/>
<exif:ComponentsConfiguration>
<rdf:Seq>
<rdf:li>1</rdf:li>
<rdf:li>2</rdf:li>
<rdf:li>3</rdf:li>
<rdf:li>0</rdf:li>
</rdf:Seq>
</exif:ComponentsConfiguration>
<exif:ISOSpeedRatings>
<rdf:Seq>
<rdf:li>100</rdf:li>
</rdf:Seq>
</exif:ISOSpeedRatings>
<digiKam:TagsList>
<rdf:Seq>
<rdf:li>Travel</rdf:li>
</rdf:Seq>
</digiKam:TagsList>
<dc:creator>
<rdf:Seq/>
</dc:creator>
<dc:subject>
<rdf:Bag>
<rdf:li>Travel</rdf:li>
</rdf:Bag>
</dc:subject>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>
<?xpacket end="w"?>

View File

@ -0,0 +1,29 @@
{
"cameraData": {
"ISO": 100,
"exposure": 0.003125,
"fStop": 6.3,
"focalLength": 16,
"lens": "NIKKOR Z DX 16-50mm f/3.5-6.3 VR",
"make": "NIKON CORPORATION",
"model": "NIKON Z 30"
},
"creationDate": 1705832640930,
"creationDateOffset": "+01:00",
"fileSize": 25556,
"size": {
"height": 10,
"width": 15
},
"keywords": [
"Výlet",
"Travel"
],
"positionData": {
"GPSData": {
"latitude": 50.08958748333333,
"longitude": 14.397409516666666
}
},
"rating": 3
}

View File

@ -0,0 +1,15 @@
{
"bitRate": 184871,
"creationDate": 1706435660000,
"duration": 1000,
"fileSize": 23132,
"size": {
"height": 46,
"width": 80
},
"fps": 60000,
"keywords": [
"Travel"
],
"rating": 3
}

Binary file not shown.

View File

@ -0,0 +1,115 @@
<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 4.4.0-Exiv2">
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<rdf:Description rdf:about=""
xmlns:video="http://www.video/"
xmlns:xmpDM="http://ns.adobe.com/xmp/1.0/DynamicMedia/"
xmlns:audio="http://www.audio/"
xmlns:exif="http://ns.adobe.com/exif/1.0/"
xmlns:tiff="http://ns.adobe.com/tiff/1.0/"
xmlns:xap="http://ns.adobe.com/xap/1.0/"
xmlns:Iptc4xmpExt="http://iptc.org/std/Iptc4xmpExt/2008-02-29/"
xmlns:LImage="http://ns.leiainc.com/photos/1.0/image/"
xmlns:digiKam="http://www.digikam.org/ns/1.0/"
xmlns:photoshop="http://ns.adobe.com/photoshop/1.0/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
video:duration="1001"
video:MaxBitRate="184871"
video:StreamCount="3"
video:Codec="h264"
video:CodecDescription="H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10"
video:Format="yuv420p"
video:ColorMode="bt709"
video:ColorSpace="CCIR-709"
video:Width="80"
video:FrameWidth="80"
video:SourceImageWidth="80"
video:Height="46"
video:FrameHeight="46"
video:SourceImageHeight="46"
video:FrameSize="w:80, h:46, unit:pixels"
video:AspectRatio="80/46"
video:FrameRate="59.9401"
video:BitDepth="24"
video:Language="eng"
video:TrackCreateDate="3789284060"
video:HandlerDescription="VideoHandler"
video:MajorBrand="qt "
video:CompatibleBrands="qt niko"
video:MinorVersion="538315008"
video:Encoder="Lavf60.16.100"
video:DateTimeOriginal="2024-01-28T09:54:20"
video:DateUTC="2024-01-28T09:54:20"
video:ModificationDate="2024-01-28T09:54:20"
video:DateTimeDigitized="2024-01-28T09:54:20"
video:FileName="DSC_1928_20240128_105420_80p.mp4"
video:FileSize="0"
video:FileType="mp4"
video:MimeType="video/mp4"
xmpDM:duration="1001"
xmpDM:videoColorSpace="CCIR-709"
xmpDM:FieldOrder="Progressive"
xmpDM:videoFrameSize="w:80, h:46, unit:pixels"
xmpDM:videoPixelAspectRatio="80/46"
xmpDM:videoFrameRate="59.94"
xmpDM:videoPixelDepth="8Int"
xmpDM:shotDate="ne led 28 10:54:20 2024"
xmpDM:audioSampleRate="48000"
xmpDM:audioChannelType="Stereo"
xmpDM:audioSampleType="32Float"
audio:Codec="aac"
audio:CodecDescription="AAC (Advanced Audio Coding)"
audio:SampleRate="48000"
audio:ChannelType="Stereo"
audio:Format="fltp"
audio:SampleType="32Float"
audio:TrackLang="eng"
audio:TrackCreateDate="3789284060"
audio:HandlerDescription="SoundHandler"
exif:DateTimeOriginal="2024-01-28T09:54:20"
exif:DateTimeDigitized="2024-01-28T09:54:20"
exif:ExifVersion="0232"
exif:FlashpixVersion="0100"
exif:ColorSpace="65535"
exif:PixelXDimension="80"
exif:PixelYDimension="46"
exif:GPSVersionID="2.0.0.0"
exif:GPSLatitude="50,5.3752490N"
exif:GPSLongitude="14,23.8445710E"
exif:GPSMapDatum="WGS-84"
tiff:DateTime="2024-01-28T09:54:20"
tiff:ImageWidth="80"
tiff:ImageLength="46"
tiff:YCbCrPositioning="1"
tiff:XResolution="72/1"
tiff:YResolution="72/1"
tiff:ResolutionUnit="2"
xap:MetadataDate="2024-01-28T09:54:20"
xap:Rating="3"
xap:ModifyDate="2024-01-28T09:54:20"
xap:CreateDate="2024-01-28T09:54:20"
Iptc4xmpExt:audioBitsPerSample="16"
LImage:MinorVersion="538315008"
photoshop:DateCreated="2024-01-28T09:54:20">
<exif:ComponentsConfiguration>
<rdf:Seq>
<rdf:li>1</rdf:li>
<rdf:li>2</rdf:li>
<rdf:li>3</rdf:li>
<rdf:li>0</rdf:li>
</rdf:Seq>
</exif:ComponentsConfiguration>
<digiKam:TagsList>
<rdf:Seq>
<rdf:li>Travel</rdf:li>
</rdf:Seq>
</digiKam:TagsList>
<dc:subject>
<rdf:Bag>
<rdf:li>Travel</rdf:li>
</rdf:Bag>
</dc:subject>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>
<?xpacket end="w"?>

View File

@ -0,0 +1,15 @@
{
"bitRate": 183168,
"creationDate": 1706440145000,
"duration": 1000,
"fileSize": 22896,
"size": {
"height": 80,
"width": 46
},
"fps": 30,
"keywords": [
"Travel"
],
"rating": 3
}

Binary file not shown.

View File

@ -0,0 +1,117 @@
<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 4.4.0-Exiv2">
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<rdf:Description rdf:about=""
xmlns:video="http://www.video/"
xmlns:xmpDM="http://ns.adobe.com/xmp/1.0/DynamicMedia/"
xmlns:audio="http://www.audio/"
xmlns:exif="http://ns.adobe.com/exif/1.0/"
xmlns:tiff="http://ns.adobe.com/tiff/1.0/"
xmlns:xap="http://ns.adobe.com/xap/1.0/"
xmlns:Iptc4xmpExt="http://iptc.org/std/Iptc4xmpExt/2008-02-29/"
xmlns:LImage="http://ns.leiainc.com/photos/1.0/image/"
xmlns:digiKam="http://www.digikam.org/ns/1.0/"
xmlns:photoshop="http://ns.adobe.com/photoshop/1.0/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
video:duration="1000"
video:MaxBitRate="183168"
video:StreamCount="2"
video:Codec="h264"
video:CodecDescription="H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10"
video:Format="yuv420p"
video:ColorMode="bt709"
video:ColorSpace="CCIR-709"
video:Width="80"
video:FrameWidth="80"
video:SourceImageWidth="80"
video:Height="46"
video:FrameHeight="46"
video:SourceImageHeight="46"
video:FrameSize="w:80, h:46, unit:pixels"
video:AspectRatio="16/9"
video:FrameRate="30"
video:BitDepth="24"
video:Orientation="6"
video:Language="und"
video:TrackCreateDate="3789288545"
video:HandlerDescription="VideoHandler"
video:MajorBrand="mp42"
video:CompatibleBrands="mp42mp41isomiso2"
video:MinorVersion="0"
video:Encoder="Lavf60.16.100"
video:DateTimeOriginal="2024-01-28T11:09:05"
video:DateUTC="2024-01-28T11:09:05"
video:ModificationDate="2024-01-28T11:09:05"
video:DateTimeDigitized="2024-01-28T11:09:05"
video:FileName="20240128_120909_80p.mp4"
video:FileSize="0"
video:FileType="mp4"
video:MimeType="video/mp4"
xmpDM:duration="1000"
xmpDM:videoColorSpace="CCIR-709"
xmpDM:FieldOrder="Progressive"
xmpDM:videoFrameSize="w:80, h:46, unit:pixels"
xmpDM:videoPixelAspectRatio="16/9"
xmpDM:videoFrameRate="30"
xmpDM:videoPixelDepth="8Int"
xmpDM:shotDate="ne led 28 12:09:05 2024"
xmpDM:audioSampleRate="48000"
xmpDM:audioChannelType="Stereo"
xmpDM:audioSampleType="32Float"
audio:Codec="aac"
audio:CodecDescription="AAC (Advanced Audio Coding)"
audio:SampleRate="48000"
audio:ChannelType="Stereo"
audio:Format="fltp"
audio:SampleType="32Float"
audio:TrackLang="und"
audio:TrackCreateDate="3789288545"
audio:HandlerDescription="SoundHandler"
exif:DateTimeOriginal="2024-01-28T11:09:05"
exif:DateTimeDigitized="2024-01-28T11:09:05"
exif:ExifVersion="0232"
exif:FlashpixVersion="0100"
exif:ColorSpace="65535"
exif:PixelXDimension="80"
exif:PixelYDimension="46"
exif:GPSVersionID="2.0.0.0"
exif:GPSLatitude="50,5.3752490N"
exif:GPSLongitude="14,23.8445710E"
exif:GPSMapDatum="WGS-84"
tiff:DateTime="2024-01-28T11:09:05"
tiff:ImageWidth="81"
tiff:ImageLength="46"
tiff:Orientation="6"
tiff:YCbCrPositioning="1"
tiff:XResolution="72/1"
tiff:YResolution="72/1"
tiff:ResolutionUnit="2"
xap:MetadataDate="2024-01-28T11:09:05"
xap:Rating="3"
xap:ModifyDate="2024-01-28T11:09:05"
xap:CreateDate="2024-01-28T11:09:05"
Iptc4xmpExt:audioBitsPerSample="16"
LImage:MinorVersion="0"
photoshop:DateCreated="2024-01-28T11:09:05">
<exif:ComponentsConfiguration>
<rdf:Seq>
<rdf:li>1</rdf:li>
<rdf:li>2</rdf:li>
<rdf:li>3</rdf:li>
<rdf:li>0</rdf:li>
</rdf:Seq>
</exif:ComponentsConfiguration>
<digiKam:TagsList>
<rdf:Seq>
<rdf:li>Travel</rdf:li>
</rdf:Seq>
</digiKam:TagsList>
<dc:subject>
<rdf:Bag>
<rdf:li>Travel</rdf:li>
</rdf:Bag>
</dc:subject>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>
<?xpacket end="w"?>

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

View File

@ -0,0 +1,114 @@
<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 4.4.0-Exiv2">
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<rdf:Description rdf:about=""
xmlns:xmp="http://ns.adobe.com/xap/1.0/"
xmlns:exif="http://ns.adobe.com/exif/1.0/"
xmlns:acdsee="http://ns.acdsee.com/iptc/1.0/"
xmlns:MicrosoftPhoto="http://ns.microsoft.com/photo/1.0/"
xmlns:digiKam="http://www.digikam.org/ns/1.0/"
xmlns:lr="http://ns.adobe.com/lightroom/1.0/"
xmlns:mediapro="http://ns.iview-multimedia.com/mediapro/1.0/"
xmlns:tiff="http://ns.adobe.com/tiff/1.0/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:photoshop="http://ns.adobe.com/photoshop/1.0/"
xmp:CreatorTool="NIKON Z 30 Ver.01.00 "
xmp:Rating="3"
xmp:ModifyDate="2024-01-28T18:58:08.66"
xmp:CreateDate="2024-01-28T18:58:08.66"
exif:GPSLatitude="50,5.3752490N"
exif:GPSLongitude="14,23.8445710E"
exif:GPSMapDatum="WGS-84"
exif:ExifVersion="0231"
exif:FlashpixVersion="0100"
exif:CompressedBitsPerPixel="4/1"
exif:PixelXDimension="15"
exif:PixelYDimension="10"
exif:ExposureTime="10/250"
exif:FNumber="420/100"
exif:ExposureProgram="2"
exif:ExposureBiasValue="0/6"
exif:MeteringMode="5"
exif:LightSource="0"
exif:FocalLength="250/10"
exif:SensingMethod="2"
exif:FileSource="3"
exif:SceneType="1"
exif:CFAPattern="2 0 2 0 0 1 1 2"
exif:CustomRendered="1"
exif:ExposureMode="0"
exif:WhiteBalance="0"
exif:FocalLengthIn35mmFilm="37"
exif:SceneCaptureType="0"
exif:GainControl="2"
exif:Contrast="0"
exif:Saturation="0"
exif:Sharpness="0"
exif:SubjectDistanceRange="0"
exif:GPSVersionID="2.3.0.0"
acdsee:categories="&lt;Categories&gt;&lt;Category Assigned=&quot;1&quot;&gt;Travel&lt;/Category&gt;&lt;/Categories&gt;"
acdsee:rating="3"
MicrosoftPhoto:Rating="50"
tiff:ImageWidth="15"
tiff:ImageLength="10"
tiff:Orientation="1"
tiff:YCbCrPositioning="2"
tiff:XResolution="300/1"
tiff:YResolution="300/1"
tiff:ResolutionUnit="2"
tiff:Make="NIKON CORPORATION"
tiff:Model="NIKON Z 30"
tiff:Software="digiKam-8.2.0"
photoshop:DateCreated="2024-01-28T18:58:08.66"
photoshop:Urgency="4">
<exif:Flash
exif:Fired="False"
exif:Return="0"
exif:Mode="0"
exif:Function="False"
exif:RedEyeMode="False"/>
<exif:ComponentsConfiguration>
<rdf:Seq>
<rdf:li>1</rdf:li>
<rdf:li>2</rdf:li>
<rdf:li>3</rdf:li>
<rdf:li>0</rdf:li>
</rdf:Seq>
</exif:ComponentsConfiguration>
<exif:ISOSpeedRatings>
<rdf:Seq>
<rdf:li>25600</rdf:li>
</rdf:Seq>
</exif:ISOSpeedRatings>
<MicrosoftPhoto:LastKeywordXMP>
<rdf:Bag>
<rdf:li>Travel</rdf:li>
</rdf:Bag>
</MicrosoftPhoto:LastKeywordXMP>
<digiKam:TagsList>
<rdf:Seq>
<rdf:li>Travel</rdf:li>
</rdf:Seq>
</digiKam:TagsList>
<lr:hierarchicalSubject>
<rdf:Bag>
<rdf:li>Travel</rdf:li>
</rdf:Bag>
</lr:hierarchicalSubject>
<mediapro:CatalogSets>
<rdf:Bag>
<rdf:li>Travel</rdf:li>
</rdf:Bag>
</mediapro:CatalogSets>
<dc:creator>
<rdf:Seq/>
</dc:creator>
<dc:subject>
<rdf:Bag>
<rdf:li>Travel</rdf:li>
</rdf:Bag>
</dc:subject>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>
<?xpacket end="w"?>

View File

@ -0,0 +1,29 @@
{
"cameraData": {
"ISO": 25600,
"exposure": 0.04,
"fStop": 4.2,
"focalLength": 25,
"lens": "NIKKOR Z DX 16-50mm f/3.5-6.3 VR",
"make": "NIKON CORPORATION",
"model": "NIKON Z 30"
},
"creationDate": 1706468288660,
"creationDateOffset": "+01:00",
"fileSize": 47059,
"size": {
"height": 10,
"width": 15
},
"keywords": [
"Výlet",
"Travel"
],
"positionData": {
"GPSData": {
"latitude": 50.08958748333333,
"longitude": 14.397409516666666
}
},
"rating": 3
}

View File

@ -0,0 +1,16 @@
{
"size": {
"width": 640,
"height": 360
},
"bitRate": 1794127,
"duration": 290,
"creationDate": 1542482851000,
"fileSize": 65073,
"fps": 40000,
"keywords": [
"rabbit",
"test"
],
"rating": 4
}

Binary file not shown.

View File

@ -0,0 +1,119 @@
<?xpacket begin='' id='W5M0MpCehiHzreSzNTczkc9d'?>
<x:xmpmeta xmlns:x='adobe:ns:meta/' x:xmptk='Image::ExifTool 12.69'>
<rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'>
<rdf:Description rdf:about=''
xmlns:Iptc4xmpExt='http://iptc.org/std/Iptc4xmpExt/2008-02-29/'>
<Iptc4xmpExt:audioBitsPerSample>16</Iptc4xmpExt:audioBitsPerSample>
</rdf:Description>
<rdf:Description rdf:about=''
xmlns:LImage='http://ns.leiainc.com/photos/1.0/image/'>
<LImage:MinorVersion>0.0.0</LImage:MinorVersion>
</rdf:Description>
<rdf:Description rdf:about=''
xmlns:dc='http://purl.org/dc/elements/1.1/'>
<dc:format>H.264</dc:format>
<dc:subject>
<rdf:Bag>
<rdf:li>rabbit</rdf:li>
<rdf:li>test</rdf:li>
</rdf:Bag>
</dc:subject>
</rdf:Description>
<rdf:Description rdf:about=''
xmlns:tiff='http://ns.adobe.com/tiff/1.0/'>
<tiff:ImageLength>480</tiff:ImageLength>
<tiff:ImageWidth>852</tiff:ImageWidth>
<tiff:XResolution>72/1</tiff:XResolution>
<tiff:YResolution>72/1</tiff:YResolution>
</rdf:Description>
<rdf:Description rdf:about=''
xmlns:xmp='http://ns.adobe.com/xap/1.0/'>
<xmp:CreateDate>2018-11-17T20:27:31+01:00</xmp:CreateDate>
<xmp:MetadataDate>2018-11-17T20:27:31+01:00</xmp:MetadataDate>
<xmp:ModifyDate>2018-11-17T20:27:31+01:00</xmp:ModifyDate>
<xmp:Rating>4</xmp:Rating>
</rdf:Description>
<rdf:Description rdf:about=''
xmlns:stDim='http://ns.adobe.com/xap/1.0/sType/Dimensions#'
xmlns:xmpDM='http://ns.adobe.com/xmp/1.0/DynamicMedia/'>
<xmpDM:altTimecode rdf:parseType='Resource'>
<xmpDM:timeFormat>25Timecode</xmpDM:timeFormat>
<xmpDM:timeValue>00:00:00:00</xmpDM:timeValue>
</xmpDM:altTimecode>
<xmpDM:audioChannelType>Stereo</xmpDM:audioChannelType>
<xmpDM:audioSampleRate>48000</xmpDM:audioSampleRate>
<xmpDM:audioSampleType>16Int</xmpDM:audioSampleType>
<xmpDM:duration rdf:parseType='Resource'>
<xmpDM:scale>1/90000</xmpDM:scale>
<xmpDM:value>2928000</xmpDM:value>
</xmpDM:duration>
<xmpDM:startTimeSampleSize>1</xmpDM:startTimeSampleSize>
<xmpDM:startTimeScale>25</xmpDM:startTimeScale>
<xmpDM:startTimecode rdf:parseType='Resource'>
<xmpDM:timeFormat>25Timecode</xmpDM:timeFormat>
<xmpDM:timeValue>00:00:00:00</xmpDM:timeValue>
</xmpDM:startTimecode>
<xmpDM:videoFieldOrder>Progressive</xmpDM:videoFieldOrder>
<xmpDM:videoFrameRate>25.000000</xmpDM:videoFrameRate>
<xmpDM:videoFrameSize rdf:parseType='Resource'>
<stDim:h>480</stDim:h>
<stDim:unit>pixel</stDim:unit>
<stDim:w>852</stDim:w>
</xmpDM:videoFrameSize>
<xmpDM:videoPixelAspectRatio>1/1</xmpDM:videoPixelAspectRatio>
</rdf:Description>
<rdf:Description rdf:about=''
xmlns:stEvt='http://ns.adobe.com/xap/1.0/sType/ResourceEvent#'
xmlns:stRef='http://ns.adobe.com/xap/1.0/sType/ResourceRef#'
xmlns:xmpMM='http://ns.adobe.com/xap/1.0/mm/'>
<xmpMM:DerivedFrom rdf:parseType='Resource'>
<stRef:documentID>d47681ee-e57e-2256-f455-43c40000004b</stRef:documentID>
<stRef:instanceID>2a5a623f-09cc-ea32-5014-869400000078</stRef:instanceID>
<stRef:originalDocumentID>xmp.did:5af8e6dd-2af0-e94e-8f3c-767794b3efa1</stRef:originalDocumentID>
</xmpMM:DerivedFrom>
<xmpMM:DocumentID>b2c5763f-bfb9-7ee1-6893-05220000004b</xmpMM:DocumentID>
<xmpMM:History>
<rdf:Seq>
<rdf:li rdf:parseType='Resource'>
<stEvt:action>saved</stEvt:action>
<stEvt:changed>/</stEvt:changed>
<stEvt:instanceID>63c4c09c-9648-ee43-720e-644600000078</stEvt:instanceID>
<stEvt:softwareAgent>Adobe Adobe Media Encoder CC 2017.1 (Windows)</stEvt:softwareAgent>
<stEvt:when>2018-11-17T20:27:31+01:00</stEvt:when>
</rdf:li>
<rdf:li rdf:parseType='Resource'>
<stEvt:action>saved</stEvt:action>
<stEvt:changed>/</stEvt:changed>
<stEvt:instanceID>2a5a623f-09cc-ea32-5014-869400000078</stEvt:instanceID>
<stEvt:softwareAgent>Adobe Adobe Media Encoder CC 2017.1 (Windows)</stEvt:softwareAgent>
<stEvt:when>2018-11-17T20:26:54+01:00</stEvt:when>
</rdf:li>
<rdf:li rdf:parseType='Resource'>
<stEvt:action>saved</stEvt:action>
<stEvt:changed>/</stEvt:changed>
<stEvt:instanceID>xmp.iid:6e43712c-17f5-cc4c-b90d-766dca2590dc</stEvt:instanceID>
<stEvt:softwareAgent>Adobe Adobe Media Encoder CC 2017.1 (Windows)</stEvt:softwareAgent>
<stEvt:when>2018-11-17T20:27:31+01:00</stEvt:when>
</rdf:li>
<rdf:li rdf:parseType='Resource'>
<stEvt:action>saved</stEvt:action>
<stEvt:changed>/metadata</stEvt:changed>
<stEvt:instanceID>xmp.iid:4d4376d3-c650-354b-b4eb-0fc2d21bcaa4</stEvt:instanceID>
<stEvt:softwareAgent>Adobe Adobe Media Encoder CC 2017.1 (Windows)</stEvt:softwareAgent>
<stEvt:when>2018-11-17T20:27:31+01:00</stEvt:when>
</rdf:li>
</rdf:Seq>
</xmpMM:History>
<xmpMM:InstanceID>xmp.iid:4d4376d3-c650-354b-b4eb-0fc2d21bcaa4</xmpMM:InstanceID>
<xmpMM:OriginalDocumentID>xmp.did:1aa2d671-bf82-2043-9053-ec864079866c</xmpMM:OriginalDocumentID>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>
<?xpacket end='w'?>

View File

@ -0,0 +1,16 @@
{
"size": {
"width": 640,
"height": 360
},
"bitRate": 1794127,
"duration": 290,
"creationDate": 1542482851000,
"fileSize": 65073,
"fps": 40000,
"keywords": [
"rabbit",
"test"
],
"rating": 4
}

Binary file not shown.

View File

@ -0,0 +1,119 @@
<?xpacket begin='' id='W5M0MpCehiHzreSzNTczkc9d'?>
<x:xmpmeta xmlns:x='adobe:ns:meta/' x:xmptk='Image::ExifTool 12.69'>
<rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'>
<rdf:Description rdf:about=''
xmlns:Iptc4xmpExt='http://iptc.org/std/Iptc4xmpExt/2008-02-29/'>
<Iptc4xmpExt:audioBitsPerSample>16</Iptc4xmpExt:audioBitsPerSample>
</rdf:Description>
<rdf:Description rdf:about=''
xmlns:LImage='http://ns.leiainc.com/photos/1.0/image/'>
<LImage:MinorVersion>0.0.0</LImage:MinorVersion>
</rdf:Description>
<rdf:Description rdf:about=''
xmlns:dc='http://purl.org/dc/elements/1.1/'>
<dc:format>H.264</dc:format>
<dc:subject>
<rdf:Bag>
<rdf:li>rabbit</rdf:li>
<rdf:li>test</rdf:li>
</rdf:Bag>
</dc:subject>
</rdf:Description>
<rdf:Description rdf:about=''
xmlns:tiff='http://ns.adobe.com/tiff/1.0/'>
<tiff:ImageLength>480</tiff:ImageLength>
<tiff:ImageWidth>852</tiff:ImageWidth>
<tiff:XResolution>72/1</tiff:XResolution>
<tiff:YResolution>72/1</tiff:YResolution>
</rdf:Description>
<rdf:Description rdf:about=''
xmlns:xmp='http://ns.adobe.com/xap/1.0/'>
<xmp:CreateDate>2018-11-17T20:27:31+01:00</xmp:CreateDate>
<xmp:MetadataDate>2018-11-17T20:27:31+01:00</xmp:MetadataDate>
<xmp:ModifyDate>2018-11-17T20:27:31+01:00</xmp:ModifyDate>
<xmp:Rating>4</xmp:Rating>
</rdf:Description>
<rdf:Description rdf:about=''
xmlns:stDim='http://ns.adobe.com/xap/1.0/sType/Dimensions#'
xmlns:xmpDM='http://ns.adobe.com/xmp/1.0/DynamicMedia/'>
<xmpDM:altTimecode rdf:parseType='Resource'>
<xmpDM:timeFormat>25Timecode</xmpDM:timeFormat>
<xmpDM:timeValue>00:00:00:00</xmpDM:timeValue>
</xmpDM:altTimecode>
<xmpDM:audioChannelType>Stereo</xmpDM:audioChannelType>
<xmpDM:audioSampleRate>48000</xmpDM:audioSampleRate>
<xmpDM:audioSampleType>16Int</xmpDM:audioSampleType>
<xmpDM:duration rdf:parseType='Resource'>
<xmpDM:scale>1/90000</xmpDM:scale>
<xmpDM:value>2928000</xmpDM:value>
</xmpDM:duration>
<xmpDM:startTimeSampleSize>1</xmpDM:startTimeSampleSize>
<xmpDM:startTimeScale>25</xmpDM:startTimeScale>
<xmpDM:startTimecode rdf:parseType='Resource'>
<xmpDM:timeFormat>25Timecode</xmpDM:timeFormat>
<xmpDM:timeValue>00:00:00:00</xmpDM:timeValue>
</xmpDM:startTimecode>
<xmpDM:videoFieldOrder>Progressive</xmpDM:videoFieldOrder>
<xmpDM:videoFrameRate>25.000000</xmpDM:videoFrameRate>
<xmpDM:videoFrameSize rdf:parseType='Resource'>
<stDim:h>480</stDim:h>
<stDim:unit>pixel</stDim:unit>
<stDim:w>852</stDim:w>
</xmpDM:videoFrameSize>
<xmpDM:videoPixelAspectRatio>1/1</xmpDM:videoPixelAspectRatio>
</rdf:Description>
<rdf:Description rdf:about=''
xmlns:stEvt='http://ns.adobe.com/xap/1.0/sType/ResourceEvent#'
xmlns:stRef='http://ns.adobe.com/xap/1.0/sType/ResourceRef#'
xmlns:xmpMM='http://ns.adobe.com/xap/1.0/mm/'>
<xmpMM:DerivedFrom rdf:parseType='Resource'>
<stRef:documentID>d47681ee-e57e-2256-f455-43c40000004b</stRef:documentID>
<stRef:instanceID>2a5a623f-09cc-ea32-5014-869400000078</stRef:instanceID>
<stRef:originalDocumentID>xmp.did:5af8e6dd-2af0-e94e-8f3c-767794b3efa1</stRef:originalDocumentID>
</xmpMM:DerivedFrom>
<xmpMM:DocumentID>b2c5763f-bfb9-7ee1-6893-05220000004b</xmpMM:DocumentID>
<xmpMM:History>
<rdf:Seq>
<rdf:li rdf:parseType='Resource'>
<stEvt:action>saved</stEvt:action>
<stEvt:changed>/</stEvt:changed>
<stEvt:instanceID>63c4c09c-9648-ee43-720e-644600000078</stEvt:instanceID>
<stEvt:softwareAgent>Adobe Adobe Media Encoder CC 2017.1 (Windows)</stEvt:softwareAgent>
<stEvt:when>2018-11-17T20:27:31+01:00</stEvt:when>
</rdf:li>
<rdf:li rdf:parseType='Resource'>
<stEvt:action>saved</stEvt:action>
<stEvt:changed>/</stEvt:changed>
<stEvt:instanceID>2a5a623f-09cc-ea32-5014-869400000078</stEvt:instanceID>
<stEvt:softwareAgent>Adobe Adobe Media Encoder CC 2017.1 (Windows)</stEvt:softwareAgent>
<stEvt:when>2018-11-17T20:26:54+01:00</stEvt:when>
</rdf:li>
<rdf:li rdf:parseType='Resource'>
<stEvt:action>saved</stEvt:action>
<stEvt:changed>/</stEvt:changed>
<stEvt:instanceID>xmp.iid:6e43712c-17f5-cc4c-b90d-766dca2590dc</stEvt:instanceID>
<stEvt:softwareAgent>Adobe Adobe Media Encoder CC 2017.1 (Windows)</stEvt:softwareAgent>
<stEvt:when>2018-11-17T20:27:31+01:00</stEvt:when>
</rdf:li>
<rdf:li rdf:parseType='Resource'>
<stEvt:action>saved</stEvt:action>
<stEvt:changed>/metadata</stEvt:changed>
<stEvt:instanceID>xmp.iid:4d4376d3-c650-354b-b4eb-0fc2d21bcaa4</stEvt:instanceID>
<stEvt:softwareAgent>Adobe Adobe Media Encoder CC 2017.1 (Windows)</stEvt:softwareAgent>
<stEvt:when>2018-11-17T20:27:31+01:00</stEvt:when>
</rdf:li>
</rdf:Seq>
</xmpMM:History>
<xmpMM:InstanceID>xmp.iid:4d4376d3-c650-354b-b4eb-0fc2d21bcaa4</xmpMM:InstanceID>
<xmpMM:OriginalDocumentID>xmp.did:1aa2d671-bf82-2043-9053-ec864079866c</xmpMM:OriginalDocumentID>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>
<?xpacket end='w'?>

View File

@ -0,0 +1,15 @@
{
"size": {
"width": 640,
"height": 360
},
"bitRate": 1794127,
"duration": 290,
"creationDate": 1542482851000,
"fileSize": 65073,
"fps": 40000,
"keywords": [
"rabbit"
],
"rating": 4
}

Binary file not shown.

View File

@ -0,0 +1,118 @@
<?xpacket begin='' id='W5M0MpCehiHzreSzNTczkc9d'?>
<x:xmpmeta xmlns:x='adobe:ns:meta/' x:xmptk='Image::ExifTool 12.69'>
<rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'>
<rdf:Description rdf:about=''
xmlns:Iptc4xmpExt='http://iptc.org/std/Iptc4xmpExt/2008-02-29/'>
<Iptc4xmpExt:audioBitsPerSample>16</Iptc4xmpExt:audioBitsPerSample>
</rdf:Description>
<rdf:Description rdf:about=''
xmlns:LImage='http://ns.leiainc.com/photos/1.0/image/'>
<LImage:MinorVersion>0.0.0</LImage:MinorVersion>
</rdf:Description>
<rdf:Description rdf:about=''
xmlns:dc='http://purl.org/dc/elements/1.1/'>
<dc:format>H.264</dc:format>
<dc:subject>
<rdf:Bag>
<rdf:li>rabbit</rdf:li>
</rdf:Bag>
</dc:subject>
</rdf:Description>
<rdf:Description rdf:about=''
xmlns:tiff='http://ns.adobe.com/tiff/1.0/'>
<tiff:ImageLength>480</tiff:ImageLength>
<tiff:ImageWidth>852</tiff:ImageWidth>
<tiff:XResolution>72/1</tiff:XResolution>
<tiff:YResolution>72/1</tiff:YResolution>
</rdf:Description>
<rdf:Description rdf:about=''
xmlns:xmp='http://ns.adobe.com/xap/1.0/'>
<xmp:CreateDate>2018-11-17T20:27:31+01:00</xmp:CreateDate>
<xmp:MetadataDate>2018-11-17T20:27:31+01:00</xmp:MetadataDate>
<xmp:ModifyDate>2018-11-17T20:27:31+01:00</xmp:ModifyDate>
<xmp:Rating>4</xmp:Rating>
</rdf:Description>
<rdf:Description rdf:about=''
xmlns:stDim='http://ns.adobe.com/xap/1.0/sType/Dimensions#'
xmlns:xmpDM='http://ns.adobe.com/xmp/1.0/DynamicMedia/'>
<xmpDM:altTimecode rdf:parseType='Resource'>
<xmpDM:timeFormat>25Timecode</xmpDM:timeFormat>
<xmpDM:timeValue>00:00:00:00</xmpDM:timeValue>
</xmpDM:altTimecode>
<xmpDM:audioChannelType>Stereo</xmpDM:audioChannelType>
<xmpDM:audioSampleRate>48000</xmpDM:audioSampleRate>
<xmpDM:audioSampleType>16Int</xmpDM:audioSampleType>
<xmpDM:duration rdf:parseType='Resource'>
<xmpDM:scale>1/90000</xmpDM:scale>
<xmpDM:value>2928000</xmpDM:value>
</xmpDM:duration>
<xmpDM:startTimeSampleSize>1</xmpDM:startTimeSampleSize>
<xmpDM:startTimeScale>25</xmpDM:startTimeScale>
<xmpDM:startTimecode rdf:parseType='Resource'>
<xmpDM:timeFormat>25Timecode</xmpDM:timeFormat>
<xmpDM:timeValue>00:00:00:00</xmpDM:timeValue>
</xmpDM:startTimecode>
<xmpDM:videoFieldOrder>Progressive</xmpDM:videoFieldOrder>
<xmpDM:videoFrameRate>25.000000</xmpDM:videoFrameRate>
<xmpDM:videoFrameSize rdf:parseType='Resource'>
<stDim:h>480</stDim:h>
<stDim:unit>pixel</stDim:unit>
<stDim:w>852</stDim:w>
</xmpDM:videoFrameSize>
<xmpDM:videoPixelAspectRatio>1/1</xmpDM:videoPixelAspectRatio>
</rdf:Description>
<rdf:Description rdf:about=''
xmlns:stEvt='http://ns.adobe.com/xap/1.0/sType/ResourceEvent#'
xmlns:stRef='http://ns.adobe.com/xap/1.0/sType/ResourceRef#'
xmlns:xmpMM='http://ns.adobe.com/xap/1.0/mm/'>
<xmpMM:DerivedFrom rdf:parseType='Resource'>
<stRef:documentID>d47681ee-e57e-2256-f455-43c40000004b</stRef:documentID>
<stRef:instanceID>2a5a623f-09cc-ea32-5014-869400000078</stRef:instanceID>
<stRef:originalDocumentID>xmp.did:5af8e6dd-2af0-e94e-8f3c-767794b3efa1</stRef:originalDocumentID>
</xmpMM:DerivedFrom>
<xmpMM:DocumentID>b2c5763f-bfb9-7ee1-6893-05220000004b</xmpMM:DocumentID>
<xmpMM:History>
<rdf:Seq>
<rdf:li rdf:parseType='Resource'>
<stEvt:action>saved</stEvt:action>
<stEvt:changed>/</stEvt:changed>
<stEvt:instanceID>63c4c09c-9648-ee43-720e-644600000078</stEvt:instanceID>
<stEvt:softwareAgent>Adobe Adobe Media Encoder CC 2017.1 (Windows)</stEvt:softwareAgent>
<stEvt:when>2018-11-17T20:27:31+01:00</stEvt:when>
</rdf:li>
<rdf:li rdf:parseType='Resource'>
<stEvt:action>saved</stEvt:action>
<stEvt:changed>/</stEvt:changed>
<stEvt:instanceID>2a5a623f-09cc-ea32-5014-869400000078</stEvt:instanceID>
<stEvt:softwareAgent>Adobe Adobe Media Encoder CC 2017.1 (Windows)</stEvt:softwareAgent>
<stEvt:when>2018-11-17T20:26:54+01:00</stEvt:when>
</rdf:li>
<rdf:li rdf:parseType='Resource'>
<stEvt:action>saved</stEvt:action>
<stEvt:changed>/</stEvt:changed>
<stEvt:instanceID>xmp.iid:6e43712c-17f5-cc4c-b90d-766dca2590dc</stEvt:instanceID>
<stEvt:softwareAgent>Adobe Adobe Media Encoder CC 2017.1 (Windows)</stEvt:softwareAgent>
<stEvt:when>2018-11-17T20:27:31+01:00</stEvt:when>
</rdf:li>
<rdf:li rdf:parseType='Resource'>
<stEvt:action>saved</stEvt:action>
<stEvt:changed>/metadata</stEvt:changed>
<stEvt:instanceID>xmp.iid:4d4376d3-c650-354b-b4eb-0fc2d21bcaa4</stEvt:instanceID>
<stEvt:softwareAgent>Adobe Adobe Media Encoder CC 2017.1 (Windows)</stEvt:softwareAgent>
<stEvt:when>2018-11-17T20:27:31+01:00</stEvt:when>
</rdf:li>
</rdf:Seq>
</xmpMM:History>
<xmpMM:InstanceID>xmp.iid:4d4376d3-c650-354b-b4eb-0fc2d21bcaa4</xmpMM:InstanceID>
<xmpMM:OriginalDocumentID>xmp.did:1aa2d671-bf82-2043-9053-ec864079866c</xmpMM:OriginalDocumentID>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>
<?xpacket end='w'?>

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

@ -0,0 +1,12 @@
{
"size": {
"width": 10,
"height": 5
},
"creationDate": 1710188754000,
"fileSize": 5095,
"keywords": [
"floor",
"book"
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

@ -0,0 +1,14 @@
{
"size": {
"width": 10,
"height": 5
},
"creationDate": 1710188754000,
"fileSize": 5095,
"keywords": [
"floor",
"book",
"first",
"second"
]
}

View File

@ -0,0 +1,18 @@
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 6.0.0">
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<rdf:Description rdf:about=""
xmlns:xmp="http://ns.adobe.com/xap/1.0/"
xmlns:MicrosoftPhoto="http://ns.microsoft.com/photo/1.0/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:lr="http://ns.adobe.com/lightroom/1.0/">
<xmp:Rating>0</xmp:Rating>
<MicrosoftPhoto:Rating>0</MicrosoftPhoto:Rating>
<dc:subject>
<rdf:Bag>
<rdf:li>first</rdf:li>
<rdf:li>second</rdf:li>
</rdf:Bag>
</dc:subject>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -0,0 +1,24 @@
<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 4.4.0-Exiv2">
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<rdf:Description rdf:about=""
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:fstop="http://www.fstopapp.com/xmp/"
fstop:favorite="0">
<dc:subject>
<rdf:Bag>
<rdf:li>first</rdf:li>
<rdf:li>second</rdf:li>
</rdf:Bag>
</dc:subject>
</rdf:Description>
<rdf:Description rdf:about=''
xmlns:xmp='http://ns.adobe.com/xap/1.0/'>
<xmp:CreateDate>2018-11-17T20:27:31+01:00</xmp:CreateDate>
<xmp:MetadataDate>2018-11-17T20:27:31+01:00</xmp:MetadataDate>
<xmp:ModifyDate>2018-11-17T20:27:31+01:00</xmp:ModifyDate>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>
<?xpacket end="w"?>

View File

@ -0,0 +1,12 @@
{
"size": {
"width": 10,
"height": 5
},
"creationDate": 1542482851000,
"fileSize": 1430,
"keywords": [
"first",
"second"
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -0,0 +1,12 @@
{
"size": {
"width": 10,
"height": 5
},
"creationDate": 1542482851000,
"fileSize": 1430,
"keywords": [
"first",
"second"
]
}

View File

@ -0,0 +1,23 @@
<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 4.4.0-Exiv2">
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<rdf:Description rdf:about=""
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:fstop="http://www.fstopapp.com/xmp/"
fstop:favorite="0">
<dc:subject>
<rdf:Bag>
<rdf:li>first</rdf:li>
<rdf:li>second</rdf:li>
</rdf:Bag>
</dc:subject>
</rdf:Description>
<rdf:Description rdf:about=''
xmlns:xmp='http://ns.adobe.com/xap/1.0/'>
<xmp:CreateDate>2018-11-17T20:27:31+01:00</xmp:CreateDate>
<xmp:MetadataDate>2018-11-17T20:27:31+01:00</xmp:MetadataDate>
<xmp:ModifyDate>2018-11-17T20:27:31+01:00</xmp:ModifyDate>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>
<?xpacket end="w"?>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -0,0 +1,11 @@
{
"size": {
"width": 10,
"height": 5
},
"creationDate": 1542482851000,
"fileSize": 1430,
"keywords": [
"first"
]
}

View File

@ -0,0 +1,22 @@
<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 4.4.0-Exiv2">
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<rdf:Description rdf:about=""
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:fstop="http://www.fstopapp.com/xmp/"
fstop:favorite="0">
<dc:subject>
<rdf:Bag>
<rdf:li>first</rdf:li>
</rdf:Bag>
</dc:subject>
</rdf:Description>
<rdf:Description rdf:about=''
xmlns:xmp='http://ns.adobe.com/xap/1.0/'>
<xmp:CreateDate>2018-11-17T20:27:31+01:00</xmp:CreateDate>
<xmp:MetadataDate>2018-11-17T20:27:31+01:00</xmp:MetadataDate>
<xmp:ModifyDate>2018-11-17T20:27:31+01:00</xmp:ModifyDate>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>
<?xpacket end="w"?>

View File

@ -5,6 +5,7 @@ import {Utils} from '../../../../../src/common/Utils';
import * as path from 'path';
import * as fs from 'fs';
import {PhotoProcessing} from '../../../../../src/backend/model/fileaccess/fileprocessing/PhotoProcessing';
import {VideoProcessing} from '../../../../../src/backend/model/fileaccess/fileprocessing/VideoProcessing';
import {Config} from '../../../../../src/common/config/private/Config';
import {DatabaseType} from '../../../../../src/common/config/private/PrivateConfig';
@ -99,6 +100,67 @@ describe('MetadataLoader', () => {
const expected = require(path.join(__dirname, '/../../../assets/timestamps/big_ben_only_time.json'));
expect(Utils.clone(data)).to.be.deep.equal(expected);
});
it('should load sidecar file with file extension for video', async () => {
const data = await MetadataLoader.loadVideoMetadata(path.join(__dirname, '/../../../assets/sidecar/bunny_1sec.mp4'));
const expected = require(path.join(__dirname, '/../../../assets/sidecar/bunny_1sec.json'));
expect(Utils.clone(data)).to.be.deep.equal(expected);
});
it('should load sidecar file without file extension for video', async () => {
const data = await MetadataLoader.loadVideoMetadata(path.join(__dirname, '/../../../assets/sidecar/bunny_1sec_v2.mp4'));
const expected = require(path.join(__dirname, '/../../../assets/sidecar/bunny_1sec.json'));//sidecar "bunny_1sec_v2.xmp" is identical to "bunny_1sec.mp4.xmp" so we expect the same result
expect(Utils.clone(data)).to.be.deep.equal(expected);
});
it('should retrieve both keywords from sidecar file for video', async () => {
const data = await MetadataLoader.loadVideoMetadata(path.join(__dirname, '/../../../assets/sidecar/bunny_1sec.mp4'));
const expected = require(path.join(__dirname, '/../../../assets/sidecar/bunny_1sec.json'));
expect(Utils.clone(data)).to.be.deep.equal(expected);
});
it('should retrieve one keyword from sidecar file for video', async () => {
const data = await MetadataLoader.loadVideoMetadata(path.join(__dirname, '/../../../assets/sidecar/bunny_1sec_v3.mp4'));
const expected = require(path.join(__dirname, '/../../../assets/sidecar/bunny_1sec_v3.json'));
expect(Utils.clone(data)).to.be.deep.equal(expected);
});
it('should load sidecar file with file extension for photo', async () => {
const data = await MetadataLoader.loadPhotoMetadata(path.join(__dirname, '/../../../assets/sidecar/no_metadata.jpg'));
const expected = require(path.join(__dirname, '/../../../assets/sidecar/no_metadata.json'));
expect(Utils.clone(data)).to.be.deep.equal(expected);
});
it('should load sidecar file without file extension for photo', async () => {
const data = await MetadataLoader.loadPhotoMetadata(path.join(__dirname, '/../../../assets/sidecar/no_metadata_v2.jpg'));
const expected = require(path.join(__dirname, '/../../../assets/sidecar/no_metadata_v2.json'));
expect(Utils.clone(data)).to.be.deep.equal(expected);
});
it('should retrieve both keywords from sidecar file for photo', async () => {
const data = await MetadataLoader.loadPhotoMetadata(path.join(__dirname, '/../../../assets/sidecar/no_metadata.jpg'));
const expected = require(path.join(__dirname, '/../../../assets/sidecar/no_metadata.json'));
expect(Utils.clone(data)).to.be.deep.equal(expected);
});
it('should retrieve one keyword from sidecar file for photo', async () => {
const data = await MetadataLoader.loadPhotoMetadata(path.join(__dirname, '/../../../assets/sidecar/no_metadata_v3.jpg'));
const expected = require(path.join(__dirname, '/../../../assets/sidecar/no_metadata_v3.json'));
expect(Utils.clone(data)).to.be.deep.equal(expected);
});
it('should read keywords from photo without sidecar file', async () => {
const data = await MetadataLoader.loadPhotoMetadata(path.join(__dirname, '/../../../assets/sidecar/metadata.jpg'));
const expected = require(path.join(__dirname, '/../../../assets/sidecar/metadata.json'));
expect(Utils.clone(data)).to.be.deep.equal(expected);
});
it('should merge keywords from photo with keywords from sidecar', async () => {
const data = await MetadataLoader.loadPhotoMetadata(path.join(__dirname, '/../../../assets/sidecar/metadata_v2.jpg'));
const expected = require(path.join(__dirname, '/../../../assets/sidecar/metadata_v2.json')); //"metadata_v2.jpg" is identical to "metadata.jpg" and "metadata_v2.xmp" contains 2 different keywords
expect(Utils.clone(data)).to.be.deep.equal(expected);
});
describe('should load jpg with proper height and orientation', () => {
it('jpg 1', async () => {
const data = await MetadataLoader.loadPhotoMetadata(path.join(__dirname, '/../../../assets/orientation/broken_orientation_exif.jpg'));
@ -196,4 +258,24 @@ describe('MetadataLoader', () => {
expect(Utils.clone(data)).to.be.deep.equal(expected);
});
describe('should load metadata from sidecar files', () => {
const root = path.join(__dirname, '/../../../assets/sidecar');
const files = fs.readdirSync(root);
for (const item of files) {
const fullFilePath = path.join(root, item);
if (PhotoProcessing.isPhoto(fullFilePath)) {
it(item, async () => {
const data = await MetadataLoader.loadPhotoMetadata(fullFilePath);
const expected = require(fullFilePath.split('.').slice(0, -1).join('.') + '.json');
expect(Utils.clone(data)).to.be.deep.equal(expected);
});
} else if (VideoProcessing.isVideo(fullFilePath)) {
it(item, async () => {
const data = await MetadataLoader.loadVideoMetadata(fullFilePath);
const expected = require(fullFilePath.split('.').slice(0, -1).join('.') + '.json');
expect(Utils.clone(data)).to.be.deep.equal(expected);
});
}
}
});
});