Compare commits

..

58 Commits

Author SHA1 Message Date
Rhet Turnbull
2f866256ad version bump 2021-01-18 23:26:08 -08:00
Rhet Turnbull
86018d5cc0 Fixed face regions for exif orientation 6, 8 2021-01-18 23:25:32 -08:00
Rhet Turnbull
d657fc6ccd Updated CHANGELOG.md, [skip ci] 2021-01-18 12:09:57 -08:00
Rhet Turnbull
875f79b92d Fixed face region orientation 2021-01-18 12:02:33 -08:00
Rhet Turnbull
3a110bb6d3 Updated documentation for new face region properties 2021-01-18 09:14:29 -08:00
Rhet Turnbull
e73327c164 Updated CHANGELOG.md, [skip ci] 2021-01-18 09:00:58 -08:00
Rhet Turnbull
3799594473 Beta fix for Digikam reading XMP 2021-01-18 08:55:44 -08:00
Rhet Turnbull
db430173b5 Add @martinhrpi as a contributor 2021-01-18 07:32:46 -08:00
Rhet Turnbull
defe5cb61a Updated CHANGELOG.md, [skip ci] 2021-01-17 19:42:23 -08:00
Rhet Turnbull
f58f8dd804 Fixed osxphotos.spec datas 2021-01-17 19:32:23 -08:00
Rhet Turnbull
2773ff7381 Added beta support for face regions in xmp 2021-01-17 19:14:21 -08:00
Rhet Turnbull
348ef54b30 Updated CHANGELOG.md, [skip ci] 2021-01-15 21:35:59 -08:00
Rhet Turnbull
9c18cee37e version bump 2021-01-15 21:21:21 -08:00
Rhet Turnbull
651ed50a07 Added isreference property and --is-reference, #321 2021-01-15 21:20:08 -08:00
Rhet Turnbull
248c95237c Updated CHANGELOG.md, [skip ci] 2021-01-15 14:34:17 -08:00
Rhet Turnbull
ddce731a5d Added retry to use_photos_export, issue #351 2021-01-15 14:13:00 -08:00
Rhet Turnbull
f662495c46 Cleaned up utils 2021-01-15 13:52:35 -08:00
Rhet Turnbull
08bc8a9723 Version bump 2021-01-15 13:50:09 -08:00
Rhet Turnbull
1fd0fe5ea4 Fixed XMP sidecars to conform with exiftool format, #349, #350 2021-01-15 13:49:26 -08:00
Rhet Turnbull
fd5976b75c Added update_readme.py to auto-build README 2021-01-15 07:26:58 -08:00
Rhet Turnbull
088476c591 Added modified.strftime template, refactored test_template.py 2021-01-13 06:19:41 -08:00
Rhet Turnbull
250697c4a2 Updated CHANGELOG.md, [skip ci] 2021-01-12 07:23:08 -08:00
Rhet Turnbull
eba796b684 Updated README.md for BigSur support 2021-01-12 07:22:14 -08:00
Rhet Turnbull
965e10e20f Fixed test for M1, added about command, closes #315 2021-01-12 07:03:07 -08:00
Rhet Turnbull
61f649e59d Update @narensankar0529 as a contributor 2021-01-12 06:19:40 -08:00
Rhet Turnbull
165f9b08f5 Fixed time zone for tests 2021-01-11 21:42:03 -08:00
Rhet Turnbull
039118c1aa Add @narensankar0529 as a contributor 2021-01-11 21:33:06 -08:00
Rhet Turnbull
27f779b16c Added version check for M1 macs 2021-01-11 20:27:51 -08:00
Rhet Turnbull
eec960861e Updated CHANGELOG.md, [skip ci] 2021-01-11 06:49:26 -08:00
Rhet Turnbull
4d924d0826 Completed implementation of --jpeg-ext, fixed --dry-run, closes #330, #346 2021-01-11 06:45:35 -08:00
Rhet Turnbull
55c088eea2 Added --jpeg-ext, implements #330 2021-01-10 09:44:42 -08:00
Rhet Turnbull
ee2750224a Updated CHANGELOG.md, [skip ci] 2021-01-09 18:03:21 -08:00
Rhet Turnbull
db1947dd1e Fixed leaky memory in PhotoKit, issue #276 2021-01-09 17:24:06 -08:00
Rhet Turnbull
248fdbcf02 Updated CHANGELOG.md, [skip ci] 2021-01-09 10:32:32 -08:00
Rhet Turnbull
71cb01572d Add @Rott-Apple as a contributor 2021-01-09 10:28:33 -08:00
Rhet Turnbull
51b1058785 Added PhotoInfo.visible, PhotoInfo.date_trashed, closes #333, #334 2021-01-09 10:20:13 -08:00
Rhet Turnbull
87701822ae Merge pull request #344 from kradalby/write-jpeg-memory-leak
Force cleanup of objects in write_jpeg (fix memory leak)
2021-01-09 08:47:35 -08:00
Kristoffer Dalby
b67f11a3bb Force cleanup of objects with autorelease pool
This commit puts the content of write_jpeg into a autorelease_pool context
provided by PyObjC. This essentially means that the objects should be cleaned up
when the context is exited and prevent them from leaking (memory leak).

https://pyobjc.readthedocs.io/en/latest/api/module-objc.html#memory-management
https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmAutoreleasePools.html
2021-01-09 14:44:26 +00:00
Rhet Turnbull
804e13efff Updated README [skip ci] 2021-01-08 10:24:45 -08:00
Rhet Turnbull
504b81b720 Merge pull request #328 from synox/patch-2
doc: Recorded screencast and updated of readme [skip ci]
2021-01-08 07:10:49 -08:00
Rhet Turnbull
538e8b588e Updated CHANGELOG.md, [skip ci] 2021-01-08 07:08:07 -08:00
Rhet Turnbull
c4980fc284 Added README.rst, closes #331 2021-01-08 07:04:07 -08:00
Rhet Turnbull
a7678df397 Updated tests workflow badge link 2021-01-08 06:41:05 -08:00
Rhet Turnbull
e6f45f5949 Merge branch 'master' of github.com:RhetTbull/osxphotos 2021-01-08 06:36:07 -08:00
Rhet Turnbull
f8468c63fd Renamed workflow to tests 2021-01-08 06:35:56 -08:00
Rhet Turnbull
0545d5e321 Merge pull request #343 from RhetTbull/all-contributors/add-kradalby
All contributors/add kradalby
2021-01-08 06:26:51 -08:00
Rhet Turnbull
5de9d4f90c Merge branch 'master' of github.com:RhetTbull/osxphotos 2021-01-08 06:23:25 -08:00
Rhet Turnbull
123ebb2cb7 Ensure merge_exif_keywords are str not int 2021-01-08 06:23:17 -08:00
Rhet Turnbull
2d09d382e9 skip action for all-contributors bot 2021-01-08 06:22:01 -08:00
allcontributors[bot]
5e676d3507 docs: update .all-contributorsrc [skip ci] 2021-01-08 14:16:30 +00:00
allcontributors[bot]
935865dc65 docs: update README.md [skip ci] 2021-01-08 14:16:25 +00:00
Rhet Turnbull
193f26bec8 Merge pull request #342 from kradalby/master
Ensure keyword list only contains strings, @all-contributors please add @kradalby for code
2021-01-08 06:06:17 -08:00
Kristoffer Dalby
7b6a0af314 Ensure keyword list only contains string
This commit ensures that every keyword in the keyword list that is to be written
to a sidecar or exif only contains strings. The current implementation fails
with an exception as the "sorted" functions will fail if the list contains a mix
of strings and integers.
2021-01-08 11:33:50 +00:00
Rhet Turnbull
549a9b3572 Updated CHANGELOG.md 2021-01-06 08:33:40 -08:00
Aravindo Wingeier
aba50c5c73 doc: fixed toc in readme 2021-01-03 22:40:49 +01:00
Aravindo Wingeier
8ca7719641 added screencast files 2021-01-03 22:38:38 +01:00
Aravindo Wingeier
5dc2eeaf9a Create terminalizer-demo.yml 2021-01-03 22:38:08 +01:00
Aravindo Wingeier
658e8ac096 doc: Recorded screencast and updated of readme
... to be more attractive. Inspired by https://github.com/faressoft/terminalizer/blob/master/README.md
2021-01-03 22:36:11 +01:00
161 changed files with 8200 additions and 3876 deletions

View File

@@ -128,7 +128,46 @@
"contributions": [
"doc"
]
},
{
"login": "kradalby",
"name": "Kristoffer Dalby",
"avatar_url": "https://avatars1.githubusercontent.com/u/98431?v=4",
"profile": "https://kradalby.no",
"contributions": [
"code"
]
},
{
"login": "Rott-Apple",
"name": "Rott-Apple",
"avatar_url": "https://avatars1.githubusercontent.com/u/67875570?v=4",
"profile": "https://github.com/Rott-Apple",
"contributions": [
"research"
]
},
{
"login": "narensankar0529",
"name": "narensankar0529",
"avatar_url": "https://avatars3.githubusercontent.com/u/74054766?v=4",
"profile": "https://github.com/narensankar0529",
"contributions": [
"bug",
"userTesting"
]
},
{
"login": "martinhrpi",
"name": "Martin",
"avatar_url": "https://avatars2.githubusercontent.com/u/19407684?v=4",
"profile": "https://github.com/martinhrpi",
"contributions": [
"research",
"userTesting"
]
}
],
"contributorsPerLine": 7
"contributorsPerLine": 7,
"skipCi": true
}

View File

@@ -6,6 +6,7 @@ jobs:
build:
runs-on: macOS-latest
if: "!contains(github.event.head_commit.message, '[skip ci]')"
strategy:
max-parallel: 4
matrix:

View File

@@ -4,6 +4,122 @@ All notable changes to this project will be documented in this file. Dates are d
Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
#### [v0.39.23](https://github.com/RhetTbull/osxphotos/compare/v0.39.22...v0.39.23)
> 18 January 2021
- Fixed face region orientation [`875f79b`](https://github.com/RhetTbull/osxphotos/commit/875f79b92d9510e59fe8ca0aa21a42abc7600f70)
- Updated documentation for new face region properties [`3a110bb`](https://github.com/RhetTbull/osxphotos/commit/3a110bb6d3d23d1c9fd8612b4201144046fed567)
#### [v0.39.22](https://github.com/RhetTbull/osxphotos/compare/v0.39.21...v0.39.22)
> 18 January 2021
- Beta fix for Digikam reading XMP [`3799594`](https://github.com/RhetTbull/osxphotos/commit/379959447373f951ffca372598ea8f1d5834fe52)
- Add @martinhrpi as a contributor [`db43017`](https://github.com/RhetTbull/osxphotos/commit/db430173b59732f944ca52b53c928370684580df)
#### [v0.39.21](https://github.com/RhetTbull/osxphotos/compare/v0.39.20...v0.39.21)
> 18 January 2021
- Added beta support for face regions in xmp [`2773ff7`](https://github.com/RhetTbull/osxphotos/commit/2773ff73815ef4667f88a45b016539e490d31769)
- Fixed osxphotos.spec datas [`f58f8dd`](https://github.com/RhetTbull/osxphotos/commit/f58f8dd804f432d07048b98e5dcedca57fec0a5e)
#### [v0.39.20](https://github.com/RhetTbull/osxphotos/compare/v0.39.19...v0.39.20)
> 16 January 2021
- Added isreference property and --is-reference, #321 [`651ed50`](https://github.com/RhetTbull/osxphotos/commit/651ed50a076bd3685c7d7a568e53960363d5c30b)
- version bump [`9c18cee`](https://github.com/RhetTbull/osxphotos/commit/9c18cee37e961d2e1059490ad1dbe4e45c501002)
#### [v0.39.19](https://github.com/RhetTbull/osxphotos/compare/v0.39.18...v0.39.19)
> 15 January 2021
- Added retry to use_photos_export, issue #351 [`ddce731`](https://github.com/RhetTbull/osxphotos/commit/ddce731a5d354e833d56a64d06cdbc39711f693e)
#### [v0.39.18](https://github.com/RhetTbull/osxphotos/compare/v0.39.17...v0.39.18)
> 15 January 2021
- Fixed XMP sidecars to conform with exiftool format, #349, #350 [`1fd0fe5`](https://github.com/RhetTbull/osxphotos/commit/1fd0fe5ea477ccea43c78086af440bd32dc702d8)
- Added update_readme.py to auto-build README [`fd5976b`](https://github.com/RhetTbull/osxphotos/commit/fd5976b75c79a3d205db2e8132c388de95632b77)
- Added modified.strftime template, refactored test_template.py [`088476c`](https://github.com/RhetTbull/osxphotos/commit/088476c59126c6d6fe75551ff122e81aababf818)
#### [v0.39.17](https://github.com/RhetTbull/osxphotos/compare/v0.39.16...v0.39.17)
> 12 January 2021
- Fixed test for M1, added about command, closes #315 [`#315`](https://github.com/RhetTbull/osxphotos/issues/315)
- Fixed time zone for tests [`165f9b0`](https://github.com/RhetTbull/osxphotos/commit/165f9b08f5056d1f0b2ca7c74cec84d42b635663)
- Add @narensankar0529 as a contributor [`039118c`](https://github.com/RhetTbull/osxphotos/commit/039118c1aaa217f46354b351ea36b0729e3e1c35)
- Update @narensankar0529 as a contributor [`61f649e`](https://github.com/RhetTbull/osxphotos/commit/61f649e59d53a3e3011602476b72cc64951d38c0)
#### [v0.39.16](https://github.com/RhetTbull/osxphotos/compare/v0.39.15...v0.39.16)
> 12 January 2021
- Added version check for M1 macs [`27f779b`](https://github.com/RhetTbull/osxphotos/commit/27f779b16c850cdbda2691e5fae8cd14405653b3)
#### [v0.39.15](https://github.com/RhetTbull/osxphotos/compare/v0.39.13...v0.39.15)
> 11 January 2021
- Completed implementation of --jpeg-ext, fixed --dry-run, closes #330, #346 [`#330`](https://github.com/RhetTbull/osxphotos/issues/330)
- Added --jpeg-ext, implements #330 [`55c088e`](https://github.com/RhetTbull/osxphotos/commit/55c088eea2ddecb14e362221da9e2a7c0f403780)
#### [v0.39.13](https://github.com/RhetTbull/osxphotos/compare/v0.39.12...v0.39.13)
> 10 January 2021
- Fixed leaky memory in PhotoKit, issue #276 [`db1947d`](https://github.com/RhetTbull/osxphotos/commit/db1947dd1e3d47a487eeb68a5ceb5f7098f1df10)
#### [v0.39.12](https://github.com/RhetTbull/osxphotos/compare/v0.39.11...v0.39.12)
> 9 January 2021
- Force cleanup of objects in write_jpeg (fix memory leak) [`#344`](https://github.com/RhetTbull/osxphotos/pull/344)
- doc: Recorded screencast and updated of readme [skip ci] [`#328`](https://github.com/RhetTbull/osxphotos/pull/328)
- Added PhotoInfo.visible, PhotoInfo.date_trashed, closes #333, #334 [`#333`](https://github.com/RhetTbull/osxphotos/issues/333)
- Force cleanup of objects with autorelease pool [`b67f11a`](https://github.com/RhetTbull/osxphotos/commit/b67f11a3bb95c08a39a185b6d884092870e949f2)
- Add @Rott-Apple as a contributor [`71cb015`](https://github.com/RhetTbull/osxphotos/commit/71cb01572d2d946df18dd7b36f95b2f2e5b48f86)
- Updated README [skip ci] [`804e13e`](https://github.com/RhetTbull/osxphotos/commit/804e13efff921ab51b996493d659b32102807a8a)
#### [v0.39.11](https://github.com/RhetTbull/osxphotos/compare/v0.39.10...v0.39.11)
> 8 January 2021
- All contributors/add kradalby [`#343`](https://github.com/RhetTbull/osxphotos/pull/343)
- Ensure keyword list only contains strings, @all-contributors please add @kradalby for code [`#342`](https://github.com/RhetTbull/osxphotos/pull/342)
- Added README.rst, closes #331 [`#331`](https://github.com/RhetTbull/osxphotos/issues/331)
- Updated tests workflow badge link [`a7678df`](https://github.com/RhetTbull/osxphotos/commit/a7678df3974ff539050f5acb4c94817f525dcd56)
- Merge branch 'master' of github.com:RhetTbull/osxphotos [`e6f45f5`](https://github.com/RhetTbull/osxphotos/commit/e6f45f59491d9e805e227af8cbf8ac08ff99fdf0)
- Renamed workflow to tests [`f8468c6`](https://github.com/RhetTbull/osxphotos/commit/f8468c63fda930216f73ad5aa8c4aa92edf1adf2)
- Merge branch 'master' of github.com:RhetTbull/osxphotos [`5de9d4f`](https://github.com/RhetTbull/osxphotos/commit/5de9d4f90c1102c4fb0099befd6142180f32df3f)
- Ensure merge_exif_keywords are str not int [`123ebb2`](https://github.com/RhetTbull/osxphotos/commit/123ebb2cb752bb94291ac2b77e4a327cee996df1)
#### [v0.39.10](https://github.com/RhetTbull/osxphotos/compare/v0.39.9...v0.39.10)
> 6 January 2021
- Refactored ExportResults [`568d1b3`](https://github.com/RhetTbull/osxphotos/commit/568d1b36a631df33317dc00f27126b507c90bf51)
- Improved handling of deleted photos, #332 [`792247b`](https://github.com/RhetTbull/osxphotos/commit/792247b51cc2263221ba8c2e741d2ec454c75ca8)
- Added error_str to ExportResults [`d78097c`](https://github.com/RhetTbull/osxphotos/commit/d78097ccc0686680baf5fffa91f9e082e44b576e)
#### [v0.39.9](https://github.com/RhetTbull/osxphotos/compare/v0.39.8...v0.39.9)
> 4 January 2021
- Added test for Big Sur 16.0.1 database changes [`7deac58`](https://github.com/RhetTbull/osxphotos/commit/7deac581b1f1fb3dc59885b6e1ab9a63b382408d)
- Create terminalizer-demo.yml [`5dc2eea`](https://github.com/RhetTbull/osxphotos/commit/5dc2eeaf9a7265873c81db23bbc86d3023189a26)
- doc: Recorded screencast and updated of readme [`658e8ac`](https://github.com/RhetTbull/osxphotos/commit/658e8ac096d141fce48483dbfc1426bea317d806)
#### [v0.39.8](https://github.com/RhetTbull/osxphotos/compare/v0.39.7...v0.39.8)
> 3 January 2021
- Updated README, version [`b93d682`](https://github.com/RhetTbull/osxphotos/commit/b93d6822ac5366c57d9142cba9b809b4ab99ad98)
#### [v0.39.7](https://github.com/RhetTbull/osxphotos/compare/v0.39.6...v0.39.7)
> 3 January 2021

View File

@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2019 Rhet Turnbull
Copyright (c) 2019-2021 Rhet Turnbull
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

954
README.md

File diff suppressed because it is too large Load Diff

271
README.rst Normal file
View File

@@ -0,0 +1,271 @@
.. role:: raw-html-m2r(raw)
:format: html
OSXPhotos
=========
What is osxphotos?
------------------
OSXPhotos provides both the ability to interact with and query Apple's Photos.app library on macOS directly from your python code
as well as a very flexible command line interface (CLI) app for exporting photos.
You can query the Photos library database -- for example, file name, file path, and metadata such as keywords/tags, persons/faces, albums, etc.
You can also easily export both the original and edited photos.
Supported operating systems
---------------------------
Only works on macOS (aka Mac OS X). Tested on macOS Sierra (10.12.6) until macOS Catalina (10.15.7).
Beta support for macOS Big Sur (10.16.01/11.01).
This package will read Photos databases for any supported version on any supported macOS version.
E.g. you can read a database created with Photos 5.0 on MacOS 10.15 on a machine running macOS 10.12 and vice versa.
Requires python >= ``3.7``.
Installation
------------
If you are new to python and just want to use the command line application, I recommend you to install using pipx. See other advanced options below.
Installation using pipx
^^^^^^^^^^^^^^^^^^^^^^^
If you aren't familiar with installing python applications, I recommend you install ``osxphotos`` with `pipx <https://github.com/pipxproject/pipx>`_. If you use ``pipx``\ , you will not need to create a virtual environment as ``pipx`` takes care of this. The easiest way to do this on a Mac is to use `homebrew <https://brew.sh/>`_\ :
* Open ``Terminal`` (search for ``Terminal`` in Spotlight or look in ``Applications/Utilities``\ )
* Install ``homebrew`` according to instructions at `https://brew.sh/ <https://brew.sh/>`_
* Type the following into Terminal: ``brew install pipx``
* Then type this: ``pipx install osxphotos``
* Now you should be able to run ``osxphotos`` by typing: ``osxphotos``
Installation using pip
^^^^^^^^^^^^^^^^^^^^^^
You can also install directly from `pypi <https://pypi.org/project/osxphotos/>`_\ :
.. code-block::
pip install osxphotos
Installation from git repository
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
OSXPhotos uses setuptools, thus simply run:
.. code-block::
git clone https://github.com/RhetTbull/osxphotos.git
cd osxphotos
python3 setup.py install
I recommend you create a `virtual environment <https://docs.python.org/3/tutorial/venv.html>`_ before installing osxphotos.
**WARNING** The git repo for this project is very large (> 1GB) because it contains multiple Photos libraries used for testing
on different versions of macOS. If you just want to use the osxphotos package in your own code,
I recommend you install the latest version from `PyPI <https://pypi.org/project/osxphotos/>`_ which does not include all the test
libraries. If you just want to use the command line utility, you can download a pre-built executable of the latest
`release <https://github.com/RhetTbull/osxphotos/releases>`_ or you can install via ``pip`` which also installs the command line app.
If you aren't comfortable with running python on your Mac, start with the pre-built executable or ``pipx`` as described above.
Command Line Usage
------------------
This package will install a command line utility called ``osxphotos`` that allows you to query the Photos database and export photos.
Alternatively, you can also run the command line utility like this: ``python3 -m osxphotos``
.. code-block::
> osxphotos
Usage: osxphotos [OPTIONS] COMMAND [ARGS]...
Options:
--db <Photos database path> Specify Photos database path. Path to Photos
library/database can be specified using either
--db or directly as PHOTOS_LIBRARY positional
argument. If neither --db or PHOTOS_LIBRARY
provided, will attempt to find the library to
use in the following order: 1. last opened
library, 2. system library, 3.
~/Pictures/Photos Library.photoslibrary
--json Print output in JSON format.
-v, --version Show the version and exit.
-h, --help Show this message and exit.
Commands:
about Print information about osxphotos including license.
albums Print out albums found in the Photos library.
dump Print list of all photos & associated info from the Photos...
export Export photos from the Photos database.
help Print help; for help on commands: help <command>.
info Print out descriptive info of the Photos library database.
keywords Print out keywords found in the Photos library.
labels Print out image classification labels found in the Photos...
list Print list of Photos libraries found on the system.
persons Print out persons (faces) found in the Photos library.
places Print out places found in the Photos library.
query Query the Photos database using 1 or more search options; if...
To get help on a specific command, use ``osxphotos help <command_name>``
Command line examples
^^^^^^^^^^^^^^^^^^^^^
export all photos to ~/Desktop/export group in folders by date created
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
``osxphotos export --export-by-date ~/Pictures/Photos\ Library.photoslibrary ~/Desktop/export``
**Note**\ : Photos library/database path can also be specified using ``--db`` option:
``osxphotos export --export-by-date --db ~/Pictures/Photos\ Library.photoslibrary ~/Desktop/export``
find all photos with keyword "Kids" and output results to json file named results.json:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
``osxphotos query --keyword Kids --json ~/Pictures/Photos\ Library.photoslibrary >results.json``
export photos to file structure based on 4-digit year and full name of month of photo's creation date:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
``osxphotos export ~/Desktop/export --directory "{created.year}/{created.month}"``
(by default, it will attempt to use the system library)
export photos to file structure based on 4-digit year of photo's creation date and add keywords for media type and labels (labels are only awailable on Photos 5 and higher):
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
``osxphotos export ~/Desktop/export --directory "{created.year}" --keyword-template "{label}" --keyword-template "{media_type}"``
export default library using 'country name/year' as output directory (but use "NoCountry/year" if country not specified), add persons, album names, and year as keywords, write exif metadata to files when exporting, update only changed files, print verbose ouput
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
``osxphotos export ~/Desktop/export --directory "{place.name.country,NoCountry}/{created.year}" --person-keyword --album-keyword --keyword-template "{created.year}" --exiftool --update --verbose``
Example uses of the package
---------------------------
.. code-block:: python
""" Simple usage of the package """
import osxphotos
def main():
photosdb = osxphotos.PhotosDB()
print(photosdb.keywords)
print(photosdb.persons)
print(photosdb.album_names)
print(photosdb.keywords_as_dict)
print(photosdb.persons_as_dict)
print(photosdb.albums_as_dict)
# find all photos with Keyword = Foo and containing John Smith
photos = photosdb.photos(keywords=["Foo"],persons=["John Smith"])
# find all photos that include Alice Smith but do not contain the keyword Bar
photos = [p for p in photosdb.photos(persons=["Alice Smith"])
if p not in photosdb.photos(keywords=["Bar"]) ]
for p in photos:
print(
p.uuid,
p.filename,
p.original_filename,
p.date,
p.description,
p.title,
p.keywords,
p.albums,
p.persons,
p.path,
)
if __name__ == "__main__":
main()
.. code-block:: python
""" Export all photos to specified directory using album names as folders
If file has been edited, also export the edited version,
otherwise, export the original version
This will result in duplicate photos if photo is in more than album """
import os.path
import pathlib
import sys
import click
from pathvalidate import is_valid_filepath, sanitize_filepath
import osxphotos
@click.command()
@click.argument("export_path", type=click.Path(exists=True))
@click.option(
"--default-album",
help="Default folder for photos with no album. Defaults to 'unfiled'",
default="unfiled",
)
@click.option(
"--library-path",
help="Path to Photos library, default to last used library",
default=None,
)
def export(export_path, default_album, library_path):
export_path = os.path.expanduser(export_path)
library_path = os.path.expanduser(library_path) if library_path else None
if library_path is not None:
photosdb = osxphotos.PhotosDB(library_path)
else:
photosdb = osxphotos.PhotosDB()
photos = photosdb.photos()
for p in photos:
if not p.ismissing:
albums = p.albums
if not albums:
albums = [default_album]
for album in albums:
click.echo(f"exporting {p.filename} in album {album}")
# make sure no invalid characters in destination path (could be in album name)
album_name = sanitize_filepath(album, platform="auto")
# create destination folder, if necessary, based on album name
dest_dir = os.path.join(export_path, album_name)
# verify path is a valid path
if not is_valid_filepath(dest_dir, platform="auto"):
sys.exit(f"Invalid filepath {dest_dir}")
# create destination dir if needed
if not os.path.isdir(dest_dir):
os.makedirs(dest_dir)
# export the photo
if p.hasadjustments:
# export edited version
exported = p.export(dest_dir, edited=True)
edited_name = pathlib.Path(p.path_edited).name
click.echo(f"Exported {edited_name} to {exported}")
# export unedited version
exported = p.export(dest_dir)
click.echo(f"Exported {p.filename} to {exported}")
else:
click.echo(f"Skipping missing photo: {p.filename}")
if __name__ == "__main__":
export() # pylint: disable=no-value-for-parameter
Package Interface
-----------------
Reference full documentation on `GitHub <https://github.com/RhetTbull/osxphotos/blob/master/README.md>`_

3
cli.py
View File

@@ -3,8 +3,7 @@
To build this into an executable:
- install pyinstaller:
python3 -m pip install pyinstaller
- then use make_cli_exe.sh to run pyinstaller or execute the following command:
pyinstaller --onefile --hidden-import="pkg_resources.py2_warn" --name osxphotos --add-data osxphotos/templates/xmp_sidecar.mako:osxphotos/templates cli.py
- then use make_cli_exe.sh to run pyinstaller
Resulting executable will be in "dist/osxphotos"

BIN
docs/screencast/demo.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 219 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

View File

@@ -0,0 +1,296 @@
# how to use this file? see https://github.com/faressoft/terminalizer
# running commands:
# mkdir trip
# osxphotos export --export-by-date --from-date 2021-01-01 trip
# du -h trip
# find trip | head -20
# The configurations that used for the recording, feel free to edit them
config:
# Specify a command to be executed
# like `/bin/bash -l`, `ls`, or any other commands
# the default is bash for Linux
# or powershell.exe for Windows
command: zsh
# Specify the current working directory path
# the default is the current working directory path
cwd: /Users/aravindo/Downloads
# Export additional ENV variables
env:
recording: true
# Explicitly set the number of columns
# or use `auto` to take the current
# number of columns of your shell
cols: 91
# Explicitly set the number of rows
# or use `auto` to take the current
# number of rows of your shell
rows: 20
# Amount of times to repeat GIF
# If value is -1, play once
# If value is 0, loop indefinitely
# If value is a positive number, loop n times
repeat: 0
# Quality
# 1 - 100
quality: 100
# Delay between frames in ms
# If the value is `auto` use the actual recording delays
frameDelay: auto
# Maximum delay between frames in ms
# Ignored if the `frameDelay` isn't set to `auto`
# Set to `auto` to prevent limiting the max idle time
maxIdleTime: 2000
# The surrounding frame box
# The `type` can be null, window, floating, or solid`
# To hide the title use the value null
# Don't forget to add a backgroundColor style with a null as type
frameBox:
type: floating
title: ""
style:
border: 0px black solid
# boxShadow: none
# margin: 0px
# Add a watermark image to the rendered gif
# You need to specify an absolute path for
# the image on your machine or a URL, and you can also
# add your own CSS styles
watermark:
imagePath: null
style:
position: absolute
right: 15px
bottom: 15px
width: 100px
opacity: 0.9
# Cursor style can be one of
# `block`, `underline`, or `bar`
cursorStyle: block
# Font family
# You can use any font that is installed on your machine
# in CSS-like syntax
fontFamily: "Monaco, Lucida Console, Ubuntu Mono, Monospace"
# The size of the font
fontSize: 12
# The height of lines
lineHeight: 1
# The spacing between letters
letterSpacing: 0
# Theme
theme:
background: "transparent"
foreground: "#afafaf"
cursor: "#c7c7c7"
black: "#232628"
red: "#fc4384"
green: "#b3e33b"
yellow: "#ffa727"
blue: "#75dff2"
magenta: "#ae89fe"
cyan: "#708387"
white: "#d5d5d0"
brightBlack: "#626566"
brightRed: "#ff7fac"
brightGreen: "#c8ed71"
brightYellow: "#ebdf86"
brightBlue: "#75dff2"
brightMagenta: "#ae89fe"
brightCyan: "#b1c6ca"
brightWhite: "#f9f9f4"
# Records, feel free to edit them
records:
- delay: 100
content: "\e[1m\e[7m%\e[27m\e[1m\e[0m \r \r\e]7;file://wingeier-macOS/Users/aravindo/Downloads\a\r\e[0m\e[27m\e[24m\e[J \e[K\e[?2004h"
- delay: 100
content: m
- delay: 100
content: "\bmk"
- delay: 100
content: d
- delay: 100
content: i
- delay: 100
content: r
- delay: 100
content: ' '
- delay: 100
content: t
- delay: 100
content: r
- delay: 100
content: i
- delay: 100
content: p
- delay: 100
content: "\e[?2004l\r\r\n"
- delay: 9
content: "\e[1m\e[7m%\e[27m\e[1m\e[0m \r \r\e]7;file://wingeier-macOS/Users/aravindo/Downloads\a\r\e[0m\e[27m\e[24m\e[J \e[K\e[?2004h"
- delay: 300
content: o
- delay: 100
content: "\bos"
- delay: 100
content: x
- delay: 100
content: p
- delay: 100
content: h
- delay: 100
content: o
- delay: 100
content: t
- delay: 100
content: o
- delay: 100
content: s
- delay: 100
content: ' '
- delay: 100
content: e
- delay: 100
content: x
- delay: 100
content: p
- delay: 100
content: o
- delay: 100
content: r
- delay: 100
content: t
- delay: 100
content: ' '
- delay: 100
content: '-'
- delay: 100
content: '-'
- delay: 100
content: e
- delay: 100
content: x
- delay: 100
content: p
- delay: 100
content: o
- delay: 100
content: r
- delay: 100
content: t
- delay: 100
content: '-'
- delay: 100
content: b
- delay: 100
content: 'y'
- delay: 100
content: '-'
- delay: 100
content: d
- delay: 100
content: a
- delay: 100
content: t
- delay: 100
content: e
- delay: 100
content: ' '
- delay: 100
content: '-'
- delay: 100
content: '-'
- delay: 100
content: f
- delay: 100
content: r
- delay: 100
content: o
- delay: 100
content: m
- delay: 100
content: '-'
- delay: 100
content: d
- delay: 100
content: a
- delay: 100
content: t
- delay: 100
content: e
- delay: 100
content: ' '
- delay: 100
content: '2'
- delay: 100
content: '0'
- delay: 100
content: '2'
- delay: 100
content: '1'
- delay: 100
content: '-'
- delay: 100
content: '0'
- delay: 100
content: '1'
- delay: 100
content: '-'
- delay: 100
content: '0'
- delay: 100
content: '1'
- delay: 100
content: ' '
- delay: 100
content: t
- delay: 100
content: r
- delay: 100
content: i
- delay: 100
content: p
- delay: 300
content: "\e[?2004l\r\r\n"
- delay: 500
content: "Using last opened Photos library: /Users/user/Pictures/Photos Library.photoslibrary\r\n"
- delay: 8204
content: "Exporting 79 photos to /Users/user/trip...\r\n"
- delay: 321
content: "Processed: 79 photos, exported: 80, missing: 0, error: 0\r\nElapsed time: 0.321 seconds\r\n"
- delay: 317
content: "\e[1m\e[7m%\e[27m\e[1m\e[0m \r \r\e]7;file://wingeier-macOS/Users/aravindo/Downloads\a\r\e[0m\e[27m\e[24m\e[J \e[K\e[?2004h"
- delay: 4252
content: "\e[7mdu -h trip\e[27m"
- delay: 487
content: "\e[10D\e[27md\e[27mu\e[27m \e[27m-\e[27mh\e[27m \e[27mt\e[27mr\e[27mi\e[27mp\e[?2004l\r\r\n"
- delay: 7
content: "229M\ttrip/2021/01/03\r\n712K\ttrip/2021/01/02\r\n7.5M\ttrip/2021/01/01\r\n237M\ttrip/2021/01\r\n237M\ttrip/2021\r\n238M\ttrip\r\n\e[1m\e[7m%\e[27m\e[1m\e[0m \r \r\e]7;file://wingeier-macOS/Users/aravindo/Downloads\a\r\e[0m\e[27m\e[24m\e[J \e[K\e[?2004h"
- delay: 4280
content: "\e[7mfind trip | head -20\e[27m"
- delay: 923
content: "\e[20D\e[27mf\e[27mi\e[27mn\e[27md\e[27m \e[27mt\e[27mr\e[27mi\e[27mp\e[27m \e[27m|\e[27m \e[27mh\e[27me\e[27ma\e[27md\e[27m \e[27m-\e[27m2\e[27m0\e[?2004l\r\r\n"
- delay: 5
content: "trip\r\ntrip/2021\r\ntrip/2021/01\r\ntrip/2021/01/03\r\ntrip/2021/01/03/IMG_1234 (1).HEIC\r\ntrip/2021/01/03/IMG_1267.HEIC\r\ntrip/2021/01/03/IMG_1226.HEIC\r\ntrip/2021/01/03/IMG_1271.HEIC\r\ntrip/2021/01/03/IMG_1232 (1).JPG\r\ntrip/2021/01/03/IMG_1270.HEIC\r\ntrip/2021/01/03/IMG_1231.HEIC\r\ntrip/2021/01/03/IMG_6926.JPG\r\ntrip/2021/01/03/IMG_6932.JPG\r\ntrip/2021/01/03/IMG_1266.HEIC\r\ntrip/2021/01/03/IMG_6933.JPG\r\ntrip/2021/01/03/IMG_6927.JPG\r\ntrip/2021/01/03/IMG_1233 (1).JPG\r\ntrip/2021/01/03/IMG_1228 (1).HEIC\r\ntrip/2021/01/03/IMG_6931.JPG\r\ntrip/2021/01/03/IMG_6930.JPG\r\n\e[1m\e[7m%\e[27m\e[1m\e[0m \r \r\e]7;file://wingeier-macOS/Users/aravindo/Downloads\a\r\e[0m\e[27m\e[24m\e[J \e[K\e[?2004h"
- delay: 3615
content: "\e[?2004l\r\r\n"

View File

@@ -8,7 +8,7 @@ import importlib
pathex = os.getcwd()
# include necessary data files
datas=[('osxphotos/templates/xmp_sidecar.mako', 'osxphotos/templates')]
datas=[('osxphotos/templates/xmp_sidecar.mako', 'osxphotos/templates'), ('osxphotos/templates/xmp_sidecar_beta.mako', 'osxphotos/templates')]
package_imports = [['photoscript', ['photoscript.applescript']]]
for package, files in package_imports:
proot = os.path.dirname(importlib.import_module(package).__file__)

File diff suppressed because it is too large Load Diff

View File

@@ -5,6 +5,8 @@ Constants used by osxphotos
import os.path
from datetime import datetime
OSXPHOTOS_URL = "https://github.com/RhetTbull/osxphotos"
# Time delta: add this to Photos times to get unix time
# Apple Epoch is Jan 1, 2001
TIME_DELTA = (datetime(2001, 1, 1, 0, 0) - datetime(1970, 1, 1, 0, 0)).total_seconds()
@@ -58,8 +60,16 @@ _DB_TABLE_NAMES = {
},
}
# which major version operating systems have been tested
_TESTED_OS_VERSIONS = ["12", "13", "14", "15", "16"]
# which version operating systems have been tested
_TESTED_OS_VERSIONS = [
("10", "12"),
("10", "13"),
("10", "14"),
("10", "15"),
("10", "16"),
("11", "0"),
("11", "1"),
]
# Photos 5 has persons who are empty string if unidentified face
_UNKNOWN_PERSON = "_UNKNOWN_"
@@ -79,6 +89,7 @@ _MOVIE_TYPE = 1
# Name of XMP template file
_TEMPLATE_DIR = os.path.join(os.path.dirname(__file__), "templates")
_XMP_TEMPLATE_NAME = "xmp_sidecar.mako"
_XMP_TEMPLATE_NAME_BETA = "xmp_sidecar_beta.mako"
# Constants used for processing folders and albums
_PHOTOS_5_ALBUM_KIND = 2 # normal user album

View File

@@ -1,5 +1,3 @@
""" version info """
__version__ = "0.39.10"
__version__ = "0.39.24"

View File

@@ -60,6 +60,11 @@ class FileUtilABC(ABC):
def convert_to_jpeg(cls, src_file, dest_file, compression_quality=1.0):
pass
@classmethod
@abstractmethod
def rename(cls, src, dest):
pass
class FileUtilMacOS(FileUtilABC):
""" Various file utilities """
@@ -201,6 +206,21 @@ class FileUtilMacOS(FileUtilABC):
src_file, dest_file, compression_quality=compression_quality
)
@classmethod
def rename(cls, src, dest):
""" Copy src to dest
Args:
src: path to source file
dest: path to destination file
Returns:
Name of renamed file (dest)
"""
os.rename(str(src), str(dest))
return dest
@staticmethod
def _sig(st):
""" return tuple of (mode, size, mtime) of file based on os.stat
@@ -266,3 +286,7 @@ class FileUtilNoOp(FileUtil):
@classmethod
def convert_to_jpeg(cls, src_file, dest_file, compression_quality=1.0):
cls.verbose(f"convert_to_jpeg: {src_file}, {dest_file}, {compression_quality}")
@classmethod
def rename(cls, src, dest):
cls.verbose(f"rename: {src}, {dest}")

View File

@@ -1,11 +1,12 @@
""" ImageConverter class
Convert an image to JPEG using CoreImage --
Convert an image to JPEG using CoreImage --
for example, RAW to JPEG. Only works if Mac equipped with GPU. """
# reference: https://stackoverflow.com/questions/59330149/coreimage-ciimage-write-jpg-is-shifting-colors-macos/59334308#59334308
import pathlib
import objc
import Metal
import Quartz
from Cocoa import NSURL
@@ -20,6 +21,7 @@ class ImageConversionError(Exception):
pass
class ImageConverter:
""" Convert images to jpeg. This class is a singleton
which will re-use the Core Image CIContext to avoid
@@ -67,49 +69,58 @@ class ImageConverter:
ImageConversionError if error during conversion
"""
# accept input_path or output_path as pathlib.Path
if not isinstance(input_path, str):
input_path = str(input_path)
# Set up a dedicated objc autorelease pool for this function call.
# This is to ensure that all the NSObjects are cleaned up after each
# call to prevent memory leaks.
# https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmAutoreleasePools.html
# https://pyobjc.readthedocs.io/en/latest/api/module-objc.html#memory-management
with objc.autorelease_pool():
# accept input_path or output_path as pathlib.Path
if not isinstance(input_path, str):
input_path = str(input_path)
if not isinstance(output_path, str):
output_path = str(output_path)
if not isinstance(output_path, str):
output_path = str(output_path)
if not pathlib.Path(input_path).is_file():
raise FileNotFoundError(f"could not find {input_path}")
if not pathlib.Path(input_path).is_file():
raise FileNotFoundError(f"could not find {input_path}")
if not (0.0 <= compression_quality <= 1.0):
raise ValueError(
"illegal value for compression_quality: {compression_quality}"
if not (0.0 <= compression_quality <= 1.0):
raise ValueError(
"illegal value for compression_quality: {compression_quality}"
)
input_url = NSURL.fileURLWithPath_(input_path)
output_url = NSURL.fileURLWithPath_(output_path)
with pipes() as (out, err):
# capture stdout and stderr from system calls
# otherwise, Quartz.CIImage.imageWithContentsOfURL_
# prints to stderr something like:
# 2020-09-20 20:55:25.538 python[73042:5650492] Creating client/daemon connection: B8FE995E-3F27-47F4-9FA8-559C615FD774
# 2020-09-20 20:55:25.652 python[73042:5650492] Got the query meta data reply for: com.apple.MobileAsset.RawCamera.Camera, response: 0
input_image = Quartz.CIImage.imageWithContentsOfURL_(input_url)
if input_image is None:
raise ImageConversionError(f"Could not create CIImage for {input_path}")
output_colorspace = input_image.colorSpace() or Quartz.CGColorSpaceCreateWithName(
Quartz.CoreGraphics.kCGColorSpaceSRGB
)
input_url = NSURL.fileURLWithPath_(input_path)
output_url = NSURL.fileURLWithPath_(output_path)
with pipes() as (out, err):
# capture stdout and stderr from system calls
# otherwise, Quartz.CIImage.imageWithContentsOfURL_
# prints to stderr something like:
# 2020-09-20 20:55:25.538 python[73042:5650492] Creating client/daemon connection: B8FE995E-3F27-47F4-9FA8-559C615FD774
# 2020-09-20 20:55:25.652 python[73042:5650492] Got the query meta data reply for: com.apple.MobileAsset.RawCamera.Camera, response: 0
input_image = Quartz.CIImage.imageWithContentsOfURL_(input_url)
if input_image is None:
raise ImageConversionError(f"Could not create CIImage for {input_path}")
output_colorspace = input_image.colorSpace() or Quartz.CGColorSpaceCreateWithName(
Quartz.CoreGraphics.kCGColorSpaceSRGB
)
output_options = NSDictionary.dictionaryWithDictionary_(
{"kCGImageDestinationLossyCompressionQuality": compression_quality}
)
_, error = self.context.writeJPEGRepresentationOfImage_toURL_colorSpace_options_error_(
input_image, output_url, output_colorspace, output_options, None
)
if not error:
return True
else:
raise ImageConversionError(
"Error converting file {input_path} to jpeg at {output_path}: {error}"
output_options = NSDictionary.dictionaryWithDictionary_(
{"kCGImageDestinationLossyCompressionQuality": compression_quality}
)
(
_,
error,
) = self.context.writeJPEGRepresentationOfImage_toURL_colorSpace_options_error_(
input_image, output_url, output_colorspace, output_options, None
)
if not error:
return True
else:
raise ImageConversionError(
"Error converting file {input_path} to jpeg at {output_path}: {error}"
)

View File

@@ -4,6 +4,11 @@ import json
import logging
import math
from collections import namedtuple
MWG_RS_Area = namedtuple("MWG_RS_Area", ["x", "y", "h", "w"])
MPRI_Reg_Rect = namedtuple("MPRI_Reg_Rect", ["x", "y", "h", "w"])
class PersonInfo:
""" Info about a person in the Photos library
@@ -216,6 +221,62 @@ class FaceInfo:
logging.warning(f"Could not get photo for uuid: {self.asset_uuid}")
return self._photo
@property
def mwg_rs_area(self):
""" Get coordinates for Metadata Working Group Region Area.
Returns:
MWG_RS_Area named tuple with x, y, h, w where:
x = stArea:x
y = stArea:y
h = stArea:h
w = stArea:w
Reference:
https://photo.stackexchange.com/questions/106410/how-does-xmp-define-the-face-region
"""
x, y = self.center_x, self.center_y
x, y = self._fix_orientation((x, y))
if self.photo.orientation in [5, 6, 7, 8]:
w = self.size_pixels / self.photo.height
h = self.size_pixels / self.photo.width
else:
h = self.size_pixels / self.photo.height
w = self.size_pixels / self.photo.width
return MWG_RS_Area(x, y, h, w)
@property
def mpri_reg_rect(self):
""" Get coordinates for Microsoft Photo Region Rectangle.
Returns:
MPRI_Reg_Rect named tuple with x, y, h, w where:
x = x coordinate of top left corner of rectangle
y = y coordinate of top left corner of rectangle
h = height of rectangle
w = width of rectangle
Reference:
https://docs.microsoft.com/en-us/windows/win32/wic/-wic-people-tagging
"""
x, y = self.center_x, self.center_y
x, y = self._fix_orientation((x, y))
if self.photo.orientation in [5, 6, 7, 8]:
w = self.size_pixels / self.photo.width
h = self.size_pixels / self.photo.height
x = x - self.size_pixels / self.photo.height / 2
y = y - self.size_pixels / self.photo.width / 2
else:
h = self.size_pixels / self.photo.width
w = self.size_pixels / self.photo.height
x = x - self.size_pixels / self.photo.width / 2
y = y - self.size_pixels / self.photo.height / 2
return MPRI_Reg_Rect(x, y, h, w)
def face_rect(self):
""" Get face rectangle coordinates for current version of the associated image
If image has been edited, rectangle applies to edited version, otherwise original version
@@ -259,6 +320,33 @@ class FaceInfo:
_, _, yaw = self.roll_pitch_yaw()
return yaw
def _fix_orientation(self, xy):
""" Translate an (x, y) tuple based on image orientation
Arguments:
xy: tuple of (x, y) coordinates for point to translate
in format used by Photos (percent of height/width)
Returns:
(x, y) tuple of translated coordinates
"""
# Reference: https://github.com/neilpa/phace/blob/7594776480505d0c389688a42099c94ac5d34f3f/cmd/phace/draw.go#L79-L94
orientation = self.photo.orientation
x, y = xy
if orientation in [1, 2]:
y = 1.0 - y
elif orientation in [3, 4]:
x = 1.0 - x
elif orientation in [5, 6]:
x, y = 1.0 - y, 1.0 - x
elif orientation in [7, 8]:
x, y = y, x
else:
logging.warning(f"Unhandled orientation: {orientation}")
return (x, y)
def _make_point(self, xy):
""" Translate an (x, y) tuple based on image orientation
and convert to image coordinates
@@ -273,22 +361,11 @@ class FaceInfo:
# Reference: https://github.com/neilpa/phace/blob/7594776480505d0c389688a42099c94ac5d34f3f/cmd/phace/draw.go#L79-L94
orientation = self.photo.orientation
x, y = xy
x, y = self._fix_orientation(xy)
dx = self.photo.width
dy = self.photo.height
if orientation in [1, 2]:
y = 1.0 - y
elif orientation in [3, 4]:
x = 1.0 - x
elif orientation in [5, 6]:
x, y = 1.0 - y, 1.0 - x
if orientation in [5, 6, 7, 8]:
dx, dy = dy, dx
elif orientation in [7, 8]:
x, y = y, x
dx, dy = dy, dx
else:
logging.warning(f"Unhandled orientation: {orientation}")
return (int(x * dx), int(y * dy))
def _make_point_with_rotation(self, xy):
@@ -336,6 +413,8 @@ class FaceInfo:
"right_eye": self.right_eye,
"size": self.size,
"face_rect": self.face_rect(),
"mpri_reg_rect": self.mpri_reg_rect._asdict(),
"mwg_rs_area": self.mwg_rs_area._asdict(),
"roll": roll,
"pitch": pitch,
"yaw": yaw,

View File

@@ -35,10 +35,12 @@ from .._constants import (
_TEMPLATE_DIR,
_UNKNOWN_PERSON,
_XMP_TEMPLATE_NAME,
_XMP_TEMPLATE_NAME_BETA,
SIDECAR_EXIFTOOL,
SIDECAR_JSON,
SIDECAR_XMP,
)
from .._version import __version__
from ..datetime_utils import datetime_tz_to_utc
from ..exiftool import ExifTool
from ..export_db import ExportDBNoOp
@@ -49,7 +51,10 @@ from ..photokit import (
PhotoKitFetchFailed,
PhotoLibrary,
)
from ..utils import dd_to_dms_str, findfiles, noop
from ..utils import findfiles, get_preferred_uti_extension, noop
# retry if use_photos_export fails the first time (which sometimes it does)
MAX_PHOTOSCRIPT_RETRIES = 3
class ExportError(Exception):
@@ -233,9 +238,16 @@ def _export_photo_uuid_applescript(
exported_files = []
filename = None
try:
photo = photoscript.Photo(uuid)
filename = photo.filename
exported_files = photo.export(tmpdir.name, original=original, timeout=timeout)
# I've seen intermittent failures with the PhotoScript export so retry if
# export doesn't return anything
retries = 0
while not exported_files and retries < MAX_PHOTOSCRIPT_RETRIES:
photo = photoscript.Photo(uuid)
filename = photo.filename
exported_files = photo.export(
tmpdir.name, original=original, timeout=timeout
)
retries += 1
except Exception as e:
raise ExportError(e)
@@ -268,7 +280,7 @@ def _export_photo_uuid_applescript(
exported_paths.append(str(dest_new))
return exported_paths
else:
return None
return []
# _check_export_suffix is not a class method, don't import this into PhotoInfo
@@ -311,6 +323,34 @@ def _check_export_suffix(src, dest, edited):
)
# not a class method, don't import into PhotoInfo
def rename_jpeg_files(files, jpeg_ext, fileutil):
""" rename any jpeg files in files so that extension matches jpeg_ext
Args:
files: list of file paths
jpeg_ext: extension to use for jpeg files found in files, e.g. "jpg"
fileutil: a FileUtil object
Returns:
list of files with updated names
Note: If non-jpeg files found, they will be ignore and returned in the return list
"""
jpeg_ext = "." + jpeg_ext
jpegs = [".jpeg", ".jpg"]
new_files = []
for file in files:
path = pathlib.Path(file)
if path.suffix.lower() in jpegs and path.suffix != jpeg_ext:
new_file = path.parent / (path.stem + jpeg_ext)
fileutil.rename(file, new_file)
new_files.append(new_file)
else:
new_files.append(file)
return new_files
def export(
self,
dest,
@@ -437,6 +477,7 @@ def export2(
exiftool_flags=None,
merge_exif_keywords=False,
merge_exif_persons=False,
jpeg_ext=None,
):
"""export photo, like export but with update and dry_run options
dest: must be valid destination path or exception raised
@@ -488,6 +529,7 @@ def export2(
exiftool_flags: optional list of flags to pass to exiftool when using exiftool option, e.g ["-m", "-F"]
merge_exif_keywords: boolean; if True, merged keywords found in file's exif data (requires exiftool)
merge_exif_persons: boolean; if True, merged persons found in file's exif data (requires exiftool)
jpeg_ext: if set, will use this value for extension on jpegs converted to jpeg with convert_to_jpeg; if not set, uses jpeg; do not include the leading "."
Returns: ExportResults class
ExportResults has attributes:
@@ -576,7 +618,8 @@ def export2(
if convert_to_jpeg and self.isphoto and uti != "public.jpeg":
# not a jpeg but will convert to jpeg upon export so fix file extension
fname_new = pathlib.Path(fname)
fname = str(fname_new.parent / f"{fname_new.stem}.jpeg")
ext = "." + jpeg_ext if jpeg_ext else ".jpeg"
fname = str(fname_new.parent / f"{fname_new.stem}{ext}")
else:
# nothing to convert
convert_to_jpeg = False
@@ -746,6 +789,8 @@ def export2(
)
all_results += results
else:
# TODO: move this big if/else block to separate functions
# e.g. _export_with_photos_export or such
# use_photo_export
# export live_photo .mov file?
live_photo = True if live_photo and self.live_photo else False
@@ -760,7 +805,10 @@ def export2(
else:
# didn't get passed a filename, add _edited
filestem = f"{dest.stem}{edited_identifier}"
dest = dest.parent / f"{filestem}.jpeg"
uti = self.uti_edited if edited and self.uti_edited else self.uti
ext = get_preferred_uti_extension(uti)
dest = dest.parent / f"{filestem}{ext}"
if use_photokit:
photolib = PhotoLibrary()
photo = None
@@ -776,15 +824,24 @@ def export2(
photo = [p for p in bursts if p.uuid.startswith(self.uuid)]
photo = photo[0] if photo else None
if not photo:
all_results.error.append((str(dest), f"PhotoKitFetchFailed exception exporting photo {self.uuid}: {e}"))
if photo:
try:
exported = photo.export(
dest.parent, dest.name, version=PHOTOS_VERSION_CURRENT
all_results.error.append(
(
str(dest),
f"PhotoKitFetchFailed exception exporting photo {self.uuid}: {e}",
)
)
all_results.exported.extend(exported)
except Exception as e:
all_results.error.append((str(dest), e))
if photo:
if not dry_run:
try:
exported = photo.export(
dest.parent, dest.name, version=PHOTOS_VERSION_CURRENT
)
all_results.exported.extend(exported)
except Exception as e:
all_results.error.append((str(dest), e))
else:
# dry_run, don't actually export
all_results.exported.append(str(dest))
else:
try:
exported = _export_photo_uuid_applescript(
@@ -819,30 +876,41 @@ def export2(
photo = [p for p in bursts if p.uuid.startswith(self.uuid)]
photo = photo[0] if photo else None
if photo:
try:
exported = photo.export(
dest.parent, dest.name, version=PHOTOS_VERSION_ORIGINAL
)
all_results.exported.extend(exported)
except Exception as e:
all_results.error.append((str(dest), e))
if not dry_run:
try:
exported = photo.export(
dest.parent, dest.name, version=PHOTOS_VERSION_ORIGINAL
)
all_results.exported.extend(exported)
except Exception as e:
all_results.error.append((str(dest), e))
else:
# dry_run, don't actually export
all_results.exported.append(str(dest))
else:
try:
exported = _export_photo_uuid_applescript(
self.uuid,
dest.parent,
filestem=filestem,
original=True,
edited=False,
live_photo=live_photo,
timeout=timeout,
burst=self.burst,
dry_run=dry_run,
self.uuid,
dest.parent,
filestem=filestem,
original=True,
edited=False,
live_photo=live_photo,
timeout=timeout,
burst=self.burst,
dry_run=dry_run,
)
all_results.exported.extend(exported)
except ExportError as e:
all_results.error.append((str(dest), e))
if all_results.exported:
if jpeg_ext:
# use_photos_export (both PhotoKit and AppleScript) don't use the
# file extension provided (instead they use extension for UTI)
# so if jpeg_ext is set, rename any non-conforming jpegs
all_results.exported = rename_jpeg_files(
all_results.exported, jpeg_ext, fileutil
)
if touch_file:
for exported_file in all_results.exported:
all_results.touched.append(exported_file)
@@ -851,9 +919,6 @@ def export2(
if update:
all_results.new.extend(all_results.exported)
# else:
# all_results.error.append((str(dest), f"Error exporting photo {self.uuid} to {dest} with use_photos_export"))
# export metadata
sidecars = []
sidecar_json_files_skipped = []
@@ -1443,7 +1508,7 @@ def _exiftool_dict(
if keyword_list:
# remove duplicates
keyword_list = sorted(list(set(keyword_list)))
keyword_list = sorted(list(set([str(keyword) for keyword in keyword_list])))
exif["IPTC:Keywords"] = keyword_list.copy()
exif["XMP:Subject"] = keyword_list.copy()
exif["XMP:TagsList"] = keyword_list.copy()
@@ -1539,6 +1604,7 @@ def _get_exif_keywords(self):
kw = exifdict[field]
if kw and type(kw) != list:
kw = [kw]
kw = [str(k) for k in kw]
keywords.extend(kw)
except KeyError:
pass
@@ -1555,6 +1621,7 @@ def _get_exif_persons(self):
p = exifdict["XMP:PersonInImage"]
if p and type(p) != list:
p = [p]
p = [str(p_) for p_ in p]
persons.extend(p)
except KeyError:
pass
@@ -1648,11 +1715,15 @@ def _xmp_sidecar(
use_persons_as_keywords: treat person names as keywords
keyword_template: (list of strings); list of template strings to render as keywords
description_template: string; optional template string that will be rendered for use as photo description
extension: which extension to use for SidecarForExtension property
merge_exif_keywords: boolean; if True, merged keywords found in file's exif data (requires exiftool)
merge_exif_persons: boolean; if True, merged persons found in file's exif data (requires exiftool)
"""
xmp_template = Template(filename=os.path.join(_TEMPLATE_DIR, _XMP_TEMPLATE_NAME))
xmp_template_file = (
_XMP_TEMPLATE_NAME if not self._db._beta else _XMP_TEMPLATE_NAME_BETA
)
xmp_template = Template(filename=os.path.join(_TEMPLATE_DIR, xmp_template_file))
if extension is None:
extension = pathlib.Path(self.original_filename)
@@ -1738,6 +1809,7 @@ def _xmp_sidecar(
persons=person_list,
subjects=subject_list,
extension=extension,
version=__version__,
)
# remove extra lines that mako inserts from template

View File

@@ -113,15 +113,15 @@ class PhotoInfo:
# lastmodifieddate anytime photo database record is updated (e.g. adding tags)
# only report lastmodified date for Photos <=4 if photo is edited;
# even in this case, the date could be incorrect
if self.hasadjustments or self._db._db_version > _PHOTOS_4_VERSION:
imagedate = self._info["lastmodifieddate"]
if imagedate:
seconds = self._info["imageTimeZoneOffsetSeconds"] or 0
delta = timedelta(seconds=seconds)
tz = timezone(delta)
return imagedate.astimezone(tz=tz)
else:
return None
if not self.hasadjustments and self._db._db_version <= _PHOTOS_4_VERSION:
return None
imagedate = self._info["lastmodifieddate"]
if imagedate:
seconds = self._info["imageTimeZoneOffsetSeconds"] or 0
delta = timedelta(seconds=seconds)
tz = timezone(delta)
return imagedate.astimezone(tz=tz)
else:
return None
@@ -138,6 +138,7 @@ class PhotoInfo:
except AttributeError:
self._path = None
photopath = None
# TODO: should path try to return path even if ismissing?
if self._info["isMissing"] == 1:
return photopath # path would be meaningless until downloaded
@@ -501,37 +502,52 @@ class PhotoInfo:
downloaded from cloud to local storate their status in the database might still show
isMissing = 1
"""
return True if self._info["isMissing"] == 1 else False
return self._info["isMissing"] == 1
@property
def hasadjustments(self):
""" True if picture has adjustments / edits """
return True if self._info["hasAdjustments"] == 1 else False
return self._info["hasAdjustments"] == 1
@property
def external_edit(self):
""" Returns True if picture was edited outside of Photos using external editor """
return (
True
if self._info["adjustmentFormatID"] == "com.apple.Photos.externalEdit"
else False
)
return self._info["adjustmentFormatID"] == "com.apple.Photos.externalEdit"
@property
def favorite(self):
""" True if picture is marked as favorite """
return True if self._info["favorite"] == 1 else False
return self._info["favorite"] == 1
@property
def hidden(self):
""" True if picture is hidden """
return True if self._info["hidden"] == 1 else False
return self._info["hidden"] == 1
@property
def visible(self):
""" True if picture is visble """
return self._info["visible"]
@property
def intrash(self):
""" True if picture is in trash ('Recently Deleted' folder)"""
return self._info["intrash"]
@property
def date_trashed(self):
""" Date asset was placed in the trash or None """
# TODO: add add_timezone(dt, offset_seconds) to datetime_utils
# also update date_modified
trasheddate = self._info["trasheddate"]
if trasheddate:
seconds = self._info["imageTimeZoneOffsetSeconds"] or 0
delta = timedelta(seconds=seconds)
tz = timezone(delta)
return trasheddate.astimezone(tz=tz)
else:
return None
@property
def location(self):
""" returns (latitude, longitude) as float in degrees or None """
@@ -551,14 +567,15 @@ class PhotoInfo:
"""Returns Uniform Type Identifier (UTI) for the image
for example: public.jpeg or com.apple.quicktime-movie
"""
if self._db._db_version <= _PHOTOS_4_VERSION:
if self.hasadjustments:
return self._info["UTI_edited"]
elif self.has_raw and self.raw_original:
# return UTI of the non-raw image to match Photos 5+ behavior
return self._info["raw_pair_info"]["UTI"]
else:
return self._info["UTI"]
if self._db._db_version <= _PHOTOS_4_VERSION and self.hasadjustments:
return self._info["UTI_edited"]
elif (
self._db._db_version <= _PHOTOS_4_VERSION
and self.has_raw
and self.raw_original
):
# return UTI of the non-raw image to match Photos 5+ behavior
return self._info["raw_pair_info"]["UTI"]
else:
return self._info["UTI"]
@@ -597,12 +614,12 @@ class PhotoInfo:
@property
def ismovie(self):
"""Returns True if file is a movie, otherwise False"""
return True if self._info["type"] == _MOVIE_TYPE else False
return self._info["type"] == _MOVIE_TYPE
@property
def isphoto(self):
"""Returns True if file is an image, otherwise False"""
return True if self._info["type"] == _PHOTO_TYPE else False
return self._info["type"] == _PHOTO_TYPE
@property
def incloud(self):
@@ -627,6 +644,11 @@ class PhotoInfo:
else:
return True if self._info["cloudAssetGUID"] is not None else False
@property
def isreference(self):
""" Returns True if photo is a reference (not copied to the Photos library), otherwise False """
return self._info["isreference"]
@property
def burst(self):
""" Returns True if photo is part of a Burst photo set, otherwise False """
@@ -1017,6 +1039,7 @@ class PhotoInfo:
"path_live_photo": self.path_live_photo,
"iscloudasset": self.iscloudasset,
"incloud": self.incloud,
"isreference": self.isreference,
"date_modified": self.date_modified,
"portrait": self.portrait,
"screenshot": self.screenshot,

View File

@@ -19,6 +19,7 @@
# add original=False to export instead of version= (and maybe others like path())
# make burst/live methods get uuid from self instead of passing as arg
import copy
import pathlib
import threading
import time
@@ -169,12 +170,14 @@ class ImageData:
requestImageDataAndOrientationForAsset_options_resultHandler_
"""
def __init__(self):
self.metadata = None
self.uti = None
self.image_data = None
self.info = None
self.orientation = None
def __init__(
self, metadata=None, uti=None, image_data=None, info=None, orientation=None
):
self.metadata = metadata
self.uti = uti
self.image_data = image_data
self.info = info
self.orientation = orientation
class AVAssetData:
@@ -475,44 +478,48 @@ class PhotoAsset:
# if self.live:
# raise NotImplementedError("Live photos not implemented yet")
filename = (
pathlib.Path(filename) if filename else pathlib.Path(self.original_filename)
)
with objc.autorelease_pool():
filename = (
pathlib.Path(filename)
if filename
else pathlib.Path(self.original_filename)
)
dest = pathlib.Path(dest)
if not dest.is_dir():
raise ValueError("dest must be a valid directory: {dest}")
dest = pathlib.Path(dest)
if not dest.is_dir():
raise ValueError("dest must be a valid directory: {dest}")
output_file = None
if self.isphoto:
imagedata = self._request_image_data(version=version)
ext = get_preferred_uti_extension(imagedata.uti)
output_file = None
if self.isphoto:
imagedata = self._request_image_data(version=version)
ext = get_preferred_uti_extension(imagedata.uti)
output_file = dest / f"{filename.stem}.{ext}"
output_file = dest / f"{filename.stem}.{ext}"
if not overwrite:
output_file = pathlib.Path(increment_filename(output_file))
if not overwrite:
output_file = pathlib.Path(increment_filename(output_file))
with open(output_file, "wb") as fd:
fd.write(imagedata.image_data)
elif self.ismovie:
videodata = self._request_video_data(version=version)
if videodata.asset is None:
raise PhotoKitExportError("Could not get video for asset")
with open(output_file, "wb") as fd:
fd.write(imagedata.image_data)
del imagedata
elif self.ismovie:
videodata = self._request_video_data(version=version)
if videodata.asset is None:
raise PhotoKitExportError("Could not get video for asset")
url = videodata.asset.URL()
path = pathlib.Path(NSURL_to_path(url))
if not path.is_file():
raise FileNotFoundError("Could not get path to video file")
ext = path.suffix
output_file = dest / f"{filename.stem}{ext}"
url = videodata.asset.URL()
path = pathlib.Path(NSURL_to_path(url))
if not path.is_file():
raise FileNotFoundError("Could not get path to video file")
ext = path.suffix
output_file = dest / f"{filename.stem}{ext}"
if not overwrite:
output_file = pathlib.Path(increment_filename(output_file))
if not overwrite:
output_file = pathlib.Path(increment_filename(output_file))
FileUtil.copy(path, output_file)
FileUtil.copy(path, output_file)
return [str(output_file)]
return [str(output_file)]
def _request_image_data(self, version=PHOTOS_VERSION_ORIGINAL):
""" Request image data and metadata for self._phasset
@@ -529,50 +536,56 @@ class PhotoAsset:
# reference: https://developer.apple.com/documentation/photokit/phimagemanager/3237282-requestimagedataandorientationfo?language=objc
if version not in [
PHOTOS_VERSION_CURRENT,
PHOTOS_VERSION_ORIGINAL,
PHOTOS_VERSION_UNADJUSTED,
]:
raise ValueError("Invalid value for version")
with objc.autorelease_pool():
if version not in [
PHOTOS_VERSION_CURRENT,
PHOTOS_VERSION_ORIGINAL,
PHOTOS_VERSION_UNADJUSTED,
]:
raise ValueError("Invalid value for version")
# pylint: disable=no-member
options_request = Photos.PHImageRequestOptions.alloc().init()
options_request.setNetworkAccessAllowed_(True)
options_request.setSynchronous_(True)
options_request.setVersion_(version)
options_request.setDeliveryMode_(
Photos.PHImageRequestOptionsDeliveryModeHighQualityFormat
)
requestdata = ImageData()
event = threading.Event()
def handler(imageData, dataUTI, orientation, info):
""" result handler for requestImageDataAndOrientationForAsset_options_resultHandler_
all returned by the request is set as properties of nonlocal data (Fetchdata object) """
nonlocal requestdata
options = {}
# pylint: disable=no-member
options[Quartz.kCGImageSourceShouldCache] = Foundation.kCFBooleanFalse
imgSrc = Quartz.CGImageSourceCreateWithData(imageData, options)
requestdata.metadata = Quartz.CGImageSourceCopyPropertiesAtIndex(
imgSrc, 0, options
options_request = Photos.PHImageRequestOptions.alloc().init()
options_request.setNetworkAccessAllowed_(True)
options_request.setSynchronous_(True)
options_request.setVersion_(version)
options_request.setDeliveryMode_(
Photos.PHImageRequestOptionsDeliveryModeHighQualityFormat
)
requestdata.uti = dataUTI
requestdata.orientation = orientation
requestdata.info = info
requestdata.image_data = imageData
requestdata = ImageData()
event = threading.Event()
event.set()
def handler(imageData, dataUTI, orientation, info):
""" result handler for requestImageDataAndOrientationForAsset_options_resultHandler_
all returned by the request is set as properties of nonlocal data (Fetchdata object) """
self._manager.requestImageDataAndOrientationForAsset_options_resultHandler_(
self.phasset, options_request, handler
)
event.wait()
self._imagedata = requestdata
return requestdata
nonlocal requestdata
options = {}
# pylint: disable=no-member
options[Quartz.kCGImageSourceShouldCache] = Foundation.kCFBooleanFalse
imgSrc = Quartz.CGImageSourceCreateWithData(imageData, options)
requestdata.metadata = Quartz.CGImageSourceCopyPropertiesAtIndex(
imgSrc, 0, options
)
requestdata.uti = dataUTI
requestdata.orientation = orientation
requestdata.info = info
requestdata.image_data = imageData
event.set()
self._manager.requestImageDataAndOrientationForAsset_options_resultHandler_(
self.phasset, options_request, handler
)
event.wait()
# options_request.dealloc()
# not sure why this is needed -- some weird ref count thing maybe
# if I don't do this, memory leaks
data = copy.copy(requestdata)
del requestdata
return data
def _make_result_handle_(self, data):
""" Make handler function and threading event to use with
@@ -634,37 +647,41 @@ class SlowMoVideoExporter(NSObject):
Returns:
path to exported file
"""
exporter = AVFoundation.AVAssetExportSession.alloc().initWithAsset_presetName_(
self.avasset, AVFoundation.AVAssetExportPresetHighestQuality
)
exporter.setOutputURL_(self.url)
exporter.setOutputFileType_(AVFoundation.AVFileTypeQuickTimeMovie)
exporter.setShouldOptimizeForNetworkUse_(True)
self.done = False
with objc.autorelease_pool():
exporter = AVFoundation.AVAssetExportSession.alloc().initWithAsset_presetName_(
self.avasset, AVFoundation.AVAssetExportPresetHighestQuality
)
exporter.setOutputURL_(self.url)
exporter.setOutputFileType_(AVFoundation.AVFileTypeQuickTimeMovie)
exporter.setShouldOptimizeForNetworkUse_(True)
def handler():
""" result handler for exportAsynchronouslyWithCompletionHandler """
self.done = True
self.done = False
exporter.exportAsynchronouslyWithCompletionHandler_(handler)
# wait for export to complete
# would be more elegant to use a dispatch queue, notification, or thread event to wait
# but I can't figure out how to make that work and this does work
while True:
status = exporter.status()
if status == AVFoundation.AVAssetExportSessionStatusCompleted:
break
elif status not in (
AVFoundation.AVAssetExportSessionStatusWaiting,
AVFoundation.AVAssetExportSessionStatusExporting,
):
raise PhotoKitExportError(
f"Error encountered during exportAsynchronouslyWithCompletionHandler: status = {status}"
)
time.sleep(MIN_SLEEP)
def handler():
""" result handler for exportAsynchronouslyWithCompletionHandler """
self.done = True
return NSURL_to_path(exporter.outputURL())
exporter.exportAsynchronouslyWithCompletionHandler_(handler)
# wait for export to complete
# would be more elegant to use a dispatch queue, notification, or thread event to wait
# but I can't figure out how to make that work and this does work
while True:
status = exporter.status()
if status == AVFoundation.AVAssetExportSessionStatusCompleted:
break
elif status not in (
AVFoundation.AVAssetExportSessionStatusWaiting,
AVFoundation.AVAssetExportSessionStatusExporting,
):
raise PhotoKitExportError(
f"Error encountered during exportAsynchronouslyWithCompletionHandler: status = {status}"
)
time.sleep(MIN_SLEEP)
exported_path = NSURL_to_path(exporter.outputURL())
# exporter.dealloc()
return exported_path
def __del__(self):
self.avasset = None
@@ -701,39 +718,43 @@ class VideoAsset(PhotoAsset):
ValueError if dest is not a valid directory
"""
if self.slow_mo and version == PHOTOS_VERSION_CURRENT:
return [
self._export_slow_mo(
dest, filename=filename, version=version, overwrite=overwrite
)
]
with objc.autorelease_pool():
if self.slow_mo and version == PHOTOS_VERSION_CURRENT:
return [
self._export_slow_mo(
dest, filename=filename, version=version, overwrite=overwrite
)
]
filename = (
pathlib.Path(filename) if filename else pathlib.Path(self.original_filename)
)
filename = (
pathlib.Path(filename)
if filename
else pathlib.Path(self.original_filename)
)
dest = pathlib.Path(dest)
if not dest.is_dir():
raise ValueError("dest must be a valid directory: {dest}")
dest = pathlib.Path(dest)
if not dest.is_dir():
raise ValueError("dest must be a valid directory: {dest}")
output_file = None
videodata = self._request_video_data(version=version)
if videodata.asset is None:
raise PhotoKitExportError("Could not get video for asset")
output_file = None
videodata = self._request_video_data(version=version)
if videodata.asset is None:
raise PhotoKitExportError("Could not get video for asset")
url = videodata.asset.URL()
path = pathlib.Path(NSURL_to_path(url))
if not path.is_file():
raise FileNotFoundError("Could not get path to video file")
ext = path.suffix
output_file = dest / f"{filename.stem}{ext}"
url = videodata.asset.URL()
path = pathlib.Path(NSURL_to_path(url))
del videodata
if not path.is_file():
raise FileNotFoundError("Could not get path to video file")
ext = path.suffix
output_file = dest / f"{filename.stem}{ext}"
if not overwrite:
output_file = pathlib.Path(increment_filename(output_file))
if not overwrite:
output_file = pathlib.Path(increment_filename(output_file))
FileUtil.copy(path, output_file)
FileUtil.copy(path, output_file)
return [str(output_file)]
return [str(output_file)]
def _export_slow_mo(
self, dest, filename=None, version=PHOTOS_VERSION_CURRENT, overwrite=False
@@ -752,33 +773,38 @@ class VideoAsset(PhotoAsset):
Raises:
ValueError if dest is not a valid directory
"""
if not self.slow_mo:
raise PhotoKitMediaTypeError("Not a slow-mo video")
with objc.autorelease_pool():
if not self.slow_mo:
raise PhotoKitMediaTypeError("Not a slow-mo video")
videodata = self._request_video_data(version=version)
if (
not isinstance(videodata.asset, AVFoundation.AVComposition)
or len(videodata.asset.tracks()) != 2
):
raise PhotoKitMediaTypeError("Does not appear to be slow-mo video")
videodata = self._request_video_data(version=version)
if (
not isinstance(videodata.asset, AVFoundation.AVComposition)
or len(videodata.asset.tracks()) != 2
):
raise PhotoKitMediaTypeError("Does not appear to be slow-mo video")
filename = (
pathlib.Path(filename) if filename else pathlib.Path(self.original_filename)
)
filename = (
pathlib.Path(filename)
if filename
else pathlib.Path(self.original_filename)
)
dest = pathlib.Path(dest)
if not dest.is_dir():
raise ValueError("dest must be a valid directory: {dest}")
dest = pathlib.Path(dest)
if not dest.is_dir():
raise ValueError("dest must be a valid directory: {dest}")
output_file = dest / f"{filename.stem}.mov"
output_file = dest / f"{filename.stem}.mov"
if not overwrite:
output_file = pathlib.Path(increment_filename(output_file))
if not overwrite:
output_file = pathlib.Path(increment_filename(output_file))
exporter = SlowMoVideoExporter.alloc().initWithAVAsset_path_(
videodata.asset, output_file
)
return exporter.exportSlowMoVideo()
exporter = SlowMoVideoExporter.alloc().initWithAVAsset_path_(
videodata.asset, output_file
)
video = exporter.exportSlowMoVideo()
# exporter.dealloc()
return video
# todo: rewrite this with NotificationCenter and App event loop?
def _request_video_data(self, version=PHOTOS_VERSION_ORIGINAL):
@@ -793,38 +819,43 @@ class VideoAsset(PhotoAsset):
Raises:
ValueError if passed invalid value for version
"""
with objc.autorelease_pool():
if version not in [
PHOTOS_VERSION_CURRENT,
PHOTOS_VERSION_ORIGINAL,
PHOTOS_VERSION_UNADJUSTED,
]:
raise ValueError("Invalid value for version")
if version not in [
PHOTOS_VERSION_CURRENT,
PHOTOS_VERSION_ORIGINAL,
PHOTOS_VERSION_UNADJUSTED,
]:
raise ValueError("Invalid value for version")
options_request = Photos.PHVideoRequestOptions.alloc().init()
options_request.setNetworkAccessAllowed_(True)
options_request.setVersion_(version)
options_request.setDeliveryMode_(
Photos.PHVideoRequestOptionsDeliveryModeHighQualityFormat
)
requestdata = AVAssetData()
event = threading.Event()
options_request = Photos.PHVideoRequestOptions.alloc().init()
options_request.setNetworkAccessAllowed_(True)
options_request.setVersion_(version)
options_request.setDeliveryMode_(
Photos.PHVideoRequestOptionsDeliveryModeHighQualityFormat
)
requestdata = AVAssetData()
event = threading.Event()
def handler(asset, audiomix, info):
""" result handler for requestAVAssetForVideo:asset options:options resultHandler """
nonlocal requestdata
def handler(asset, audiomix, info):
""" result handler for requestAVAssetForVideo:asset options:options resultHandler """
nonlocal requestdata
requestdata.asset = asset
requestdata.audiomix = audiomix
requestdata.info = info
requestdata.asset = asset
requestdata.audiomix = audiomix
requestdata.info = info
event.set()
event.set()
self._manager.requestAVAssetForVideo_options_resultHandler_(
self.phasset, options_request, handler
)
event.wait()
self._manager.requestAVAssetForVideo_options_resultHandler_(
self.phasset, options_request, handler
)
event.wait()
return requestdata
# not sure why this is needed -- some weird ref count thing maybe
# if I don't do this, memory leaks
data = copy.copy(requestdata)
del requestdata
return data
class LivePhotoRequest(NSObject):
@@ -843,47 +874,54 @@ class LivePhotoRequest(NSObject):
def requestLivePhotoResources(self, version=PHOTOS_VERSION_CURRENT):
""" return the photos and video components of a live video as [PHAssetResource] """
options = Photos.PHLivePhotoRequestOptions.alloc().init()
options.setNetworkAccessAllowed_(True)
options.setVersion_(version)
options.setDeliveryMode_(
Photos.PHVideoRequestOptionsDeliveryModeHighQualityFormat
)
delegate = PhotoKitNotificationDelegate.alloc().init()
self.nc.addObserver_selector_name_object_(
delegate, "liveNotification:", None, None
)
self.live_photo = None
def handler(result, info):
""" result handler for requestLivePhotoForAsset:targetSize:contentMode:options:resultHandler: """
if not info["PHImageResultIsDegradedKey"]:
self.live_photo = result
self.info = info
self.nc.postNotificationName_object_(
PHOTOKIT_NOTIFICATION_FINISHED_REQUEST, self
)
try:
self.manager.requestLivePhotoForAsset_targetSize_contentMode_options_resultHandler_(
self.asset,
Photos.PHImageManagerMaximumSize,
Photos.PHImageContentModeDefault,
options,
handler,
with objc.autorelease_pool():
options = Photos.PHLivePhotoRequestOptions.alloc().init()
options.setNetworkAccessAllowed_(True)
options.setVersion_(version)
options.setDeliveryMode_(
Photos.PHVideoRequestOptionsDeliveryModeHighQualityFormat
)
AppHelper.runConsoleEventLoop(installInterrupt=True)
except KeyboardInterrupt:
AppHelper.stopEventLoop()
finally:
pass
delegate = PhotoKitNotificationDelegate.alloc().init()
asset_resources = Photos.PHAssetResource.assetResourcesForLivePhoto_(
self.live_photo
)
return asset_resources
self.nc.addObserver_selector_name_object_(
delegate, "liveNotification:", None, None
)
self.live_photo = None
def handler(result, info):
""" result handler for requestLivePhotoForAsset:targetSize:contentMode:options:resultHandler: """
if not info["PHImageResultIsDegradedKey"]:
self.live_photo = result
self.info = info
self.nc.postNotificationName_object_(
PHOTOKIT_NOTIFICATION_FINISHED_REQUEST, self
)
try:
self.manager.requestLivePhotoForAsset_targetSize_contentMode_options_resultHandler_(
self.asset,
Photos.PHImageManagerMaximumSize,
Photos.PHImageContentModeDefault,
options,
handler,
)
AppHelper.runConsoleEventLoop(installInterrupt=True)
except KeyboardInterrupt:
AppHelper.stopEventLoop()
finally:
pass
asset_resources = Photos.PHAssetResource.assetResourcesForLivePhoto_(
self.live_photo
)
# not sure why this is needed -- some weird ref count thing maybe
# if I don't do this, memory leaks
data = copy.copy(asset_resources)
del asset_resources
return data
def __del__(self):
self.manager = None
@@ -923,88 +961,99 @@ class LivePhotoAsset(PhotoAsset):
ValueError if dest is not a valid directory
PhotoKitExportError if error during export
"""
filename = (
pathlib.Path(filename) if filename else pathlib.Path(self.original_filename)
)
dest = pathlib.Path(dest)
if not dest.is_dir():
raise ValueError("dest must be a valid directory: {dest}")
request = LivePhotoRequest.alloc().initWithManager_Asset_(
self._manager, self.phasset
)
resources = request.requestLivePhotoResources(version=version)
video_resource = None
photo_resource = None
for resource in resources:
if resource.type() == Photos.PHAssetResourceTypePairedVideo:
video_resource = resource
elif resource.type() == Photos.PHAssetMediaTypeImage:
photo_resource = resource
if not video_resource or not photo_resource:
raise PhotoKitExportError(
"Did not find photo/video resources for live photo"
with objc.autorelease_pool():
filename = (
pathlib.Path(filename)
if filename
else pathlib.Path(self.original_filename)
)
photo_ext = get_preferred_uti_extension(photo_resource.uniformTypeIdentifier())
photo_output_file = dest / f"{filename.stem}.{photo_ext}"
video_ext = get_preferred_uti_extension(video_resource.uniformTypeIdentifier())
video_output_file = dest / f"{filename.stem}.{video_ext}"
dest = pathlib.Path(dest)
if not dest.is_dir():
raise ValueError("dest must be a valid directory: {dest}")
if not overwrite:
photo_output_file = pathlib.Path(increment_filename(photo_output_file))
video_output_file = pathlib.Path(increment_filename(video_output_file))
request = LivePhotoRequest.alloc().initWithManager_Asset_(
self._manager, self.phasset
)
resources = request.requestLivePhotoResources(version=version)
# def handler(error):
# if error:
# raise PhotoKitExportError(f"writeDataForAssetResource error: {error}")
video_resource = None
photo_resource = None
for resource in resources:
if resource.type() == Photos.PHAssetResourceTypePairedVideo:
video_resource = resource
elif resource.type() == Photos.PHAssetMediaTypeImage:
photo_resource = resource
# resource_manager = Photos.PHAssetResourceManager.defaultManager()
# options = Photos.PHAssetResourceRequestOptions.alloc().init()
# options.setNetworkAccessAllowed_(True)
# exported = []
# Note: Tried writeDataForAssetResource_toFile_options_completionHandler_ which works
# but sets quarantine flag and for reasons I can't determine (maybe quarantine flag)
# causes pathlib.Path().is_file() to fail in tests
if not video_resource or not photo_resource:
raise PhotoKitExportError(
"Did not find photo/video resources for live photo"
)
# if photo:
# photo_output_url = path_to_NSURL(photo_output_file)
# resource_manager.writeDataForAssetResource_toFile_options_completionHandler_(
# photo_resource, photo_output_url, options, handler
# )
# exported.append(str(photo_output_file))
photo_ext = get_preferred_uti_extension(
photo_resource.uniformTypeIdentifier()
)
photo_output_file = dest / f"{filename.stem}.{photo_ext}"
video_ext = get_preferred_uti_extension(
video_resource.uniformTypeIdentifier()
)
video_output_file = dest / f"{filename.stem}.{video_ext}"
# if video:
# video_output_url = path_to_NSURL(video_output_file)
# resource_manager.writeDataForAssetResource_toFile_options_completionHandler_(
# video_resource, video_output_url, options, handler
# )
# exported.append(str(video_output_file))
if not overwrite:
photo_output_file = pathlib.Path(increment_filename(photo_output_file))
video_output_file = pathlib.Path(increment_filename(video_output_file))
# def completion_handler(error):
# if error:
# raise PhotoKitExportError(f"writeDataForAssetResource error: {error}")
# def handler(error):
# if error:
# raise PhotoKitExportError(f"writeDataForAssetResource error: {error}")
# would be nice to be able to usewriteDataForAssetResource_toFile_options_completionHandler_
# but it sets quarantine flags that cause issues so instead, request the data and write the files directly
# resource_manager = Photos.PHAssetResourceManager.defaultManager()
# options = Photos.PHAssetResourceRequestOptions.alloc().init()
# options.setNetworkAccessAllowed_(True)
# exported = []
# Note: Tried writeDataForAssetResource_toFile_options_completionHandler_ which works
# but sets quarantine flag and for reasons I can't determine (maybe quarantine flag)
# causes pathlib.Path().is_file() to fail in tests
exported = []
if photo:
data = self._request_resource_data(photo_resource)
# image_data = self.request_image_data(version=version)
with open(photo_output_file, "wb") as fd:
fd.write(data)
exported.append(str(photo_output_file))
if video:
data = self._request_resource_data(video_resource)
with open(video_output_file, "wb") as fd:
fd.write(data)
exported.append(str(video_output_file))
# if photo:
# photo_output_url = path_to_NSURL(photo_output_file)
# resource_manager.writeDataForAssetResource_toFile_options_completionHandler_(
# photo_resource, photo_output_url, options, handler
# )
# exported.append(str(photo_output_file))
return exported
# if video:
# video_output_url = path_to_NSURL(video_output_file)
# resource_manager.writeDataForAssetResource_toFile_options_completionHandler_(
# video_resource, video_output_url, options, handler
# )
# exported.append(str(video_output_file))
# def completion_handler(error):
# if error:
# raise PhotoKitExportError(f"writeDataForAssetResource error: {error}")
# would be nice to be able to usewriteDataForAssetResource_toFile_options_completionHandler_
# but it sets quarantine flags that cause issues so instead, request the data and write the files directly
exported = []
if photo:
data = self._request_resource_data(photo_resource)
# image_data = self.request_image_data(version=version)
with open(photo_output_file, "wb") as fd:
fd.write(data)
exported.append(str(photo_output_file))
del data
if video:
data = self._request_resource_data(video_resource)
with open(video_output_file, "wb") as fd:
fd.write(data)
exported.append(str(video_output_file))
del data
request.dealloc()
return exported
def _request_resource_data(self, resource):
""" Request asset resource data (either photo or video component)
@@ -1015,33 +1064,40 @@ class LivePhotoAsset(PhotoAsset):
Raises:
"""
resource_manager = Photos.PHAssetResourceManager.defaultManager()
options = Photos.PHAssetResourceRequestOptions.alloc().init()
options.setNetworkAccessAllowed_(True)
with objc.autorelease_pool():
resource_manager = Photos.PHAssetResourceManager.defaultManager()
options = Photos.PHAssetResourceRequestOptions.alloc().init()
options.setNetworkAccessAllowed_(True)
requestdata = PHAssetResourceData()
event = threading.Event()
requestdata = PHAssetResourceData()
event = threading.Event()
def handler(data):
""" result handler for requestImageDataAndOrientationForAsset_options_resultHandler_
all returned by the request is set as properties of nonlocal data (Fetchdata object) """
def handler(data):
""" result handler for requestImageDataAndOrientationForAsset_options_resultHandler_
all returned by the request is set as properties of nonlocal data (Fetchdata object) """
nonlocal requestdata
nonlocal requestdata
requestdata.data += data
requestdata.data += data
def completion_handler(error):
if error:
raise PhotoKitExportError("Error requesting data for asset resource")
event.set()
def completion_handler(error):
if error:
raise PhotoKitExportError(
"Error requesting data for asset resource"
)
event.set()
resource_manager.requestDataForAssetResource_options_dataReceivedHandler_completionHandler_(
resource, options, handler, completion_handler
)
resource_manager.requestDataForAssetResource_options_dataReceivedHandler_completionHandler_(
resource, options, handler, completion_handler
)
event.wait()
options.dealloc()
return requestdata.data
event.wait()
# not sure why this is needed -- some weird ref count thing maybe
# if I don't do this, memory leaks
data = copy.copy(requestdata.data)
del requestdata
return data
# def request_image_data(self, version=PHOTOS_VERSION_CURRENT):
# # Returns an NSImage which isn't overly useful
@@ -1127,19 +1183,20 @@ class PhotoLibrary:
"""
# pylint: disable=no-member
fetch_options = Photos.PHFetchOptions.alloc().init()
fetch_result = Photos.PHAsset.fetchAssetsWithLocalIdentifiers_options_(
uuid_list, fetch_options
)
if fetch_result and fetch_result.count() >= 1:
return [
self._asset_factory(fetch_result.objectAtIndex_(idx))
for idx in range(fetch_result.count())
]
else:
raise PhotoKitFetchFailed(
f"Fetch did not return result for uuid_list {uuid_list}"
with objc.autorelease_pool():
fetch_options = Photos.PHFetchOptions.alloc().init()
fetch_result = Photos.PHAsset.fetchAssetsWithLocalIdentifiers_options_(
uuid_list, fetch_options
)
if fetch_result and fetch_result.count() >= 1:
return [
self._asset_factory(fetch_result.objectAtIndex_(idx))
for idx in range(fetch_result.count())
]
else:
raise PhotoKitFetchFailed(
f"Fetch did not return result for uuid_list {uuid_list}"
)
def fetch_uuid(self, uuid):
""" fetch PHAsset with uuid = uuid

View File

@@ -85,12 +85,12 @@ class PhotosDB:
# Check OS version
system = platform.system()
(_, major, _) = _get_os_version()
if system != "Darwin" or (major not in _TESTED_OS_VERSIONS):
(ver, major, _) = _get_os_version()
if system != "Darwin" or ((ver, major) not in _TESTED_OS_VERSIONS):
logging.warning(
f"WARNING: This module has only been tested with MacOS 10."
f"[{', '.join(_TESTED_OS_VERSIONS)}]: "
f"you have {system}, OS version: {major}"
f"WARNING: This module has only been tested with macOS versions "
f"[{', '.join(f'{v}.{m}' for (v, m) in _TESTED_OS_VERSIONS)}]: "
f"you have {system}, OS version: {ver}.{major}"
)
if verbose is None:
@@ -99,6 +99,9 @@ class PhotosDB:
raise TypeError("verbose must be callable")
self._verbose = verbose
# enable beta features
self._beta = False
self._exiftool_path = exiftool
# create a temporary directory
@@ -887,7 +890,10 @@ class PhotosDB:
RKMaster.width,
RKMaster.orientation,
RKMaster.fileSize,
RKVersion.subType
RKVersion.subType,
RKVersion.inTrashDate,
RKVersion.showInLibrary,
RKMaster.fileIsReference
FROM RKVersion, RKMaster
WHERE RKVersion.masterUuid = RKMaster.uuid"""
)
@@ -915,8 +921,11 @@ class PhotosDB:
RKMaster.width,
RKMaster.orientation,
RKMaster.originalFileSize,
RKVersion.subType
FROM RKVersion, RKMaster
RKVersion.subType,
RKVersion.inTrashDate,
RKVersion.showInLibrary,
RKMaster.fileIsReference
FROM RKVersion, RKMaster
WHERE RKVersion.masterUuid = RKMaster.uuid"""
)
@@ -962,6 +971,9 @@ class PhotosDB:
# 38 RKMaster.orientation,
# 39 RKMaster.originalFileSize
# 40 RKVersion.subType
# 41 RKVersion.inTrashDate
# 42 RKVersion.showInLibrary -- is item visible in library (e.g. non-selected burst images are not visible)
# 43 RKMaster.fileIsReference -- file is reference (imported without copying to Photos library)
for row in c:
uuid = row[0]
@@ -1136,7 +1148,14 @@ class PhotosDB:
)
# recently deleted items
self._dbphotos[uuid]["intrash"] = True if row[32] == 1 else False
self._dbphotos[uuid]["intrash"] = row[32] == 1
self._dbphotos[uuid]["trasheddate_timestamp"] = row[41]
try:
self._dbphotos[uuid]["trasheddate"] = datetime.fromtimestamp(
row[41] + TIME_DELTA
)
except (ValueError, TypeError):
self._dbphotos[uuid]["trasheddate"] = None
# height/width/orientation
self._dbphotos[uuid]["height"] = row[33]
@@ -1147,6 +1166,14 @@ class PhotosDB:
self._dbphotos[uuid]["original_orientation"] = row[38]
self._dbphotos[uuid]["original_filesize"] = row[39]
# visibility state
self._dbphotos[uuid]["visibility_state"] = row[42]
self._dbphotos[uuid]["visible"] = row[42] == 1
# file is reference (not copied into Photos library)
self._dbphotos[uuid]["isreference"] = row[43] == 1
self._dbphotos[uuid]["saved_asset_type"] = None # Photos 5+
# import session not yet handled for Photos 4
self._dbphotos[uuid]["import_session"] = None
self._dbphotos[uuid]["import_uuid"] = None
@@ -1840,7 +1867,10 @@ class PhotosDB:
ZADDITIONALASSETATTRIBUTES.ZORIGINALORIENTATION,
ZADDITIONALASSETATTRIBUTES.ZORIGINALFILESIZE,
{depth_state},
{asset_table}.ZADJUSTMENTTIMESTAMP
{asset_table}.ZADJUSTMENTTIMESTAMP,
{asset_table}.ZVISIBILITYSTATE,
{asset_table}.ZTRASHEDDATE,
{asset_table}.ZSAVEDASSETTYPE
FROM {asset_table}
JOIN ZADDITIONALASSETATTRIBUTES ON ZADDITIONALASSETATTRIBUTES.ZASSET = {asset_table}.Z_PK
ORDER BY {asset_table}.ZUUID """
@@ -1885,6 +1915,9 @@ class PhotosDB:
# 35 ZADDITIONALASSETATTRIBUTES.ZORIGINALFILESIZE
# 36 ZGENERICASSET.ZDEPTHSTATES / ZASSET.ZDEPTHTYPE
# 37 ZGENERICASSET.ZADJUSTMENTTIMESTAMP -- when was photo edited?
# 38 ZGENERICASSET.ZVISIBILITYSTATE -- 0 if visible, 2 if not (e.g. a burst image)
# 39 ZGENERICASSET.ZTRASHEDDATE -- date item placed in the trash or null if not in trash
# 40 ZGENERICASSET.ZSAVEDASSETTYPE -- how item imported
for row in c:
uuid = row[0]
@@ -1901,9 +1934,7 @@ class PhotosDB:
info["lastmodifieddate_timestamp"] = row[37]
try:
info["lastmodifieddate"] = datetime.fromtimestamp(row[37] + TIME_DELTA)
except ValueError:
info["lastmodifieddate"] = None
except TypeError:
except (ValueError, TypeError):
info["lastmodifieddate"] = None
info["imageTimeZoneOffsetSeconds"] = row[6]
@@ -2046,6 +2077,11 @@ class PhotosDB:
# recently deleted items
info["intrash"] = True if row[28] == 1 else False
info["trasheddate_timestamp"] = row[39]
try:
info["trasheddate"] = datetime.fromtimestamp(row[39] + TIME_DELTA)
except (ValueError, TypeError):
info["trasheddate"] = None
# height/width/orientation
info["height"] = row[29]
@@ -2056,6 +2092,19 @@ class PhotosDB:
info["original_orientation"] = row[34]
info["original_filesize"] = row[35]
# visibility state, visible (True) if 0, otherwise not visible (False)
# only values I've seen are 0 for visible, 2 for not-visible
info["visibility_state"] = row[38]
info["visible"] = row[38] == 0
# ZSAVEDASSETTYPE Values:
# 3: imported by copying to Photos library
# 4: shared iCloud photo
# 6: imported by iCloud (e.g. from iPhone)
# 10: referenced file (not copied to Photos library)
info["saved_asset_type"] = row[40]
info["isreference"] = row[40] == 10
# initialize import session info which will be filled in later
# not every photo has an import session so initialize all records now
info["import_session"] = None

View File

@@ -82,11 +82,11 @@ TEMPLATE_SUBSTITUTIONS = {
"{modified.hour}": "2-digit hour of the photo modification time; uses creation date if photo is not modified",
"{modified.min}": "2-digit minute of the photo modification time; uses creation date if photo is not modified",
"{modified.sec}": "2-digit second of the photo modification time; uses creation date if photo is not modified",
# "{modified.strftime}": "Apply strftime template to file modification date/time. Should be used in form "
# + "{modified.strftime,TEMPLATE} where TEMPLATE is a valid strftime template, e.g. "
# + "{modified.strftime,%Y-%U} would result in year-week number of year: '2020-23'. "
# + "If used with no template will return null value. "
# + "See https://strftime.org/ for help on strftime templates.",
"{modified.strftime}": "Apply strftime template to file modification date/time. Should be used in form "
+ "{modified.strftime,TEMPLATE} where TEMPLATE is a valid strftime template, e.g. "
+ "{modified.strftime,%Y-%U} would result in year-week number of year: '2020-23'. "
+ "If used with no template will return null value. Uses creation date if photo is not modified. "
+ "See https://strftime.org/ for help on strftime templates.",
"{today.date}": "Current date in iso format, e.g. '2020-03-22'",
"{today.year}": "4-digit year of current date",
"{today.yy}": "2-digit year of current date",
@@ -118,9 +118,9 @@ TEMPLATE_SUBSTITUTIONS = {
"{place.address.country}": "Country name of the postal address, e.g. 'United States'",
"{place.address.country_code}": "ISO country code of the postal address, e.g. 'US'",
"{searchinfo.season}": "Season of the year associated with a photo, e.g. 'Summer'; (Photos 5+ only, applied automatically by Photos' image categorization algorithms).",
"{exif.camera_make}": "Camera make from original photo's EXIF inormation as imported by Photos, e.g. 'Apple'",
"{exif.camera_model}": "Camera model from original photo's EXIF inormation as imported by Photos, e.g. 'iPhone 6s'",
"{exif.lens_model}": "Lens model from original photo's EXIF inormation as imported by Photos, e.g. 'iPhone 6s back camera 4.15mm f/2.2'",
"{exif.camera_make}": "Camera make from original photo's EXIF information as imported by Photos, e.g. 'Apple'",
"{exif.camera_model}": "Camera model from original photo's EXIF information as imported by Photos, e.g. 'iPhone 6s'",
"{exif.lens_model}": "Lens model from original photo's EXIF information as imported by Photos, e.g. 'iPhone 6s back camera 4.15mm f/2.2'",
"{uuid}": "Photo's internal universally unique identifier (UUID) for the photo, a 36-character string unique to the photo, e.g. '128FB4C6-0B16-4E7D-9108-FB2E90DA1546'",
}
@@ -797,6 +797,15 @@ class PhotoTemplate:
if self.photo.date_modified
else DateTimeFormatter(self.photo.date).sec
)
elif field == "modified.strftime":
if default:
try:
date = self.photo.date_modified or self.photo.date
value = date.strftime(default)
except:
raise ValueError(f"Invalid strftime template: '{default}'")
else:
value = None
elif field == "today.date":
value = DateTimeFormatter(self.today).date
elif field == "today.year":

View File

@@ -10,28 +10,44 @@
<%def name="dc_description(desc)">
% if desc is None:
<dc:description></dc:description>
<dc:description>
<rdf:Alt>
<rdf:li xml:lang='x-default'/>
</rdf:Alt>
</dc:description>
% else:
<dc:description>${desc | x}</dc:description>
<dc:description>
<rdf:Alt>
<rdf:li xml:lang='x-default'>${desc | x}</rdf:li>
</rdf:Alt>
</dc:description>
% endif
</%def>
<%def name="dc_title(title)">
% if title is None:
<dc:title></dc:title>
<dc:title>
<rdf:Alt>
<rdf:li xml:lang='x-default'/>
</rdf:Alt>
</dc:title>
% else:
<dc:title>${title | x}</dc:title>
<dc:title>
<rdf:Alt>
<rdf:li xml:lang='x-default'>${title | x}</rdf:li>
</rdf:Alt>
</dc:title>
% endif
</%def>
<%def name="dc_subject(subject)">
% if subject:
<dc:subject>
<rdf:Seq>
% for subj in subject:
<rdf:li>${subj | x}</rdf:li>
% endfor
</rdf:Seq>
<rdf:Bag>
% for subj in subject:
<rdf:li>${subj | x}</rdf:li>
% endfor
</rdf:Bag>
</dc:subject>
% endif
</%def>
@@ -86,7 +102,6 @@
</%def>
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 5.4.0">
<!-- mirrors Photos 5 "Export IPTC as XMP" option -->
<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/"

View File

@@ -0,0 +1,210 @@
<%def name="photoshop_sidecar_for_extension(extension)">
% if extension is None:
<photoshop:SidecarForExtension></photoshop:SidecarForExtension>
% else:
<photoshop:SidecarForExtension>${extension}</photoshop:SidecarForExtension>
% endif
</%def>
<%def name="dc_description(desc)">
% if desc is None:
<dc:description>
<rdf:Alt>
<rdf:li xml:lang='x-default'/>
</rdf:Alt>
</dc:description>
% else:
<dc:description>
<rdf:Alt>
<rdf:li xml:lang='x-default'>${desc | x}</rdf:li>
</rdf:Alt>
</dc:description>
% endif
</%def>
<%def name="dc_title(title)">
% if title is None:
<dc:title>
<rdf:Alt>
<rdf:li xml:lang='x-default'/>
</rdf:Alt>
</dc:title>
% else:
<dc:title>
<rdf:Alt>
<rdf:li xml:lang='x-default'>${title | x}</rdf:li>
</rdf:Alt>
</dc:title>
% endif
</%def>
<%def name="dc_subject(subject)">
% if subject:
<dc:subject>
<rdf:Bag>
% for subj in subject:
<rdf:li>${subj | x}</rdf:li>
% endfor
</rdf:Bag>
</dc:subject>
% endif
</%def>
<%def name="dc_datecreated(date)">
% if date is not None:
<photoshop:DateCreated>${date.isoformat()}</photoshop:DateCreated>
% endif
</%def>
<%def name="iptc_personinimage(persons)">
% if persons:
<Iptc4xmpExt:PersonInImage>
<rdf:Bag>
% for person in persons:
<rdf:li>${person | x}</rdf:li>
% endfor
</rdf:Bag>
</Iptc4xmpExt:PersonInImage>
% endif
</%def>
<%def name="dk_tagslist(keywords)">
% if keywords:
<digiKam:TagsList>
<rdf:Seq>
% for keyword in keywords:
<rdf:li>${keyword | x}</rdf:li>
% endfor
</rdf:Seq>
</digiKam:TagsList>
% endif
</%def>
<%def name="adobe_createdate(date)">
% if date is not None:
<xmp:CreateDate>${date.strftime("%Y-%m-%dT%H:%M:%S")}</xmp:CreateDate>
% endif
</%def>
<%def name="adobe_modifydate(date)">
% if date is not None:
<xmp:ModifyDate>${date.strftime("%Y-%m-%dT%H:%M:%S")}</xmp:ModifyDate>
% endif
</%def>
<%def name="gps_info(latitude, longitude)">
% if latitude is not None and longitude is not None:
<exif:GPSLongitude>${int(abs(longitude))},${(abs(longitude) % 1) * 60}${"E" if longitude >= 0 else "W"}</exif:GPSLongitude>
<exif:GPSLatitude>${int(abs(latitude))},${(abs(latitude) % 1) * 60}${"N" if latitude >= 0 else "S"}</exif:GPSLatitude>
% endif
</%def>
<%def name="orientation(orientation)">
% if orientation is not None:
<tiff:Orientation>${orientation}</tiff:Orientation>
% endif
</%def>
<%def name="mwg_face_regions(photo)">
% if photo.face_info:
<mwg-rs:Regions rdf:parseType="Resource">
<mwg-rs:AppliedToDimensions rdf:parseType="Resource">
<stDim:unit>pixel</stDim:unit>
</mwg-rs:AppliedToDimensions>
<mwg-rs:RegionList>
<rdf:Bag>
% for face in photo.face_info:
<rdf:li rdf:parseType="Resource">
<mwg-rs:Area rdf:parseType="Resource">
<stArea:h>${'{0:.6f}'.format(face.mwg_rs_area.h)}</stArea:h>
<stArea:w>${'{0:.6f}'.format(face.mwg_rs_area.w)}</stArea:w>
<stArea:x>${'{0:.6f}'.format(face.mwg_rs_area.x)}</stArea:x>
<stArea:y>${'{0:.6f}'.format(face.mwg_rs_area.y)}</stArea:y>
<stArea:unit>normalized</stArea:unit>
</mwg-rs:Area>
<mwg-rs:Name>${face.name}</mwg-rs:Name>
<mwg-rs:Rotation>${face.roll}</mwg-rs:Rotation>
<mwg-rs:Type>Face</mwg-rs:Type>
</rdf:li>
% endfor
</rdf:Bag>
</mwg-rs:RegionList>
</mwg-rs:Regions>
% endif
</%def>
<%def name="mpri_face_regions(photo)">
% if photo.face_info:
<MP:RegionInfo rdf:parseType="Resource">
<MPRI:Regions>
<rdf:Bag>
% for face in photo.face_info:
<rdf:li rdf:parseType="Resource">
<MPReg:PersonDisplayName>${face.name}</MPReg:PersonDisplayName>
<MPReg:Rectangle>${'{0:.6f}'.format(face.mpri_reg_rect.x)}, ${'{0:.6f}'.format(face.mpri_reg_rect.y)}, ${'{0:.6f}'.format(face.mpri_reg_rect.h)}, ${'{0:.6f}'.format(face.mpri_reg_rect.w)}</MPReg:Rectangle>
</rdf:li>
% endfor
</rdf:Bag>
</MPRI:Regions>
</MP:RegionInfo>
% endif
</%def>
<?xpacket begin="${"\uFEFF"}" id="W5M0MpCehiHzreSzNTczkc9d"?>
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="osxphotos ${version}">
<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:photoshop="http://ns.adobe.com/photoshop/1.0/">
${photoshop_sidecar_for_extension(extension)}
${dc_description(description)}
${dc_title(photo.title)}
${dc_subject(subjects)}
${dc_datecreated(photo.date)}
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:Iptc4xmpExt='http://iptc.org/std/Iptc4xmpExt/2008-02-29/'>
${iptc_personinimage(persons)}
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:digiKam='http://www.digikam.org/ns/1.0/'>
${dk_tagslist(keywords)}
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:xmp='http://ns.adobe.com/xap/1.0/'>
${adobe_createdate(photo.date)}
${adobe_modifydate(photo.date)}
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:exif='http://ns.adobe.com/exif/1.0/'>
${gps_info(*photo.location)}
</rdf:Description>
<rdf:Description rdf:about=''
xmlns:tiff='http://ns.adobe.com/tiff/1.0/'>
${orientation(photo.orientation)}
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:mwg-rs="http://www.metadataworkinggroup.com/schemas/regions/"
xmlns:stArea="http://ns.adobe.com/xmp/sType/Area#"
xmlns:stDim="http://ns.adobe.com/xap/1.0/sType/Dimensions#">
${mwg_face_regions(photo)}
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:MP="http://ns.microsoft.com/photo/1.2/"
xmlns:MPRI="http://ns.microsoft.com/photo/1.2/t/RegionInfo#"
xmlns:MPReg="http://ns.microsoft.com/photo/1.2/t/Region#">
${mpri_face_regions(photo)}
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>
<?xpacket end="w"?>

View File

@@ -63,8 +63,8 @@ def noop(*args, **kwargs):
def _get_os_version():
# returns tuple containing OS version
# e.g. 10.13.6 = (10, 13, 6)
# returns tuple of str containing OS version
# e.g. 10.13.6 = ("10", "13", "6")
version = platform.mac_ver()[0].split(".")
if len(version) == 2:
(ver, major) = version
@@ -260,10 +260,10 @@ def get_preferred_uti_extension(uti):
returns: preferred extension as str """
# reference: https://developer.apple.com/documentation/coreservices/1442744-uttypecopypreferredtagwithclass?language=objc
return CoreServices.UTTypeCopyPreferredTagWithClass(
uti, CoreServices.kUTTagClassFilenameExtension
)
with objc.autorelease_pool():
return CoreServices.UTTypeCopyPreferredTagWithClass(
uti, CoreServices.kUTTagClassFilenameExtension
)
def findfiles(pattern, path_):

View File

@@ -3,7 +3,7 @@
#
# setup.py script for osxphotos
#
# Copyright (c) 2019, 2020 Rhet Turnbull, rturnbull+git@gmail.com
# Copyright (c) 2019, 2020, 2021 Rhet Turnbull, rturnbull+git@gmail.com
# All rights reserved.
#
# Permission is hereby granted, free of charge, to any person
@@ -45,7 +45,7 @@ with open(
exec(f.read(), about)
# read README.md into long_description
with open(os.path.join(this_directory, "README.md"), encoding="utf-8") as f:
with open(os.path.join(this_directory, "README.rst"), encoding="utf-8") as f:
about["long_description"] = f.read()
setup(
@@ -53,7 +53,7 @@ setup(
version=about["__version__"],
description="Export photos from Apple's macOS Photos app and query the Photos library database to access metadata about images.",
long_description=about["long_description"],
long_description_content_type="text/markdown",
long_description_content_type="text/x-rst",
author="Rhet Turnbull",
author_email="rturnbull+git@gmail.com",
url="https://github.com/RhetTbull/",

View File

@@ -6,7 +6,8 @@ import sys
import osxphotos
photosdb = osxphotos.PhotosDB()
db = sys.argv[1]
photosdb = osxphotos.PhotosDB(dbfile=db)
face_photos = [p for p in photosdb.photos() if p.face_info]

View File

@@ -2,6 +2,8 @@
# reads data from the author's system photo library to build the test data
# used to test SearchInfo
# run as:
# python3 tests/generate_search_info_test_data.py >tests/search_info_test_data_10_15_7.json
import json

View File

@@ -0,0 +1,113 @@
""" Generate sidecars used for tests """
# Generates sidecars used for test cases
# tests generate sidecars and compare to the ones generated here to assert nothing changed
# Run this any time you change code that would result in a change to sidecar files
import pathlib
import osxphotos
PHOTOS_DB_15_7 = "./tests/Test-10.15.7.photoslibrary/database/photos.db"
PHOTOS_DB_14_6 = "./tests/Test-10.14.6.photoslibrary/database/photos.db"
UUID_DICT_15_7 = {
"not_favorite": "A1DD1F98-2ECD-431F-9AC9-5AFEFE2D3A5C",
"has_adjustments": "E9BC5C36-7CD1-40A1-A72B-8B8FAC227D51",
"location": "DC99FBDD-7A52-4100-A5BB-344131646C30",
"no_location": "6191423D-8DB8-4D4C-92BE-9BBBA308AAC4",
"export": "D79B8D77-BFFC-460B-9312-034F2877D35B", # "Pumkins2.jpg"
"xmp": "F12384F6-CD17-4151-ACBA-AE0E3688539E", # Pumkins1.jpg
}
UUID_DICT_14_6 = {
"has_adjustments": "6bxcNnzRQKGnK4uPrCJ9UQ",
"no_adjustments": "15uNd7%8RguTEgNPKHfTWw",
"location": "3Jn73XpSQQCluzRBMWRsMA",
"xmp": "8SOE9s0XQVGsuq4ONohTng",
}
SIDECAR_DIR = "tests/sidecars"
def generate_sidecars(dbname, uuid_dict):
""" generate XMP and JSON sidecars for testing """
photosdb = osxphotos.PhotosDB(dbname)
for _, uuid in uuid_dict.items():
photo = photosdb.get_photo(uuid)
# plain xmp
sidecar = str(pathlib.Path(SIDECAR_DIR) / f"{uuid}.xmp")
xmp = photo._xmp_sidecar()
with open(sidecar, "w") as file:
file.write(xmp)
# with extension
ext = osxphotos.utils.get_preferred_uti_extension(photo.uti)
ext = "jpg" if ext == "jpeg" else ext
sidecar = str(pathlib.Path(SIDECAR_DIR) / f"{uuid}_ext.xmp")
xmp = photo._xmp_sidecar(extension=ext)
with open(sidecar, "w") as file:
file.write(xmp)
# persons_as_keywords
sidecar = str(pathlib.Path(SIDECAR_DIR) / f"{uuid}_persons_as_keywords.xmp")
xmp = photo._xmp_sidecar(use_persons_as_keywords=True, extension=ext)
with open(sidecar, "w") as file:
file.write(xmp)
# albums_as_keywords
sidecar = str(pathlib.Path(SIDECAR_DIR) / f"{uuid}_albums_as_keywords.xmp")
xmp = photo._xmp_sidecar(use_albums_as_keywords=True, extension=ext)
with open(sidecar, "w") as file:
file.write(xmp)
# keyword_template
sidecar = str(pathlib.Path(SIDECAR_DIR) / f"{uuid}_keyword_template.xmp")
xmp = photo._xmp_sidecar(
keyword_template=["{created.year}", "{folder_album}"], extension=ext
)
with open(sidecar, "w") as file:
file.write(xmp)
# generate JSON files
sidecar = str(pathlib.Path(SIDECAR_DIR) / f"{uuid}.json")
json_ = photo._exiftool_json_sidecar()
with open(sidecar, "w") as file:
file.write(json_)
# no tag groups
sidecar = str(pathlib.Path(SIDECAR_DIR) / f"{uuid}_no_tag_groups.json")
json_ = photo._exiftool_json_sidecar(tag_groups=False)
with open(sidecar, "w") as file:
file.write(json_)
# ignore_date_modified
sidecar = str(pathlib.Path(SIDECAR_DIR) / f"{uuid}_ignore_date_modified.json")
json_ = photo._exiftool_json_sidecar(ignore_date_modified=True)
with open(sidecar, "w") as file:
file.write(json_)
# keyword_template
sidecar = str(pathlib.Path(SIDECAR_DIR) / f"{uuid}_keyword_template.json")
json_ = photo._exiftool_json_sidecar(keyword_template=["{folder_album}"])
with open(sidecar, "w") as file:
file.write(json_)
# persons_as_keywords
sidecar = str(pathlib.Path(SIDECAR_DIR) / f"{uuid}_persons_as_keywords.json")
json_ = photo._exiftool_json_sidecar(use_persons_as_keywords=True)
with open(sidecar, "w") as file:
file.write(json_)
# albums_as_keywords
sidecar = str(pathlib.Path(SIDECAR_DIR) / f"{uuid}_albums_as_keywords.json")
json_ = photo._exiftool_json_sidecar(use_albums_as_keywords=True)
with open(sidecar, "w") as file:
file.write(json_)
if __name__ == "__main__":
generate_sidecars(PHOTOS_DB_15_7, UUID_DICT_15_7)
generate_sidecars(PHOTOS_DB_14_6, UUID_DICT_14_6)

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
[{"EXIF:ImageDescription": "Girl holding pumpkin", "XMP:Description": "Girl holding pumpkin", "XMP:Title": "I found one!", "IPTC:Keywords": ["Kids"], "XMP:Subject": ["Kids"], "XMP:TagsList": ["Kids"], "XMP:PersonInImage": ["Katie"], "EXIF:DateTimeOriginal": "2018:09:28 16:07:07", "EXIF:CreateDate": "2018:09:28 16:07:07", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2018:09:28", "IPTC:TimeCreated": "16:07:07-04:00", "EXIF:ModifyDate": "2018:09:28 16:07:07"}]

View File

@@ -0,0 +1,50 @@
<!-- Created with osxphotos https://github.com/RhetTbull/osxphotos -->
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 5.4.0">
<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:photoshop="http://ns.adobe.com/photoshop/1.0/">
<photoshop:SidecarForExtension>jpg</photoshop:SidecarForExtension>
<dc:description>
<rdf:Alt>
<rdf:li xml:lang='x-default'>Girl holding pumpkin</rdf:li>
</rdf:Alt>
</dc:description>
<dc:title>
<rdf:Alt>
<rdf:li xml:lang='x-default'>I found one!</rdf:li>
</rdf:Alt>
</dc:title>
<dc:subject>
<rdf:Bag>
<rdf:li>Kids</rdf:li>
</rdf:Bag>
</dc:subject>
<photoshop:DateCreated>2018-09-28T16:07:07-04:00</photoshop:DateCreated>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:Iptc4xmpExt='http://iptc.org/std/Iptc4xmpExt/2008-02-29/'>
<Iptc4xmpExt:PersonInImage>
<rdf:Bag>
<rdf:li>Katie</rdf:li>
</rdf:Bag>
</Iptc4xmpExt:PersonInImage>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:digiKam='http://www.digikam.org/ns/1.0/'>
<digiKam:TagsList>
<rdf:Seq>
<rdf:li>Kids</rdf:li>
</rdf:Seq>
</digiKam:TagsList>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:xmp='http://ns.adobe.com/xap/1.0/'>
<xmp:CreateDate>2018-09-28T16:07:07</xmp:CreateDate>
<xmp:ModifyDate>2018-09-28T16:07:07</xmp:ModifyDate>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:exif='http://ns.adobe.com/exif/1.0/'>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>

View File

@@ -0,0 +1 @@
[{"EXIF:ImageDescription": "Girl holding pumpkin", "XMP:Description": "Girl holding pumpkin", "XMP:Title": "I found one!", "IPTC:Keywords": ["AlbumInFolder", "Kids", "Pumpkin Farm", "Test Album (1)"], "XMP:Subject": ["AlbumInFolder", "Kids", "Pumpkin Farm", "Test Album (1)"], "XMP:TagsList": ["AlbumInFolder", "Kids", "Pumpkin Farm", "Test Album (1)"], "XMP:PersonInImage": ["Katie"], "EXIF:DateTimeOriginal": "2018:09:28 16:07:07", "EXIF:CreateDate": "2018:09:28 16:07:07", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2018:09:28", "IPTC:TimeCreated": "16:07:07-04:00", "EXIF:ModifyDate": "2018:09:28 16:07:07"}]

View File

@@ -0,0 +1,56 @@
<!-- Created with osxphotos https://github.com/RhetTbull/osxphotos -->
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 5.4.0">
<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:photoshop="http://ns.adobe.com/photoshop/1.0/">
<photoshop:SidecarForExtension>jpg</photoshop:SidecarForExtension>
<dc:description>
<rdf:Alt>
<rdf:li xml:lang='x-default'>Girl holding pumpkin</rdf:li>
</rdf:Alt>
</dc:description>
<dc:title>
<rdf:Alt>
<rdf:li xml:lang='x-default'>I found one!</rdf:li>
</rdf:Alt>
</dc:title>
<dc:subject>
<rdf:Bag>
<rdf:li>AlbumInFolder</rdf:li>
<rdf:li>Kids</rdf:li>
<rdf:li>Pumpkin Farm</rdf:li>
<rdf:li>Test Album (1)</rdf:li>
</rdf:Bag>
</dc:subject>
<photoshop:DateCreated>2018-09-28T16:07:07-04:00</photoshop:DateCreated>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:Iptc4xmpExt='http://iptc.org/std/Iptc4xmpExt/2008-02-29/'>
<Iptc4xmpExt:PersonInImage>
<rdf:Bag>
<rdf:li>Katie</rdf:li>
</rdf:Bag>
</Iptc4xmpExt:PersonInImage>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:digiKam='http://www.digikam.org/ns/1.0/'>
<digiKam:TagsList>
<rdf:Seq>
<rdf:li>AlbumInFolder</rdf:li>
<rdf:li>Kids</rdf:li>
<rdf:li>Pumpkin Farm</rdf:li>
<rdf:li>Test Album (1)</rdf:li>
</rdf:Seq>
</digiKam:TagsList>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:xmp='http://ns.adobe.com/xap/1.0/'>
<xmp:CreateDate>2018-09-28T16:07:07</xmp:CreateDate>
<xmp:ModifyDate>2018-09-28T16:07:07</xmp:ModifyDate>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:exif='http://ns.adobe.com/exif/1.0/'>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>

View File

@@ -0,0 +1,50 @@
<!-- Created with osxphotos https://github.com/RhetTbull/osxphotos -->
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 5.4.0">
<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:photoshop="http://ns.adobe.com/photoshop/1.0/">
<photoshop:SidecarForExtension>jpg</photoshop:SidecarForExtension>
<dc:description>
<rdf:Alt>
<rdf:li xml:lang='x-default'>Girl holding pumpkin</rdf:li>
</rdf:Alt>
</dc:description>
<dc:title>
<rdf:Alt>
<rdf:li xml:lang='x-default'>I found one!</rdf:li>
</rdf:Alt>
</dc:title>
<dc:subject>
<rdf:Bag>
<rdf:li>Kids</rdf:li>
</rdf:Bag>
</dc:subject>
<photoshop:DateCreated>2018-09-28T16:07:07-04:00</photoshop:DateCreated>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:Iptc4xmpExt='http://iptc.org/std/Iptc4xmpExt/2008-02-29/'>
<Iptc4xmpExt:PersonInImage>
<rdf:Bag>
<rdf:li>Katie</rdf:li>
</rdf:Bag>
</Iptc4xmpExt:PersonInImage>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:digiKam='http://www.digikam.org/ns/1.0/'>
<digiKam:TagsList>
<rdf:Seq>
<rdf:li>Kids</rdf:li>
</rdf:Seq>
</digiKam:TagsList>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:xmp='http://ns.adobe.com/xap/1.0/'>
<xmp:CreateDate>2018-09-28T16:07:07</xmp:CreateDate>
<xmp:ModifyDate>2018-09-28T16:07:07</xmp:ModifyDate>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:exif='http://ns.adobe.com/exif/1.0/'>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>

View File

@@ -0,0 +1 @@
[{"EXIF:ImageDescription": "Girl holding pumpkin", "XMP:Description": "Girl holding pumpkin", "XMP:Title": "I found one!", "IPTC:Keywords": ["Kids"], "XMP:Subject": ["Kids"], "XMP:TagsList": ["Kids"], "XMP:PersonInImage": ["Katie"], "EXIF:DateTimeOriginal": "2018:09:28 16:07:07", "EXIF:CreateDate": "2018:09:28 16:07:07", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2018:09:28", "IPTC:TimeCreated": "16:07:07-04:00", "EXIF:ModifyDate": "2018:09:28 16:07:07"}]

View File

@@ -0,0 +1 @@
[{"EXIF:ImageDescription": "Girl holding pumpkin", "XMP:Description": "Girl holding pumpkin", "XMP:Title": "I found one!", "IPTC:Keywords": ["Folder1/SubFolder2/AlbumInFolder", "Kids", "Pumpkin Farm", "Test Album (1)"], "XMP:Subject": ["Folder1/SubFolder2/AlbumInFolder", "Kids", "Pumpkin Farm", "Test Album (1)"], "XMP:TagsList": ["Folder1/SubFolder2/AlbumInFolder", "Kids", "Pumpkin Farm", "Test Album (1)"], "XMP:PersonInImage": ["Katie"], "EXIF:DateTimeOriginal": "2018:09:28 16:07:07", "EXIF:CreateDate": "2018:09:28 16:07:07", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2018:09:28", "IPTC:TimeCreated": "16:07:07-04:00", "EXIF:ModifyDate": "2018:09:28 16:07:07"}]

View File

@@ -0,0 +1,58 @@
<!-- Created with osxphotos https://github.com/RhetTbull/osxphotos -->
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 5.4.0">
<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:photoshop="http://ns.adobe.com/photoshop/1.0/">
<photoshop:SidecarForExtension>jpg</photoshop:SidecarForExtension>
<dc:description>
<rdf:Alt>
<rdf:li xml:lang='x-default'>Girl holding pumpkin</rdf:li>
</rdf:Alt>
</dc:description>
<dc:title>
<rdf:Alt>
<rdf:li xml:lang='x-default'>I found one!</rdf:li>
</rdf:Alt>
</dc:title>
<dc:subject>
<rdf:Bag>
<rdf:li>2018</rdf:li>
<rdf:li>Folder1/SubFolder2/AlbumInFolder</rdf:li>
<rdf:li>Kids</rdf:li>
<rdf:li>Pumpkin Farm</rdf:li>
<rdf:li>Test Album (1)</rdf:li>
</rdf:Bag>
</dc:subject>
<photoshop:DateCreated>2018-09-28T16:07:07-04:00</photoshop:DateCreated>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:Iptc4xmpExt='http://iptc.org/std/Iptc4xmpExt/2008-02-29/'>
<Iptc4xmpExt:PersonInImage>
<rdf:Bag>
<rdf:li>Katie</rdf:li>
</rdf:Bag>
</Iptc4xmpExt:PersonInImage>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:digiKam='http://www.digikam.org/ns/1.0/'>
<digiKam:TagsList>
<rdf:Seq>
<rdf:li>2018</rdf:li>
<rdf:li>Folder1/SubFolder2/AlbumInFolder</rdf:li>
<rdf:li>Kids</rdf:li>
<rdf:li>Pumpkin Farm</rdf:li>
<rdf:li>Test Album (1)</rdf:li>
</rdf:Seq>
</digiKam:TagsList>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:xmp='http://ns.adobe.com/xap/1.0/'>
<xmp:CreateDate>2018-09-28T16:07:07</xmp:CreateDate>
<xmp:ModifyDate>2018-09-28T16:07:07</xmp:ModifyDate>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:exif='http://ns.adobe.com/exif/1.0/'>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>

View File

@@ -0,0 +1 @@
[{"ImageDescription": "Girl holding pumpkin", "Description": "Girl holding pumpkin", "Title": "I found one!", "Keywords": ["Kids"], "Subject": ["Kids"], "TagsList": ["Kids"], "PersonInImage": ["Katie"], "DateTimeOriginal": "2018:09:28 16:07:07", "CreateDate": "2018:09:28 16:07:07", "OffsetTimeOriginal": "-04:00", "DateCreated": "2018:09:28", "TimeCreated": "16:07:07-04:00", "ModifyDate": "2018:09:28 16:07:07"}]

View File

@@ -0,0 +1 @@
[{"EXIF:ImageDescription": "Girl holding pumpkin", "XMP:Description": "Girl holding pumpkin", "XMP:Title": "I found one!", "IPTC:Keywords": ["Katie", "Kids"], "XMP:Subject": ["Katie", "Kids"], "XMP:TagsList": ["Katie", "Kids"], "XMP:PersonInImage": ["Katie"], "EXIF:DateTimeOriginal": "2018:09:28 16:07:07", "EXIF:CreateDate": "2018:09:28 16:07:07", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2018:09:28", "IPTC:TimeCreated": "16:07:07-04:00", "EXIF:ModifyDate": "2018:09:28 16:07:07"}]

View File

@@ -0,0 +1,52 @@
<!-- Created with osxphotos https://github.com/RhetTbull/osxphotos -->
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 5.4.0">
<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:photoshop="http://ns.adobe.com/photoshop/1.0/">
<photoshop:SidecarForExtension>jpg</photoshop:SidecarForExtension>
<dc:description>
<rdf:Alt>
<rdf:li xml:lang='x-default'>Girl holding pumpkin</rdf:li>
</rdf:Alt>
</dc:description>
<dc:title>
<rdf:Alt>
<rdf:li xml:lang='x-default'>I found one!</rdf:li>
</rdf:Alt>
</dc:title>
<dc:subject>
<rdf:Bag>
<rdf:li>Katie</rdf:li>
<rdf:li>Kids</rdf:li>
</rdf:Bag>
</dc:subject>
<photoshop:DateCreated>2018-09-28T16:07:07-04:00</photoshop:DateCreated>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:Iptc4xmpExt='http://iptc.org/std/Iptc4xmpExt/2008-02-29/'>
<Iptc4xmpExt:PersonInImage>
<rdf:Bag>
<rdf:li>Katie</rdf:li>
</rdf:Bag>
</Iptc4xmpExt:PersonInImage>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:digiKam='http://www.digikam.org/ns/1.0/'>
<digiKam:TagsList>
<rdf:Seq>
<rdf:li>Katie</rdf:li>
<rdf:li>Kids</rdf:li>
</rdf:Seq>
</digiKam:TagsList>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:xmp='http://ns.adobe.com/xap/1.0/'>
<xmp:CreateDate>2018-09-28T16:07:07</xmp:CreateDate>
<xmp:ModifyDate>2018-09-28T16:07:07</xmp:ModifyDate>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:exif='http://ns.adobe.com/exif/1.0/'>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>

View File

@@ -0,0 +1 @@
[{"XMP:Title": "St. James's Park", "IPTC:Keywords": ["England", "London", "London 2018", "St. James's Park", "UK", "United Kingdom"], "XMP:Subject": ["England", "London", "London 2018", "St. James's Park", "UK", "United Kingdom"], "XMP:TagsList": ["England", "London", "London 2018", "St. James's Park", "UK", "United Kingdom"], "EXIF:GPSLatitude": 51.50357167, "EXIF:GPSLongitude": -0.1318055, "EXIF:GPSLatitudeRef": "N", "EXIF:GPSLongitudeRef": "W", "EXIF:DateTimeOriginal": "2018:10:13 09:18:12", "EXIF:CreateDate": "2018:10:13 09:18:12", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2018:10:13", "IPTC:TimeCreated": "09:18:12-04:00", "EXIF:ModifyDate": "2019:12:01 11:43:45"}]

View File

@@ -0,0 +1,57 @@
<!-- Created with osxphotos https://github.com/RhetTbull/osxphotos -->
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 5.4.0">
<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:photoshop="http://ns.adobe.com/photoshop/1.0/">
<photoshop:SidecarForExtension>jpg</photoshop:SidecarForExtension>
<dc:description>
<rdf:Alt>
<rdf:li xml:lang='x-default'></rdf:li>
</rdf:Alt>
</dc:description>
<dc:title>
<rdf:Alt>
<rdf:li xml:lang='x-default'>St. James&#39;s Park</rdf:li>
</rdf:Alt>
</dc:title>
<dc:subject>
<rdf:Bag>
<rdf:li>England</rdf:li>
<rdf:li>London</rdf:li>
<rdf:li>London 2018</rdf:li>
<rdf:li>St. James&#39;s Park</rdf:li>
<rdf:li>UK</rdf:li>
<rdf:li>United Kingdom</rdf:li>
</rdf:Bag>
</dc:subject>
<photoshop:DateCreated>2018-10-13T09:18:12.501000-04:00</photoshop:DateCreated>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:Iptc4xmpExt='http://iptc.org/std/Iptc4xmpExt/2008-02-29/'>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:digiKam='http://www.digikam.org/ns/1.0/'>
<digiKam:TagsList>
<rdf:Seq>
<rdf:li>England</rdf:li>
<rdf:li>London</rdf:li>
<rdf:li>London 2018</rdf:li>
<rdf:li>St. James&#39;s Park</rdf:li>
<rdf:li>UK</rdf:li>
<rdf:li>United Kingdom</rdf:li>
</rdf:Seq>
</digiKam:TagsList>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:xmp='http://ns.adobe.com/xap/1.0/'>
<xmp:CreateDate>2018-10-13T09:18:12</xmp:CreateDate>
<xmp:ModifyDate>2018-10-13T09:18:12</xmp:ModifyDate>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:exif='http://ns.adobe.com/exif/1.0/'>
<exif:GPSLongitude>0,7.908329999999999W</exif:GPSLongitude>
<exif:GPSLatitude>51,30.21430019999997N</exif:GPSLatitude>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>

View File

@@ -0,0 +1 @@
[{"XMP:Title": "St. James's Park", "IPTC:Keywords": ["England", "London", "London 2018", "St. James's Park", "UK", "United Kingdom"], "XMP:Subject": ["England", "London", "London 2018", "St. James's Park", "UK", "United Kingdom"], "XMP:TagsList": ["England", "London", "London 2018", "St. James's Park", "UK", "United Kingdom"], "EXIF:GPSLatitude": 51.50357167, "EXIF:GPSLongitude": -0.1318055, "EXIF:GPSLatitudeRef": "N", "EXIF:GPSLongitudeRef": "W", "EXIF:DateTimeOriginal": "2018:10:13 09:18:12", "EXIF:CreateDate": "2018:10:13 09:18:12", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2018:10:13", "IPTC:TimeCreated": "09:18:12-04:00", "EXIF:ModifyDate": "2019:12:01 11:43:45"}]

View File

@@ -0,0 +1,57 @@
<!-- Created with osxphotos https://github.com/RhetTbull/osxphotos -->
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 5.4.0">
<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:photoshop="http://ns.adobe.com/photoshop/1.0/">
<photoshop:SidecarForExtension>jpg</photoshop:SidecarForExtension>
<dc:description>
<rdf:Alt>
<rdf:li xml:lang='x-default'></rdf:li>
</rdf:Alt>
</dc:description>
<dc:title>
<rdf:Alt>
<rdf:li xml:lang='x-default'>St. James&#39;s Park</rdf:li>
</rdf:Alt>
</dc:title>
<dc:subject>
<rdf:Bag>
<rdf:li>England</rdf:li>
<rdf:li>London</rdf:li>
<rdf:li>London 2018</rdf:li>
<rdf:li>St. James&#39;s Park</rdf:li>
<rdf:li>UK</rdf:li>
<rdf:li>United Kingdom</rdf:li>
</rdf:Bag>
</dc:subject>
<photoshop:DateCreated>2018-10-13T09:18:12.501000-04:00</photoshop:DateCreated>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:Iptc4xmpExt='http://iptc.org/std/Iptc4xmpExt/2008-02-29/'>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:digiKam='http://www.digikam.org/ns/1.0/'>
<digiKam:TagsList>
<rdf:Seq>
<rdf:li>England</rdf:li>
<rdf:li>London</rdf:li>
<rdf:li>London 2018</rdf:li>
<rdf:li>St. James&#39;s Park</rdf:li>
<rdf:li>UK</rdf:li>
<rdf:li>United Kingdom</rdf:li>
</rdf:Seq>
</digiKam:TagsList>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:xmp='http://ns.adobe.com/xap/1.0/'>
<xmp:CreateDate>2018-10-13T09:18:12</xmp:CreateDate>
<xmp:ModifyDate>2018-10-13T09:18:12</xmp:ModifyDate>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:exif='http://ns.adobe.com/exif/1.0/'>
<exif:GPSLongitude>0,7.908329999999999W</exif:GPSLongitude>
<exif:GPSLatitude>51,30.21430019999997N</exif:GPSLatitude>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>

View File

@@ -0,0 +1,57 @@
<!-- Created with osxphotos https://github.com/RhetTbull/osxphotos -->
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 5.4.0">
<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:photoshop="http://ns.adobe.com/photoshop/1.0/">
<photoshop:SidecarForExtension>jpg</photoshop:SidecarForExtension>
<dc:description>
<rdf:Alt>
<rdf:li xml:lang='x-default'></rdf:li>
</rdf:Alt>
</dc:description>
<dc:title>
<rdf:Alt>
<rdf:li xml:lang='x-default'>St. James&#39;s Park</rdf:li>
</rdf:Alt>
</dc:title>
<dc:subject>
<rdf:Bag>
<rdf:li>England</rdf:li>
<rdf:li>London</rdf:li>
<rdf:li>London 2018</rdf:li>
<rdf:li>St. James&#39;s Park</rdf:li>
<rdf:li>UK</rdf:li>
<rdf:li>United Kingdom</rdf:li>
</rdf:Bag>
</dc:subject>
<photoshop:DateCreated>2018-10-13T09:18:12.501000-04:00</photoshop:DateCreated>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:Iptc4xmpExt='http://iptc.org/std/Iptc4xmpExt/2008-02-29/'>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:digiKam='http://www.digikam.org/ns/1.0/'>
<digiKam:TagsList>
<rdf:Seq>
<rdf:li>England</rdf:li>
<rdf:li>London</rdf:li>
<rdf:li>London 2018</rdf:li>
<rdf:li>St. James&#39;s Park</rdf:li>
<rdf:li>UK</rdf:li>
<rdf:li>United Kingdom</rdf:li>
</rdf:Seq>
</digiKam:TagsList>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:xmp='http://ns.adobe.com/xap/1.0/'>
<xmp:CreateDate>2018-10-13T09:18:12</xmp:CreateDate>
<xmp:ModifyDate>2018-10-13T09:18:12</xmp:ModifyDate>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:exif='http://ns.adobe.com/exif/1.0/'>
<exif:GPSLongitude>0,7.908329999999999W</exif:GPSLongitude>
<exif:GPSLatitude>51,30.21430019999997N</exif:GPSLatitude>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>

View File

@@ -0,0 +1 @@
[{"XMP:Title": "St. James's Park", "IPTC:Keywords": ["England", "London", "London 2018", "St. James's Park", "UK", "United Kingdom"], "XMP:Subject": ["England", "London", "London 2018", "St. James's Park", "UK", "United Kingdom"], "XMP:TagsList": ["England", "London", "London 2018", "St. James's Park", "UK", "United Kingdom"], "EXIF:GPSLatitude": 51.50357167, "EXIF:GPSLongitude": -0.1318055, "EXIF:GPSLatitudeRef": "N", "EXIF:GPSLongitudeRef": "W", "EXIF:DateTimeOriginal": "2018:10:13 09:18:12", "EXIF:CreateDate": "2018:10:13 09:18:12", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2018:10:13", "IPTC:TimeCreated": "09:18:12-04:00", "EXIF:ModifyDate": "2018:10:13 09:18:12"}]

View File

@@ -0,0 +1 @@
[{"XMP:Title": "St. James's Park", "IPTC:Keywords": ["England", "London", "London 2018", "St. James's Park", "UK", "United Kingdom"], "XMP:Subject": ["England", "London", "London 2018", "St. James's Park", "UK", "United Kingdom"], "XMP:TagsList": ["England", "London", "London 2018", "St. James's Park", "UK", "United Kingdom"], "EXIF:GPSLatitude": 51.50357167, "EXIF:GPSLongitude": -0.1318055, "EXIF:GPSLatitudeRef": "N", "EXIF:GPSLongitudeRef": "W", "EXIF:DateTimeOriginal": "2018:10:13 09:18:12", "EXIF:CreateDate": "2018:10:13 09:18:12", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2018:10:13", "IPTC:TimeCreated": "09:18:12-04:00", "EXIF:ModifyDate": "2019:12:01 11:43:45"}]

View File

@@ -0,0 +1,59 @@
<!-- Created with osxphotos https://github.com/RhetTbull/osxphotos -->
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 5.4.0">
<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:photoshop="http://ns.adobe.com/photoshop/1.0/">
<photoshop:SidecarForExtension>jpg</photoshop:SidecarForExtension>
<dc:description>
<rdf:Alt>
<rdf:li xml:lang='x-default'></rdf:li>
</rdf:Alt>
</dc:description>
<dc:title>
<rdf:Alt>
<rdf:li xml:lang='x-default'>St. James&#39;s Park</rdf:li>
</rdf:Alt>
</dc:title>
<dc:subject>
<rdf:Bag>
<rdf:li>2018</rdf:li>
<rdf:li>England</rdf:li>
<rdf:li>London</rdf:li>
<rdf:li>London 2018</rdf:li>
<rdf:li>St. James&#39;s Park</rdf:li>
<rdf:li>UK</rdf:li>
<rdf:li>United Kingdom</rdf:li>
</rdf:Bag>
</dc:subject>
<photoshop:DateCreated>2018-10-13T09:18:12.501000-04:00</photoshop:DateCreated>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:Iptc4xmpExt='http://iptc.org/std/Iptc4xmpExt/2008-02-29/'>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:digiKam='http://www.digikam.org/ns/1.0/'>
<digiKam:TagsList>
<rdf:Seq>
<rdf:li>2018</rdf:li>
<rdf:li>England</rdf:li>
<rdf:li>London</rdf:li>
<rdf:li>London 2018</rdf:li>
<rdf:li>St. James&#39;s Park</rdf:li>
<rdf:li>UK</rdf:li>
<rdf:li>United Kingdom</rdf:li>
</rdf:Seq>
</digiKam:TagsList>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:xmp='http://ns.adobe.com/xap/1.0/'>
<xmp:CreateDate>2018-10-13T09:18:12</xmp:CreateDate>
<xmp:ModifyDate>2018-10-13T09:18:12</xmp:ModifyDate>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:exif='http://ns.adobe.com/exif/1.0/'>
<exif:GPSLongitude>0,7.908329999999999W</exif:GPSLongitude>
<exif:GPSLatitude>51,30.21430019999997N</exif:GPSLatitude>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>

View File

@@ -0,0 +1 @@
[{"Title": "St. James's Park", "Keywords": ["England", "London", "London 2018", "St. James's Park", "UK", "United Kingdom"], "Subject": ["England", "London", "London 2018", "St. James's Park", "UK", "United Kingdom"], "TagsList": ["England", "London", "London 2018", "St. James's Park", "UK", "United Kingdom"], "GPSLatitude": 51.50357167, "GPSLongitude": -0.1318055, "GPSLatitudeRef": "N", "GPSLongitudeRef": "W", "DateTimeOriginal": "2018:10:13 09:18:12", "CreateDate": "2018:10:13 09:18:12", "OffsetTimeOriginal": "-04:00", "DateCreated": "2018:10:13", "TimeCreated": "09:18:12-04:00", "ModifyDate": "2019:12:01 11:43:45"}]

View File

@@ -0,0 +1 @@
[{"XMP:Title": "St. James's Park", "IPTC:Keywords": ["England", "London", "London 2018", "St. James's Park", "UK", "United Kingdom"], "XMP:Subject": ["England", "London", "London 2018", "St. James's Park", "UK", "United Kingdom"], "XMP:TagsList": ["England", "London", "London 2018", "St. James's Park", "UK", "United Kingdom"], "EXIF:GPSLatitude": 51.50357167, "EXIF:GPSLongitude": -0.1318055, "EXIF:GPSLatitudeRef": "N", "EXIF:GPSLongitudeRef": "W", "EXIF:DateTimeOriginal": "2018:10:13 09:18:12", "EXIF:CreateDate": "2018:10:13 09:18:12", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2018:10:13", "IPTC:TimeCreated": "09:18:12-04:00", "EXIF:ModifyDate": "2019:12:01 11:43:45"}]

View File

@@ -0,0 +1,57 @@
<!-- Created with osxphotos https://github.com/RhetTbull/osxphotos -->
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 5.4.0">
<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:photoshop="http://ns.adobe.com/photoshop/1.0/">
<photoshop:SidecarForExtension>jpg</photoshop:SidecarForExtension>
<dc:description>
<rdf:Alt>
<rdf:li xml:lang='x-default'></rdf:li>
</rdf:Alt>
</dc:description>
<dc:title>
<rdf:Alt>
<rdf:li xml:lang='x-default'>St. James&#39;s Park</rdf:li>
</rdf:Alt>
</dc:title>
<dc:subject>
<rdf:Bag>
<rdf:li>England</rdf:li>
<rdf:li>London</rdf:li>
<rdf:li>London 2018</rdf:li>
<rdf:li>St. James&#39;s Park</rdf:li>
<rdf:li>UK</rdf:li>
<rdf:li>United Kingdom</rdf:li>
</rdf:Bag>
</dc:subject>
<photoshop:DateCreated>2018-10-13T09:18:12.501000-04:00</photoshop:DateCreated>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:Iptc4xmpExt='http://iptc.org/std/Iptc4xmpExt/2008-02-29/'>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:digiKam='http://www.digikam.org/ns/1.0/'>
<digiKam:TagsList>
<rdf:Seq>
<rdf:li>England</rdf:li>
<rdf:li>London</rdf:li>
<rdf:li>London 2018</rdf:li>
<rdf:li>St. James&#39;s Park</rdf:li>
<rdf:li>UK</rdf:li>
<rdf:li>United Kingdom</rdf:li>
</rdf:Seq>
</digiKam:TagsList>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:xmp='http://ns.adobe.com/xap/1.0/'>
<xmp:CreateDate>2018-10-13T09:18:12</xmp:CreateDate>
<xmp:ModifyDate>2018-10-13T09:18:12</xmp:ModifyDate>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:exif='http://ns.adobe.com/exif/1.0/'>
<exif:GPSLongitude>0,7.908329999999999W</exif:GPSLongitude>
<exif:GPSLatitude>51,30.21430019999997N</exif:GPSLatitude>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>

View File

@@ -0,0 +1 @@
[{"EXIF:ImageDescription": "Wedding tulips", "XMP:Description": "Wedding tulips", "XMP:Title": "Tulips tied together at a flower shop", "IPTC:Keywords": ["flowers", "wedding"], "XMP:Subject": ["flowers", "wedding"], "XMP:TagsList": ["flowers", "wedding"], "EXIF:DateTimeOriginal": "2019:07:04 16:24:01", "EXIF:CreateDate": "2019:07:04 16:24:01", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2019:07:04", "IPTC:TimeCreated": "16:24:01-04:00", "EXIF:ModifyDate": "2020:05:28 23:39:38"}]

View File

@@ -0,0 +1,47 @@
<!-- Created with osxphotos https://github.com/RhetTbull/osxphotos -->
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 5.4.0">
<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:photoshop="http://ns.adobe.com/photoshop/1.0/">
<photoshop:SidecarForExtension>jpg</photoshop:SidecarForExtension>
<dc:description>
<rdf:Alt>
<rdf:li xml:lang='x-default'>Wedding tulips</rdf:li>
</rdf:Alt>
</dc:description>
<dc:title>
<rdf:Alt>
<rdf:li xml:lang='x-default'>Tulips tied together at a flower shop</rdf:li>
</rdf:Alt>
</dc:title>
<dc:subject>
<rdf:Bag>
<rdf:li>flowers</rdf:li>
<rdf:li>wedding</rdf:li>
</rdf:Bag>
</dc:subject>
<photoshop:DateCreated>2019-07-04T16:24:01-04:00</photoshop:DateCreated>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:Iptc4xmpExt='http://iptc.org/std/Iptc4xmpExt/2008-02-29/'>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:digiKam='http://www.digikam.org/ns/1.0/'>
<digiKam:TagsList>
<rdf:Seq>
<rdf:li>flowers</rdf:li>
<rdf:li>wedding</rdf:li>
</rdf:Seq>
</digiKam:TagsList>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:xmp='http://ns.adobe.com/xap/1.0/'>
<xmp:CreateDate>2019-07-04T16:24:01</xmp:CreateDate>
<xmp:ModifyDate>2019-07-04T16:24:01</xmp:ModifyDate>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:exif='http://ns.adobe.com/exif/1.0/'>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>

View File

@@ -0,0 +1 @@
[{"EXIF:ImageDescription": "Wedding tulips", "XMP:Description": "Wedding tulips", "XMP:Title": "Tulips tied together at a flower shop", "IPTC:Keywords": ["flowers", "wedding"], "XMP:Subject": ["flowers", "wedding"], "XMP:TagsList": ["flowers", "wedding"], "EXIF:DateTimeOriginal": "2019:07:04 16:24:01", "EXIF:CreateDate": "2019:07:04 16:24:01", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2019:07:04", "IPTC:TimeCreated": "16:24:01-04:00", "EXIF:ModifyDate": "2020:05:28 23:39:38"}]

View File

@@ -0,0 +1,47 @@
<!-- Created with osxphotos https://github.com/RhetTbull/osxphotos -->
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 5.4.0">
<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:photoshop="http://ns.adobe.com/photoshop/1.0/">
<photoshop:SidecarForExtension>jpg</photoshop:SidecarForExtension>
<dc:description>
<rdf:Alt>
<rdf:li xml:lang='x-default'>Wedding tulips</rdf:li>
</rdf:Alt>
</dc:description>
<dc:title>
<rdf:Alt>
<rdf:li xml:lang='x-default'>Tulips tied together at a flower shop</rdf:li>
</rdf:Alt>
</dc:title>
<dc:subject>
<rdf:Bag>
<rdf:li>flowers</rdf:li>
<rdf:li>wedding</rdf:li>
</rdf:Bag>
</dc:subject>
<photoshop:DateCreated>2019-07-04T16:24:01-04:00</photoshop:DateCreated>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:Iptc4xmpExt='http://iptc.org/std/Iptc4xmpExt/2008-02-29/'>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:digiKam='http://www.digikam.org/ns/1.0/'>
<digiKam:TagsList>
<rdf:Seq>
<rdf:li>flowers</rdf:li>
<rdf:li>wedding</rdf:li>
</rdf:Seq>
</digiKam:TagsList>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:xmp='http://ns.adobe.com/xap/1.0/'>
<xmp:CreateDate>2019-07-04T16:24:01</xmp:CreateDate>
<xmp:ModifyDate>2019-07-04T16:24:01</xmp:ModifyDate>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:exif='http://ns.adobe.com/exif/1.0/'>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>

View File

@@ -0,0 +1,47 @@
<!-- Created with osxphotos https://github.com/RhetTbull/osxphotos -->
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 5.4.0">
<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:photoshop="http://ns.adobe.com/photoshop/1.0/">
<photoshop:SidecarForExtension>jpg</photoshop:SidecarForExtension>
<dc:description>
<rdf:Alt>
<rdf:li xml:lang='x-default'>Wedding tulips</rdf:li>
</rdf:Alt>
</dc:description>
<dc:title>
<rdf:Alt>
<rdf:li xml:lang='x-default'>Tulips tied together at a flower shop</rdf:li>
</rdf:Alt>
</dc:title>
<dc:subject>
<rdf:Bag>
<rdf:li>flowers</rdf:li>
<rdf:li>wedding</rdf:li>
</rdf:Bag>
</dc:subject>
<photoshop:DateCreated>2019-07-04T16:24:01-04:00</photoshop:DateCreated>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:Iptc4xmpExt='http://iptc.org/std/Iptc4xmpExt/2008-02-29/'>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:digiKam='http://www.digikam.org/ns/1.0/'>
<digiKam:TagsList>
<rdf:Seq>
<rdf:li>flowers</rdf:li>
<rdf:li>wedding</rdf:li>
</rdf:Seq>
</digiKam:TagsList>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:xmp='http://ns.adobe.com/xap/1.0/'>
<xmp:CreateDate>2019-07-04T16:24:01</xmp:CreateDate>
<xmp:ModifyDate>2019-07-04T16:24:01</xmp:ModifyDate>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:exif='http://ns.adobe.com/exif/1.0/'>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>

View File

@@ -0,0 +1 @@
[{"EXIF:ImageDescription": "Wedding tulips", "XMP:Description": "Wedding tulips", "XMP:Title": "Tulips tied together at a flower shop", "IPTC:Keywords": ["flowers", "wedding"], "XMP:Subject": ["flowers", "wedding"], "XMP:TagsList": ["flowers", "wedding"], "EXIF:DateTimeOriginal": "2019:07:04 16:24:01", "EXIF:CreateDate": "2019:07:04 16:24:01", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2019:07:04", "IPTC:TimeCreated": "16:24:01-04:00", "EXIF:ModifyDate": "2019:07:04 16:24:01"}]

View File

@@ -0,0 +1 @@
[{"EXIF:ImageDescription": "Wedding tulips", "XMP:Description": "Wedding tulips", "XMP:Title": "Tulips tied together at a flower shop", "IPTC:Keywords": ["flowers", "wedding"], "XMP:Subject": ["flowers", "wedding"], "XMP:TagsList": ["flowers", "wedding"], "EXIF:DateTimeOriginal": "2019:07:04 16:24:01", "EXIF:CreateDate": "2019:07:04 16:24:01", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2019:07:04", "IPTC:TimeCreated": "16:24:01-04:00", "EXIF:ModifyDate": "2020:05:28 23:39:38"}]

View File

@@ -0,0 +1,49 @@
<!-- Created with osxphotos https://github.com/RhetTbull/osxphotos -->
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 5.4.0">
<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:photoshop="http://ns.adobe.com/photoshop/1.0/">
<photoshop:SidecarForExtension>jpg</photoshop:SidecarForExtension>
<dc:description>
<rdf:Alt>
<rdf:li xml:lang='x-default'>Wedding tulips</rdf:li>
</rdf:Alt>
</dc:description>
<dc:title>
<rdf:Alt>
<rdf:li xml:lang='x-default'>Tulips tied together at a flower shop</rdf:li>
</rdf:Alt>
</dc:title>
<dc:subject>
<rdf:Bag>
<rdf:li>2019</rdf:li>
<rdf:li>flowers</rdf:li>
<rdf:li>wedding</rdf:li>
</rdf:Bag>
</dc:subject>
<photoshop:DateCreated>2019-07-04T16:24:01-04:00</photoshop:DateCreated>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:Iptc4xmpExt='http://iptc.org/std/Iptc4xmpExt/2008-02-29/'>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:digiKam='http://www.digikam.org/ns/1.0/'>
<digiKam:TagsList>
<rdf:Seq>
<rdf:li>2019</rdf:li>
<rdf:li>flowers</rdf:li>
<rdf:li>wedding</rdf:li>
</rdf:Seq>
</digiKam:TagsList>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:xmp='http://ns.adobe.com/xap/1.0/'>
<xmp:CreateDate>2019-07-04T16:24:01</xmp:CreateDate>
<xmp:ModifyDate>2019-07-04T16:24:01</xmp:ModifyDate>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:exif='http://ns.adobe.com/exif/1.0/'>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>

View File

@@ -0,0 +1 @@
[{"ImageDescription": "Wedding tulips", "Description": "Wedding tulips", "Title": "Tulips tied together at a flower shop", "Keywords": ["flowers", "wedding"], "Subject": ["flowers", "wedding"], "TagsList": ["flowers", "wedding"], "DateTimeOriginal": "2019:07:04 16:24:01", "CreateDate": "2019:07:04 16:24:01", "OffsetTimeOriginal": "-04:00", "DateCreated": "2019:07:04", "TimeCreated": "16:24:01-04:00", "ModifyDate": "2020:05:28 23:39:38"}]

View File

@@ -0,0 +1 @@
[{"EXIF:ImageDescription": "Wedding tulips", "XMP:Description": "Wedding tulips", "XMP:Title": "Tulips tied together at a flower shop", "IPTC:Keywords": ["flowers", "wedding"], "XMP:Subject": ["flowers", "wedding"], "XMP:TagsList": ["flowers", "wedding"], "EXIF:DateTimeOriginal": "2019:07:04 16:24:01", "EXIF:CreateDate": "2019:07:04 16:24:01", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2019:07:04", "IPTC:TimeCreated": "16:24:01-04:00", "EXIF:ModifyDate": "2020:05:28 23:39:38"}]

View File

@@ -0,0 +1,47 @@
<!-- Created with osxphotos https://github.com/RhetTbull/osxphotos -->
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 5.4.0">
<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:photoshop="http://ns.adobe.com/photoshop/1.0/">
<photoshop:SidecarForExtension>jpg</photoshop:SidecarForExtension>
<dc:description>
<rdf:Alt>
<rdf:li xml:lang='x-default'>Wedding tulips</rdf:li>
</rdf:Alt>
</dc:description>
<dc:title>
<rdf:Alt>
<rdf:li xml:lang='x-default'>Tulips tied together at a flower shop</rdf:li>
</rdf:Alt>
</dc:title>
<dc:subject>
<rdf:Bag>
<rdf:li>flowers</rdf:li>
<rdf:li>wedding</rdf:li>
</rdf:Bag>
</dc:subject>
<photoshop:DateCreated>2019-07-04T16:24:01-04:00</photoshop:DateCreated>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:Iptc4xmpExt='http://iptc.org/std/Iptc4xmpExt/2008-02-29/'>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:digiKam='http://www.digikam.org/ns/1.0/'>
<digiKam:TagsList>
<rdf:Seq>
<rdf:li>flowers</rdf:li>
<rdf:li>wedding</rdf:li>
</rdf:Seq>
</digiKam:TagsList>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:xmp='http://ns.adobe.com/xap/1.0/'>
<xmp:CreateDate>2019-07-04T16:24:01</xmp:CreateDate>
<xmp:ModifyDate>2019-07-04T16:24:01</xmp:ModifyDate>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:exif='http://ns.adobe.com/exif/1.0/'>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>

View File

@@ -0,0 +1 @@
[{"EXIF:ImageDescription": "Bride Wedding day", "XMP:Description": "Bride Wedding day", "IPTC:Keywords": ["wedding"], "XMP:Subject": ["wedding"], "XMP:TagsList": ["wedding"], "XMP:PersonInImage": ["Maria"], "EXIF:DateTimeOriginal": "2019:04:15 14:40:24", "EXIF:CreateDate": "2019:04:15 14:40:24", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2019:04:15", "IPTC:TimeCreated": "14:40:24-04:00", "EXIF:ModifyDate": "2019:11:27 01:30:16"}]

View File

@@ -0,0 +1,50 @@
<!-- Created with osxphotos https://github.com/RhetTbull/osxphotos -->
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 5.4.0">
<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:photoshop="http://ns.adobe.com/photoshop/1.0/">
<photoshop:SidecarForExtension>jpg</photoshop:SidecarForExtension>
<dc:description>
<rdf:Alt>
<rdf:li xml:lang='x-default'>Bride Wedding day</rdf:li>
</rdf:Alt>
</dc:description>
<dc:title>
<rdf:Alt>
<rdf:li xml:lang='x-default'/>
</rdf:Alt>
</dc:title>
<dc:subject>
<rdf:Bag>
<rdf:li>wedding</rdf:li>
</rdf:Bag>
</dc:subject>
<photoshop:DateCreated>2019-04-15T14:40:24.086000-04:00</photoshop:DateCreated>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:Iptc4xmpExt='http://iptc.org/std/Iptc4xmpExt/2008-02-29/'>
<Iptc4xmpExt:PersonInImage>
<rdf:Bag>
<rdf:li>Maria</rdf:li>
</rdf:Bag>
</Iptc4xmpExt:PersonInImage>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:digiKam='http://www.digikam.org/ns/1.0/'>
<digiKam:TagsList>
<rdf:Seq>
<rdf:li>wedding</rdf:li>
</rdf:Seq>
</digiKam:TagsList>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:xmp='http://ns.adobe.com/xap/1.0/'>
<xmp:CreateDate>2019-04-15T14:40:24</xmp:CreateDate>
<xmp:ModifyDate>2019-04-15T14:40:24</xmp:ModifyDate>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:exif='http://ns.adobe.com/exif/1.0/'>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>

View File

@@ -0,0 +1 @@
[{"EXIF:ImageDescription": "Bride Wedding day", "XMP:Description": "Bride Wedding day", "IPTC:Keywords": ["wedding"], "XMP:Subject": ["wedding"], "XMP:TagsList": ["wedding"], "XMP:PersonInImage": ["Maria"], "EXIF:DateTimeOriginal": "2019:04:15 14:40:24", "EXIF:CreateDate": "2019:04:15 14:40:24", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2019:04:15", "IPTC:TimeCreated": "14:40:24-04:00", "EXIF:ModifyDate": "2019:11:27 01:30:16"}]

View File

@@ -0,0 +1,50 @@
<!-- Created with osxphotos https://github.com/RhetTbull/osxphotos -->
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 5.4.0">
<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:photoshop="http://ns.adobe.com/photoshop/1.0/">
<photoshop:SidecarForExtension>jpg</photoshop:SidecarForExtension>
<dc:description>
<rdf:Alt>
<rdf:li xml:lang='x-default'>Bride Wedding day</rdf:li>
</rdf:Alt>
</dc:description>
<dc:title>
<rdf:Alt>
<rdf:li xml:lang='x-default'/>
</rdf:Alt>
</dc:title>
<dc:subject>
<rdf:Bag>
<rdf:li>wedding</rdf:li>
</rdf:Bag>
</dc:subject>
<photoshop:DateCreated>2019-04-15T14:40:24.086000-04:00</photoshop:DateCreated>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:Iptc4xmpExt='http://iptc.org/std/Iptc4xmpExt/2008-02-29/'>
<Iptc4xmpExt:PersonInImage>
<rdf:Bag>
<rdf:li>Maria</rdf:li>
</rdf:Bag>
</Iptc4xmpExt:PersonInImage>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:digiKam='http://www.digikam.org/ns/1.0/'>
<digiKam:TagsList>
<rdf:Seq>
<rdf:li>wedding</rdf:li>
</rdf:Seq>
</digiKam:TagsList>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:xmp='http://ns.adobe.com/xap/1.0/'>
<xmp:CreateDate>2019-04-15T14:40:24</xmp:CreateDate>
<xmp:ModifyDate>2019-04-15T14:40:24</xmp:ModifyDate>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:exif='http://ns.adobe.com/exif/1.0/'>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>

View File

@@ -0,0 +1,50 @@
<!-- Created with osxphotos https://github.com/RhetTbull/osxphotos -->
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 5.4.0">
<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:photoshop="http://ns.adobe.com/photoshop/1.0/">
<photoshop:SidecarForExtension>jpg</photoshop:SidecarForExtension>
<dc:description>
<rdf:Alt>
<rdf:li xml:lang='x-default'>Bride Wedding day</rdf:li>
</rdf:Alt>
</dc:description>
<dc:title>
<rdf:Alt>
<rdf:li xml:lang='x-default'/>
</rdf:Alt>
</dc:title>
<dc:subject>
<rdf:Bag>
<rdf:li>wedding</rdf:li>
</rdf:Bag>
</dc:subject>
<photoshop:DateCreated>2019-04-15T14:40:24.086000-04:00</photoshop:DateCreated>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:Iptc4xmpExt='http://iptc.org/std/Iptc4xmpExt/2008-02-29/'>
<Iptc4xmpExt:PersonInImage>
<rdf:Bag>
<rdf:li>Maria</rdf:li>
</rdf:Bag>
</Iptc4xmpExt:PersonInImage>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:digiKam='http://www.digikam.org/ns/1.0/'>
<digiKam:TagsList>
<rdf:Seq>
<rdf:li>wedding</rdf:li>
</rdf:Seq>
</digiKam:TagsList>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:xmp='http://ns.adobe.com/xap/1.0/'>
<xmp:CreateDate>2019-04-15T14:40:24</xmp:CreateDate>
<xmp:ModifyDate>2019-04-15T14:40:24</xmp:ModifyDate>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:exif='http://ns.adobe.com/exif/1.0/'>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>

View File

@@ -0,0 +1 @@
[{"EXIF:ImageDescription": "Bride Wedding day", "XMP:Description": "Bride Wedding day", "IPTC:Keywords": ["wedding"], "XMP:Subject": ["wedding"], "XMP:TagsList": ["wedding"], "XMP:PersonInImage": ["Maria"], "EXIF:DateTimeOriginal": "2019:04:15 14:40:24", "EXIF:CreateDate": "2019:04:15 14:40:24", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2019:04:15", "IPTC:TimeCreated": "14:40:24-04:00", "EXIF:ModifyDate": "2019:04:15 14:40:24"}]

View File

@@ -0,0 +1 @@
[{"EXIF:ImageDescription": "Bride Wedding day", "XMP:Description": "Bride Wedding day", "IPTC:Keywords": ["wedding"], "XMP:Subject": ["wedding"], "XMP:TagsList": ["wedding"], "XMP:PersonInImage": ["Maria"], "EXIF:DateTimeOriginal": "2019:04:15 14:40:24", "EXIF:CreateDate": "2019:04:15 14:40:24", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2019:04:15", "IPTC:TimeCreated": "14:40:24-04:00", "EXIF:ModifyDate": "2019:11:27 01:30:16"}]

View File

@@ -0,0 +1,52 @@
<!-- Created with osxphotos https://github.com/RhetTbull/osxphotos -->
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 5.4.0">
<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:photoshop="http://ns.adobe.com/photoshop/1.0/">
<photoshop:SidecarForExtension>jpg</photoshop:SidecarForExtension>
<dc:description>
<rdf:Alt>
<rdf:li xml:lang='x-default'>Bride Wedding day</rdf:li>
</rdf:Alt>
</dc:description>
<dc:title>
<rdf:Alt>
<rdf:li xml:lang='x-default'/>
</rdf:Alt>
</dc:title>
<dc:subject>
<rdf:Bag>
<rdf:li>2019</rdf:li>
<rdf:li>wedding</rdf:li>
</rdf:Bag>
</dc:subject>
<photoshop:DateCreated>2019-04-15T14:40:24.086000-04:00</photoshop:DateCreated>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:Iptc4xmpExt='http://iptc.org/std/Iptc4xmpExt/2008-02-29/'>
<Iptc4xmpExt:PersonInImage>
<rdf:Bag>
<rdf:li>Maria</rdf:li>
</rdf:Bag>
</Iptc4xmpExt:PersonInImage>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:digiKam='http://www.digikam.org/ns/1.0/'>
<digiKam:TagsList>
<rdf:Seq>
<rdf:li>2019</rdf:li>
<rdf:li>wedding</rdf:li>
</rdf:Seq>
</digiKam:TagsList>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:xmp='http://ns.adobe.com/xap/1.0/'>
<xmp:CreateDate>2019-04-15T14:40:24</xmp:CreateDate>
<xmp:ModifyDate>2019-04-15T14:40:24</xmp:ModifyDate>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:exif='http://ns.adobe.com/exif/1.0/'>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>

View File

@@ -0,0 +1 @@
[{"ImageDescription": "Bride Wedding day", "Description": "Bride Wedding day", "Keywords": ["wedding"], "Subject": ["wedding"], "TagsList": ["wedding"], "PersonInImage": ["Maria"], "DateTimeOriginal": "2019:04:15 14:40:24", "CreateDate": "2019:04:15 14:40:24", "OffsetTimeOriginal": "-04:00", "DateCreated": "2019:04:15", "TimeCreated": "14:40:24-04:00", "ModifyDate": "2019:11:27 01:30:16"}]

View File

@@ -0,0 +1 @@
[{"EXIF:ImageDescription": "Bride Wedding day", "XMP:Description": "Bride Wedding day", "IPTC:Keywords": ["Maria", "wedding"], "XMP:Subject": ["Maria", "wedding"], "XMP:TagsList": ["Maria", "wedding"], "XMP:PersonInImage": ["Maria"], "EXIF:DateTimeOriginal": "2019:04:15 14:40:24", "EXIF:CreateDate": "2019:04:15 14:40:24", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2019:04:15", "IPTC:TimeCreated": "14:40:24-04:00", "EXIF:ModifyDate": "2019:11:27 01:30:16"}]

View File

@@ -0,0 +1,52 @@
<!-- Created with osxphotos https://github.com/RhetTbull/osxphotos -->
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 5.4.0">
<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:photoshop="http://ns.adobe.com/photoshop/1.0/">
<photoshop:SidecarForExtension>jpg</photoshop:SidecarForExtension>
<dc:description>
<rdf:Alt>
<rdf:li xml:lang='x-default'>Bride Wedding day</rdf:li>
</rdf:Alt>
</dc:description>
<dc:title>
<rdf:Alt>
<rdf:li xml:lang='x-default'/>
</rdf:Alt>
</dc:title>
<dc:subject>
<rdf:Bag>
<rdf:li>Maria</rdf:li>
<rdf:li>wedding</rdf:li>
</rdf:Bag>
</dc:subject>
<photoshop:DateCreated>2019-04-15T14:40:24.086000-04:00</photoshop:DateCreated>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:Iptc4xmpExt='http://iptc.org/std/Iptc4xmpExt/2008-02-29/'>
<Iptc4xmpExt:PersonInImage>
<rdf:Bag>
<rdf:li>Maria</rdf:li>
</rdf:Bag>
</Iptc4xmpExt:PersonInImage>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:digiKam='http://www.digikam.org/ns/1.0/'>
<digiKam:TagsList>
<rdf:Seq>
<rdf:li>Maria</rdf:li>
<rdf:li>wedding</rdf:li>
</rdf:Seq>
</digiKam:TagsList>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:xmp='http://ns.adobe.com/xap/1.0/'>
<xmp:CreateDate>2019-04-15T14:40:24</xmp:CreateDate>
<xmp:ModifyDate>2019-04-15T14:40:24</xmp:ModifyDate>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:exif='http://ns.adobe.com/exif/1.0/'>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>

View File

@@ -0,0 +1 @@
[{"EXIF:ImageDescription": "Girls with pumpkins", "XMP:Description": "Girls with pumpkins", "XMP:Title": "Can we carry this?", "IPTC:Keywords": ["Kids"], "XMP:Subject": ["Kids"], "XMP:TagsList": ["Kids"], "XMP:PersonInImage": ["Katie", "Suzy"], "EXIF:DateTimeOriginal": "2018:09:28 15:35:49", "EXIF:CreateDate": "2018:09:28 15:35:49", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2018:09:28", "IPTC:TimeCreated": "15:35:49-04:00", "EXIF:ModifyDate": "2018:09:28 15:35:49"}]

View File

@@ -0,0 +1,51 @@
<!-- Created with osxphotos https://github.com/RhetTbull/osxphotos -->
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 5.4.0">
<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:photoshop="http://ns.adobe.com/photoshop/1.0/">
<photoshop:SidecarForExtension>jpg</photoshop:SidecarForExtension>
<dc:description>
<rdf:Alt>
<rdf:li xml:lang='x-default'>Girls with pumpkins</rdf:li>
</rdf:Alt>
</dc:description>
<dc:title>
<rdf:Alt>
<rdf:li xml:lang='x-default'>Can we carry this?</rdf:li>
</rdf:Alt>
</dc:title>
<dc:subject>
<rdf:Bag>
<rdf:li>Kids</rdf:li>
</rdf:Bag>
</dc:subject>
<photoshop:DateCreated>2018-09-28T15:35:49.063000-04:00</photoshop:DateCreated>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:Iptc4xmpExt='http://iptc.org/std/Iptc4xmpExt/2008-02-29/'>
<Iptc4xmpExt:PersonInImage>
<rdf:Bag>
<rdf:li>Katie</rdf:li>
<rdf:li>Suzy</rdf:li>
</rdf:Bag>
</Iptc4xmpExt:PersonInImage>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:digiKam='http://www.digikam.org/ns/1.0/'>
<digiKam:TagsList>
<rdf:Seq>
<rdf:li>Kids</rdf:li>
</rdf:Seq>
</digiKam:TagsList>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:xmp='http://ns.adobe.com/xap/1.0/'>
<xmp:CreateDate>2018-09-28T15:35:49</xmp:CreateDate>
<xmp:ModifyDate>2018-09-28T15:35:49</xmp:ModifyDate>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:exif='http://ns.adobe.com/exif/1.0/'>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>

View File

@@ -0,0 +1 @@
[{"EXIF:ImageDescription": "Girls with pumpkins", "XMP:Description": "Girls with pumpkins", "XMP:Title": "Can we carry this?", "IPTC:Keywords": ["Kids", "Pumpkin Farm", "Test Album"], "XMP:Subject": ["Kids", "Pumpkin Farm", "Test Album"], "XMP:TagsList": ["Kids", "Pumpkin Farm", "Test Album"], "XMP:PersonInImage": ["Katie", "Suzy"], "EXIF:DateTimeOriginal": "2018:09:28 15:35:49", "EXIF:CreateDate": "2018:09:28 15:35:49", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2018:09:28", "IPTC:TimeCreated": "15:35:49-04:00", "EXIF:ModifyDate": "2018:09:28 15:35:49"}]

View File

@@ -0,0 +1,55 @@
<!-- Created with osxphotos https://github.com/RhetTbull/osxphotos -->
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 5.4.0">
<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:photoshop="http://ns.adobe.com/photoshop/1.0/">
<photoshop:SidecarForExtension>jpg</photoshop:SidecarForExtension>
<dc:description>
<rdf:Alt>
<rdf:li xml:lang='x-default'>Girls with pumpkins</rdf:li>
</rdf:Alt>
</dc:description>
<dc:title>
<rdf:Alt>
<rdf:li xml:lang='x-default'>Can we carry this?</rdf:li>
</rdf:Alt>
</dc:title>
<dc:subject>
<rdf:Bag>
<rdf:li>Kids</rdf:li>
<rdf:li>Pumpkin Farm</rdf:li>
<rdf:li>Test Album</rdf:li>
</rdf:Bag>
</dc:subject>
<photoshop:DateCreated>2018-09-28T15:35:49.063000-04:00</photoshop:DateCreated>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:Iptc4xmpExt='http://iptc.org/std/Iptc4xmpExt/2008-02-29/'>
<Iptc4xmpExt:PersonInImage>
<rdf:Bag>
<rdf:li>Katie</rdf:li>
<rdf:li>Suzy</rdf:li>
</rdf:Bag>
</Iptc4xmpExt:PersonInImage>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:digiKam='http://www.digikam.org/ns/1.0/'>
<digiKam:TagsList>
<rdf:Seq>
<rdf:li>Kids</rdf:li>
<rdf:li>Pumpkin Farm</rdf:li>
<rdf:li>Test Album</rdf:li>
</rdf:Seq>
</digiKam:TagsList>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:xmp='http://ns.adobe.com/xap/1.0/'>
<xmp:CreateDate>2018-09-28T15:35:49</xmp:CreateDate>
<xmp:ModifyDate>2018-09-28T15:35:49</xmp:ModifyDate>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:exif='http://ns.adobe.com/exif/1.0/'>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>

View File

@@ -0,0 +1,51 @@
<!-- Created with osxphotos https://github.com/RhetTbull/osxphotos -->
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 5.4.0">
<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:photoshop="http://ns.adobe.com/photoshop/1.0/">
<photoshop:SidecarForExtension>jpg</photoshop:SidecarForExtension>
<dc:description>
<rdf:Alt>
<rdf:li xml:lang='x-default'>Girls with pumpkins</rdf:li>
</rdf:Alt>
</dc:description>
<dc:title>
<rdf:Alt>
<rdf:li xml:lang='x-default'>Can we carry this?</rdf:li>
</rdf:Alt>
</dc:title>
<dc:subject>
<rdf:Bag>
<rdf:li>Kids</rdf:li>
</rdf:Bag>
</dc:subject>
<photoshop:DateCreated>2018-09-28T15:35:49.063000-04:00</photoshop:DateCreated>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:Iptc4xmpExt='http://iptc.org/std/Iptc4xmpExt/2008-02-29/'>
<Iptc4xmpExt:PersonInImage>
<rdf:Bag>
<rdf:li>Katie</rdf:li>
<rdf:li>Suzy</rdf:li>
</rdf:Bag>
</Iptc4xmpExt:PersonInImage>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:digiKam='http://www.digikam.org/ns/1.0/'>
<digiKam:TagsList>
<rdf:Seq>
<rdf:li>Kids</rdf:li>
</rdf:Seq>
</digiKam:TagsList>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:xmp='http://ns.adobe.com/xap/1.0/'>
<xmp:CreateDate>2018-09-28T15:35:49</xmp:CreateDate>
<xmp:ModifyDate>2018-09-28T15:35:49</xmp:ModifyDate>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:exif='http://ns.adobe.com/exif/1.0/'>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>

View File

@@ -0,0 +1 @@
[{"EXIF:ImageDescription": "Girls with pumpkins", "XMP:Description": "Girls with pumpkins", "XMP:Title": "Can we carry this?", "IPTC:Keywords": ["Kids"], "XMP:Subject": ["Kids"], "XMP:TagsList": ["Kids"], "XMP:PersonInImage": ["Katie", "Suzy"], "EXIF:DateTimeOriginal": "2018:09:28 15:35:49", "EXIF:CreateDate": "2018:09:28 15:35:49", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2018:09:28", "IPTC:TimeCreated": "15:35:49-04:00", "EXIF:ModifyDate": "2018:09:28 15:35:49"}]

View File

@@ -0,0 +1 @@
[{"EXIF:ImageDescription": "Girls with pumpkins", "XMP:Description": "Girls with pumpkins", "XMP:Title": "Can we carry this?", "IPTC:Keywords": ["Kids", "Pumpkin Farm", "Test Album"], "XMP:Subject": ["Kids", "Pumpkin Farm", "Test Album"], "XMP:TagsList": ["Kids", "Pumpkin Farm", "Test Album"], "XMP:PersonInImage": ["Katie", "Suzy"], "EXIF:DateTimeOriginal": "2018:09:28 15:35:49", "EXIF:CreateDate": "2018:09:28 15:35:49", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2018:09:28", "IPTC:TimeCreated": "15:35:49-04:00", "EXIF:ModifyDate": "2018:09:28 15:35:49"}]

View File

@@ -0,0 +1,57 @@
<!-- Created with osxphotos https://github.com/RhetTbull/osxphotos -->
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 5.4.0">
<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:photoshop="http://ns.adobe.com/photoshop/1.0/">
<photoshop:SidecarForExtension>jpg</photoshop:SidecarForExtension>
<dc:description>
<rdf:Alt>
<rdf:li xml:lang='x-default'>Girls with pumpkins</rdf:li>
</rdf:Alt>
</dc:description>
<dc:title>
<rdf:Alt>
<rdf:li xml:lang='x-default'>Can we carry this?</rdf:li>
</rdf:Alt>
</dc:title>
<dc:subject>
<rdf:Bag>
<rdf:li>2018</rdf:li>
<rdf:li>Kids</rdf:li>
<rdf:li>Pumpkin Farm</rdf:li>
<rdf:li>Test Album</rdf:li>
</rdf:Bag>
</dc:subject>
<photoshop:DateCreated>2018-09-28T15:35:49.063000-04:00</photoshop:DateCreated>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:Iptc4xmpExt='http://iptc.org/std/Iptc4xmpExt/2008-02-29/'>
<Iptc4xmpExt:PersonInImage>
<rdf:Bag>
<rdf:li>Katie</rdf:li>
<rdf:li>Suzy</rdf:li>
</rdf:Bag>
</Iptc4xmpExt:PersonInImage>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:digiKam='http://www.digikam.org/ns/1.0/'>
<digiKam:TagsList>
<rdf:Seq>
<rdf:li>2018</rdf:li>
<rdf:li>Kids</rdf:li>
<rdf:li>Pumpkin Farm</rdf:li>
<rdf:li>Test Album</rdf:li>
</rdf:Seq>
</digiKam:TagsList>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:xmp='http://ns.adobe.com/xap/1.0/'>
<xmp:CreateDate>2018-09-28T15:35:49</xmp:CreateDate>
<xmp:ModifyDate>2018-09-28T15:35:49</xmp:ModifyDate>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:exif='http://ns.adobe.com/exif/1.0/'>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>

View File

@@ -0,0 +1 @@
[{"ImageDescription": "Girls with pumpkins", "Description": "Girls with pumpkins", "Title": "Can we carry this?", "Keywords": ["Kids"], "Subject": ["Kids"], "TagsList": ["Kids"], "PersonInImage": ["Katie", "Suzy"], "DateTimeOriginal": "2018:09:28 15:35:49", "CreateDate": "2018:09:28 15:35:49", "OffsetTimeOriginal": "-04:00", "DateCreated": "2018:09:28", "TimeCreated": "15:35:49-04:00", "ModifyDate": "2018:09:28 15:35:49"}]

View File

@@ -0,0 +1 @@
[{"EXIF:ImageDescription": "Girls with pumpkins", "XMP:Description": "Girls with pumpkins", "XMP:Title": "Can we carry this?", "IPTC:Keywords": ["Katie", "Kids", "Suzy"], "XMP:Subject": ["Katie", "Kids", "Suzy"], "XMP:TagsList": ["Katie", "Kids", "Suzy"], "XMP:PersonInImage": ["Katie", "Suzy"], "EXIF:DateTimeOriginal": "2018:09:28 15:35:49", "EXIF:CreateDate": "2018:09:28 15:35:49", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2018:09:28", "IPTC:TimeCreated": "15:35:49-04:00", "EXIF:ModifyDate": "2018:09:28 15:35:49"}]

View File

@@ -0,0 +1,55 @@
<!-- Created with osxphotos https://github.com/RhetTbull/osxphotos -->
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 5.4.0">
<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:photoshop="http://ns.adobe.com/photoshop/1.0/">
<photoshop:SidecarForExtension>jpg</photoshop:SidecarForExtension>
<dc:description>
<rdf:Alt>
<rdf:li xml:lang='x-default'>Girls with pumpkins</rdf:li>
</rdf:Alt>
</dc:description>
<dc:title>
<rdf:Alt>
<rdf:li xml:lang='x-default'>Can we carry this?</rdf:li>
</rdf:Alt>
</dc:title>
<dc:subject>
<rdf:Bag>
<rdf:li>Katie</rdf:li>
<rdf:li>Kids</rdf:li>
<rdf:li>Suzy</rdf:li>
</rdf:Bag>
</dc:subject>
<photoshop:DateCreated>2018-09-28T15:35:49.063000-04:00</photoshop:DateCreated>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:Iptc4xmpExt='http://iptc.org/std/Iptc4xmpExt/2008-02-29/'>
<Iptc4xmpExt:PersonInImage>
<rdf:Bag>
<rdf:li>Katie</rdf:li>
<rdf:li>Suzy</rdf:li>
</rdf:Bag>
</Iptc4xmpExt:PersonInImage>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:digiKam='http://www.digikam.org/ns/1.0/'>
<digiKam:TagsList>
<rdf:Seq>
<rdf:li>Katie</rdf:li>
<rdf:li>Kids</rdf:li>
<rdf:li>Suzy</rdf:li>
</rdf:Seq>
</digiKam:TagsList>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:xmp='http://ns.adobe.com/xap/1.0/'>
<xmp:CreateDate>2018-09-28T15:35:49</xmp:CreateDate>
<xmp:ModifyDate>2018-09-28T15:35:49</xmp:ModifyDate>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:exif='http://ns.adobe.com/exif/1.0/'>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>

View File

@@ -0,0 +1 @@
[{"XMP:Title": "Pumpkin heads", "IPTC:Keywords": ["Kids"], "XMP:Subject": ["Kids"], "XMP:TagsList": ["Kids"], "EXIF:DateTimeOriginal": "2018:09:28 15:39:59", "EXIF:CreateDate": "2018:09:28 15:39:59", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2018:09:28", "IPTC:TimeCreated": "15:39:59-04:00", "EXIF:ModifyDate": "2018:09:28 15:39:59"}]

View File

@@ -0,0 +1,45 @@
<!-- Created with osxphotos https://github.com/RhetTbull/osxphotos -->
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 5.4.0">
<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:photoshop="http://ns.adobe.com/photoshop/1.0/">
<photoshop:SidecarForExtension>jpg</photoshop:SidecarForExtension>
<dc:description>
<rdf:Alt>
<rdf:li xml:lang='x-default'></rdf:li>
</rdf:Alt>
</dc:description>
<dc:title>
<rdf:Alt>
<rdf:li xml:lang='x-default'>Pumpkin heads</rdf:li>
</rdf:Alt>
</dc:title>
<dc:subject>
<rdf:Bag>
<rdf:li>Kids</rdf:li>
</rdf:Bag>
</dc:subject>
<photoshop:DateCreated>2018-09-28T15:39:59.008000-04:00</photoshop:DateCreated>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:Iptc4xmpExt='http://iptc.org/std/Iptc4xmpExt/2008-02-29/'>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:digiKam='http://www.digikam.org/ns/1.0/'>
<digiKam:TagsList>
<rdf:Seq>
<rdf:li>Kids</rdf:li>
</rdf:Seq>
</digiKam:TagsList>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:xmp='http://ns.adobe.com/xap/1.0/'>
<xmp:CreateDate>2018-09-28T15:39:59</xmp:CreateDate>
<xmp:ModifyDate>2018-09-28T15:39:59</xmp:ModifyDate>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:exif='http://ns.adobe.com/exif/1.0/'>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>

View File

@@ -0,0 +1 @@
[{"XMP:Title": "Pumpkin heads", "IPTC:Keywords": ["Kids"], "XMP:Subject": ["Kids"], "XMP:TagsList": ["Kids"], "EXIF:DateTimeOriginal": "2018:09:28 15:39:59", "EXIF:CreateDate": "2018:09:28 15:39:59", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2018:09:28", "IPTC:TimeCreated": "15:39:59-04:00", "EXIF:ModifyDate": "2018:09:28 15:39:59"}]

View File

@@ -0,0 +1,45 @@
<!-- Created with osxphotos https://github.com/RhetTbull/osxphotos -->
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 5.4.0">
<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:photoshop="http://ns.adobe.com/photoshop/1.0/">
<photoshop:SidecarForExtension>jpg</photoshop:SidecarForExtension>
<dc:description>
<rdf:Alt>
<rdf:li xml:lang='x-default'></rdf:li>
</rdf:Alt>
</dc:description>
<dc:title>
<rdf:Alt>
<rdf:li xml:lang='x-default'>Pumpkin heads</rdf:li>
</rdf:Alt>
</dc:title>
<dc:subject>
<rdf:Bag>
<rdf:li>Kids</rdf:li>
</rdf:Bag>
</dc:subject>
<photoshop:DateCreated>2018-09-28T15:39:59.008000-04:00</photoshop:DateCreated>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:Iptc4xmpExt='http://iptc.org/std/Iptc4xmpExt/2008-02-29/'>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:digiKam='http://www.digikam.org/ns/1.0/'>
<digiKam:TagsList>
<rdf:Seq>
<rdf:li>Kids</rdf:li>
</rdf:Seq>
</digiKam:TagsList>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:xmp='http://ns.adobe.com/xap/1.0/'>
<xmp:CreateDate>2018-09-28T15:39:59</xmp:CreateDate>
<xmp:ModifyDate>2018-09-28T15:39:59</xmp:ModifyDate>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:exif='http://ns.adobe.com/exif/1.0/'>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>

View File

@@ -0,0 +1,45 @@
<!-- Created with osxphotos https://github.com/RhetTbull/osxphotos -->
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 5.4.0">
<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:photoshop="http://ns.adobe.com/photoshop/1.0/">
<photoshop:SidecarForExtension>jpg</photoshop:SidecarForExtension>
<dc:description>
<rdf:Alt>
<rdf:li xml:lang='x-default'></rdf:li>
</rdf:Alt>
</dc:description>
<dc:title>
<rdf:Alt>
<rdf:li xml:lang='x-default'>Pumpkin heads</rdf:li>
</rdf:Alt>
</dc:title>
<dc:subject>
<rdf:Bag>
<rdf:li>Kids</rdf:li>
</rdf:Bag>
</dc:subject>
<photoshop:DateCreated>2018-09-28T15:39:59.008000-04:00</photoshop:DateCreated>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:Iptc4xmpExt='http://iptc.org/std/Iptc4xmpExt/2008-02-29/'>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:digiKam='http://www.digikam.org/ns/1.0/'>
<digiKam:TagsList>
<rdf:Seq>
<rdf:li>Kids</rdf:li>
</rdf:Seq>
</digiKam:TagsList>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:xmp='http://ns.adobe.com/xap/1.0/'>
<xmp:CreateDate>2018-09-28T15:39:59</xmp:CreateDate>
<xmp:ModifyDate>2018-09-28T15:39:59</xmp:ModifyDate>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:exif='http://ns.adobe.com/exif/1.0/'>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>

View File

@@ -0,0 +1 @@
[{"XMP:Title": "Pumpkin heads", "IPTC:Keywords": ["Kids"], "XMP:Subject": ["Kids"], "XMP:TagsList": ["Kids"], "EXIF:DateTimeOriginal": "2018:09:28 15:39:59", "EXIF:CreateDate": "2018:09:28 15:39:59", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2018:09:28", "IPTC:TimeCreated": "15:39:59-04:00", "EXIF:ModifyDate": "2018:09:28 15:39:59"}]

View File

@@ -0,0 +1 @@
[{"XMP:Title": "Pumpkin heads", "IPTC:Keywords": ["Kids"], "XMP:Subject": ["Kids"], "XMP:TagsList": ["Kids"], "EXIF:DateTimeOriginal": "2018:09:28 15:39:59", "EXIF:CreateDate": "2018:09:28 15:39:59", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2018:09:28", "IPTC:TimeCreated": "15:39:59-04:00", "EXIF:ModifyDate": "2018:09:28 15:39:59"}]

View File

@@ -0,0 +1,47 @@
<!-- Created with osxphotos https://github.com/RhetTbull/osxphotos -->
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 5.4.0">
<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:photoshop="http://ns.adobe.com/photoshop/1.0/">
<photoshop:SidecarForExtension>jpg</photoshop:SidecarForExtension>
<dc:description>
<rdf:Alt>
<rdf:li xml:lang='x-default'></rdf:li>
</rdf:Alt>
</dc:description>
<dc:title>
<rdf:Alt>
<rdf:li xml:lang='x-default'>Pumpkin heads</rdf:li>
</rdf:Alt>
</dc:title>
<dc:subject>
<rdf:Bag>
<rdf:li>2018</rdf:li>
<rdf:li>Kids</rdf:li>
</rdf:Bag>
</dc:subject>
<photoshop:DateCreated>2018-09-28T15:39:59.008000-04:00</photoshop:DateCreated>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:Iptc4xmpExt='http://iptc.org/std/Iptc4xmpExt/2008-02-29/'>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:digiKam='http://www.digikam.org/ns/1.0/'>
<digiKam:TagsList>
<rdf:Seq>
<rdf:li>2018</rdf:li>
<rdf:li>Kids</rdf:li>
</rdf:Seq>
</digiKam:TagsList>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:xmp='http://ns.adobe.com/xap/1.0/'>
<xmp:CreateDate>2018-09-28T15:39:59</xmp:CreateDate>
<xmp:ModifyDate>2018-09-28T15:39:59</xmp:ModifyDate>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:exif='http://ns.adobe.com/exif/1.0/'>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>

View File

@@ -0,0 +1 @@
[{"Title": "Pumpkin heads", "Keywords": ["Kids"], "Subject": ["Kids"], "TagsList": ["Kids"], "DateTimeOriginal": "2018:09:28 15:39:59", "CreateDate": "2018:09:28 15:39:59", "OffsetTimeOriginal": "-04:00", "DateCreated": "2018:09:28", "TimeCreated": "15:39:59-04:00", "ModifyDate": "2018:09:28 15:39:59"}]

View File

@@ -0,0 +1 @@
[{"XMP:Title": "Pumpkin heads", "IPTC:Keywords": ["Kids"], "XMP:Subject": ["Kids"], "XMP:TagsList": ["Kids"], "EXIF:DateTimeOriginal": "2018:09:28 15:39:59", "EXIF:CreateDate": "2018:09:28 15:39:59", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2018:09:28", "IPTC:TimeCreated": "15:39:59-04:00", "EXIF:ModifyDate": "2018:09:28 15:39:59"}]

View File

@@ -0,0 +1,45 @@
<!-- Created with osxphotos https://github.com/RhetTbull/osxphotos -->
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 5.4.0">
<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:photoshop="http://ns.adobe.com/photoshop/1.0/">
<photoshop:SidecarForExtension>jpg</photoshop:SidecarForExtension>
<dc:description>
<rdf:Alt>
<rdf:li xml:lang='x-default'></rdf:li>
</rdf:Alt>
</dc:description>
<dc:title>
<rdf:Alt>
<rdf:li xml:lang='x-default'>Pumpkin heads</rdf:li>
</rdf:Alt>
</dc:title>
<dc:subject>
<rdf:Bag>
<rdf:li>Kids</rdf:li>
</rdf:Bag>
</dc:subject>
<photoshop:DateCreated>2018-09-28T15:39:59.008000-04:00</photoshop:DateCreated>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:Iptc4xmpExt='http://iptc.org/std/Iptc4xmpExt/2008-02-29/'>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:digiKam='http://www.digikam.org/ns/1.0/'>
<digiKam:TagsList>
<rdf:Seq>
<rdf:li>Kids</rdf:li>
</rdf:Seq>
</digiKam:TagsList>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:xmp='http://ns.adobe.com/xap/1.0/'>
<xmp:CreateDate>2018-09-28T15:39:59</xmp:CreateDate>
<xmp:ModifyDate>2018-09-28T15:39:59</xmp:ModifyDate>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:exif='http://ns.adobe.com/exif/1.0/'>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>

View File

@@ -0,0 +1 @@
[{"EXIF:ImageDescription": "Girl holding pumpkin", "XMP:Description": "Girl holding pumpkin", "XMP:Title": "I found one!", "IPTC:Keywords": ["Kids"], "XMP:Subject": ["Kids"], "XMP:TagsList": ["Kids"], "XMP:PersonInImage": ["Katie"], "EXIF:GPSLatitude": 41.256566, "EXIF:GPSLongitude": -95.940257, "EXIF:GPSLatitudeRef": "N", "EXIF:GPSLongitudeRef": "W", "EXIF:DateTimeOriginal": "2018:09:28 16:07:07", "EXIF:CreateDate": "2018:09:28 16:07:07", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2018:09:28", "IPTC:TimeCreated": "16:07:07-04:00", "EXIF:ModifyDate": "2018:09:28 16:07:07"}]

View File

@@ -0,0 +1,52 @@
<!-- Created with osxphotos https://github.com/RhetTbull/osxphotos -->
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 5.4.0">
<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:photoshop="http://ns.adobe.com/photoshop/1.0/">
<photoshop:SidecarForExtension>jpg</photoshop:SidecarForExtension>
<dc:description>
<rdf:Alt>
<rdf:li xml:lang='x-default'>Girl holding pumpkin</rdf:li>
</rdf:Alt>
</dc:description>
<dc:title>
<rdf:Alt>
<rdf:li xml:lang='x-default'>I found one!</rdf:li>
</rdf:Alt>
</dc:title>
<dc:subject>
<rdf:Bag>
<rdf:li>Kids</rdf:li>
</rdf:Bag>
</dc:subject>
<photoshop:DateCreated>2018-09-28T16:07:07-04:00</photoshop:DateCreated>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:Iptc4xmpExt='http://iptc.org/std/Iptc4xmpExt/2008-02-29/'>
<Iptc4xmpExt:PersonInImage>
<rdf:Bag>
<rdf:li>Katie</rdf:li>
</rdf:Bag>
</Iptc4xmpExt:PersonInImage>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:digiKam='http://www.digikam.org/ns/1.0/'>
<digiKam:TagsList>
<rdf:Seq>
<rdf:li>Kids</rdf:li>
</rdf:Seq>
</digiKam:TagsList>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:xmp='http://ns.adobe.com/xap/1.0/'>
<xmp:CreateDate>2018-09-28T16:07:07</xmp:CreateDate>
<xmp:ModifyDate>2018-09-28T16:07:07</xmp:ModifyDate>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:exif='http://ns.adobe.com/exif/1.0/'>
<exif:GPSLongitude>95,56.415420000000154W</exif:GPSLongitude>
<exif:GPSLatitude>41,15.393959999999964N</exif:GPSLatitude>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>

View File

@@ -0,0 +1 @@
[{"EXIF:ImageDescription": "Girl holding pumpkin", "XMP:Description": "Girl holding pumpkin", "XMP:Title": "I found one!", "IPTC:Keywords": ["Kids", "Pumpkin Farm", "Test Album"], "XMP:Subject": ["Kids", "Pumpkin Farm", "Test Album"], "XMP:TagsList": ["Kids", "Pumpkin Farm", "Test Album"], "XMP:PersonInImage": ["Katie"], "EXIF:GPSLatitude": 41.256566, "EXIF:GPSLongitude": -95.940257, "EXIF:GPSLatitudeRef": "N", "EXIF:GPSLongitudeRef": "W", "EXIF:DateTimeOriginal": "2018:09:28 16:07:07", "EXIF:CreateDate": "2018:09:28 16:07:07", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2018:09:28", "IPTC:TimeCreated": "16:07:07-04:00", "EXIF:ModifyDate": "2018:09:28 16:07:07"}]

View File

@@ -0,0 +1,56 @@
<!-- Created with osxphotos https://github.com/RhetTbull/osxphotos -->
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 5.4.0">
<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:photoshop="http://ns.adobe.com/photoshop/1.0/">
<photoshop:SidecarForExtension>jpg</photoshop:SidecarForExtension>
<dc:description>
<rdf:Alt>
<rdf:li xml:lang='x-default'>Girl holding pumpkin</rdf:li>
</rdf:Alt>
</dc:description>
<dc:title>
<rdf:Alt>
<rdf:li xml:lang='x-default'>I found one!</rdf:li>
</rdf:Alt>
</dc:title>
<dc:subject>
<rdf:Bag>
<rdf:li>Kids</rdf:li>
<rdf:li>Pumpkin Farm</rdf:li>
<rdf:li>Test Album</rdf:li>
</rdf:Bag>
</dc:subject>
<photoshop:DateCreated>2018-09-28T16:07:07-04:00</photoshop:DateCreated>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:Iptc4xmpExt='http://iptc.org/std/Iptc4xmpExt/2008-02-29/'>
<Iptc4xmpExt:PersonInImage>
<rdf:Bag>
<rdf:li>Katie</rdf:li>
</rdf:Bag>
</Iptc4xmpExt:PersonInImage>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:digiKam='http://www.digikam.org/ns/1.0/'>
<digiKam:TagsList>
<rdf:Seq>
<rdf:li>Kids</rdf:li>
<rdf:li>Pumpkin Farm</rdf:li>
<rdf:li>Test Album</rdf:li>
</rdf:Seq>
</digiKam:TagsList>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:xmp='http://ns.adobe.com/xap/1.0/'>
<xmp:CreateDate>2018-09-28T16:07:07</xmp:CreateDate>
<xmp:ModifyDate>2018-09-28T16:07:07</xmp:ModifyDate>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:exif='http://ns.adobe.com/exif/1.0/'>
<exif:GPSLongitude>95,56.415420000000154W</exif:GPSLongitude>
<exif:GPSLatitude>41,15.393959999999964N</exif:GPSLatitude>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>

Some files were not shown because too many files have changed in this diff Show More