Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Internal metadata keys #325

Open
wants to merge 21 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,15 @@ Added:
* The ``:copy-image`` command which copies the selected image to the clipboard. The
flags ``--width``, ``--height`` and ``--size`` allow to scale the copied image.
Thanks `@jcjgraf`_!
* Series of internal metadata keys. They are aimed to provide additional metadata
information which is not provided by the external metadata libraries. All these keys
start with a leading ``Vimiv``:

* ``Vimiv.FileSize`` File size
* ``Vimiv.FileType`` File type
* ``Vimiv.XDimension`` X dimension in pixel
* ``Vimiv.YDimension`` Y dimension in pixel


Changed:
^^^^^^^^
Expand All @@ -53,6 +62,7 @@ Fixed:
* Expanding tilde to home directory when using the ``:write`` command. Thanks
`@jcjgraf`_ for pointing this out!
* Completion for aliases.
* Crash when extracting metadata using piexif from a non JPEG or TIFF image. Thanks `@BachoSeven`_ for pointing this out!


v0.8.0 (2021-01-18)
Expand Down
65 changes: 0 additions & 65 deletions docs/documentation/exif.rst

This file was deleted.

2 changes: 1 addition & 1 deletion docs/documentation/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ The following documents are available:
getting_started
commands
configuration/index
exif
metadata
contributing
migrating

Expand Down
91 changes: 91 additions & 0 deletions docs/documentation/metadata.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
Metadata
========

Vimiv provides optional metadata support if either `pyexiv2`_ or `piexif`_ is
available. If this is the case:

#. The ``:metadata`` command and the corresponding ``i``-keybinding is available.
#. Image metadata is automatically copied from source to destination when writing images
to disk.
#. The ``{exif-date-time}`` statusbar module is available.

.. include:: pyexiv2.rst

Advantages of the different metadata libraries
----------------------------------------------

In short, `pyexiv2`_ is much more powerful than `piexif`_, though also more involved to
install.

.. table:: Comparison of the two libraries
:widths: 20 15 20 45

======================= ============== ==================== =====================================================================
PROPERTY `piexif`_ `pyexiv2`_ Note
======================= ============== ==================== =====================================================================
Exif Support True True pyexiv2 can extract way more data for the same image
ICMP Support False True
XMP Suppport False True
Output Formatting False True e.g. ``FNumber: 63/10`` vs ``FNumber: F6.3``
Supported File Types JPEG, TIFF All common types
Ease of installation Simple More complicated pyexiv2 requires some dependencies including the C++ library `exiv2`_
======================= ============== ==================== =====================================================================


We recommend to use `pyexiv2`_ if the installation is not too involved on your system
and `piexif`_ as a fallback solution or in case you don't need the full power of
`pyexiv2`_ and prefer something more lightweight.


Moving from piexif to pyexiv2
-----------------------------

As `pyexiv2`_ is the more powerful option compared to `piexif`_, vimiv will prefer
`pyexiv2`_ over `piexif`_. Therefore, to switch to `pyexiv2`_ simply install it on your
system and vimiv will use it automatically. If you have defined custom metadata sets in
your config, you may have to adjust them to use the full path to any key. See the next
section for more information on this.


Customizing metadata keysets
----------------------------

You can configure the information displayed by the ``:metadata`` command by adding your
own key sets to the ``METADATA`` section in your configfile like this::

keys2 = Override,Second,Set
keys4 = New,Fourth,Set

where the values must be a comma-separated list of valid metadata keys.

In case you are using `pyexiv2`_ you can find an overview of valid Exif, IPTC and XMP
keys on the `exiv2 webpage <https://www.exiv2.org/metadata.html>`_. It is considered
best-practice to use the full path to any key, e.g. ``Exif.Image.FocalLength``, but for convenience the short version of the key, e.g. ``FocalLength``, also works for the keys
in ``Exif.Image`` or ``Exif.Photo``.

`Piexif`_ unfortunately always uses the short form of the key, i.e. everything that
comes after the last ``.`` character. In case you pass the full path, vimiv will remove
everything up to and including the last ``.`` character and match only the short form.

On top of the library specific keys, vimiv also provides a series of additional
metadata keys. They can be treated completely equivalently to the library keys.

.. table:: Complete list of internal metadata keys
:widths: 20 80

======================= =================================
Key Description
======================= =================================
``Vimiv.FileSize`` File size
``Vimiv.FileType`` File type
``Vimiv.XDimension`` X dimension in pixel
``Vimiv.YDimension`` Y dimension in pixel
======================= =================================

You can get a list of valid metadata keys for the current image using the
``:metadata-list-keys`` command.


.. _exiv2: https://www.exiv2.org/index.html
.. _pyexiv2: https://python3-exiv2.readthedocs.io
.. _piexif: https://pypi.org/project/piexif/
41 changes: 30 additions & 11 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

import pytest

from vimiv.imutils import exif
from vimiv.imutils import metadata


CI = "CI" in os.environ
Expand All @@ -24,10 +24,10 @@
)

EXIF_MARKERS = (
("exif", exif.has_exif_support, "Only run with exif support"),
("noexif", not exif.has_exif_support, "Only run without exif support"),
("pyexiv2", exif.pyexiv2 is not None, "Only run with pyexiv2"),
("piexif", exif.piexif is not None, "Only run with piexif"),
("exif", metadata.has_metadata_support, "Only run with exif support"),
("noexif", not metadata.has_metadata_support, "Only run without exif support"),
("pyexiv2", metadata.pyexiv2 is not None, "Only run with pyexiv2"),
("piexif", metadata.piexif is not None, "Only run with piexif"),
)
# fmt: on

Expand All @@ -39,7 +39,7 @@ def apply_platform_markers(item):

def apply_exif_markers(item):
"""Apply markers that skip tests depending on specific exif support."""
if os.path.basename(item.fspath) in ("test_exif.py",):
if os.path.basename(item.fspath) in ("test_metadata.py",):
for marker_name in "exif", "pyexiv2", "piexif":
marker = getattr(pytest.mark, marker_name)
item.add_marker(marker)
Expand Down Expand Up @@ -168,25 +168,44 @@ def tmpdir():
@pytest.fixture()
def piexif(monkeypatch):
"""Pytest fixture to ensure only piexif is available."""
monkeypatch.setattr(exif, "pyexiv2", None)
monkeypatch.setattr(metadata, "pyexiv2", None)


@pytest.fixture()
def noexif(monkeypatch, piexif):
"""Pytest fixture to ensure no exif library is available."""
monkeypatch.setattr(exif, "piexif", None)
monkeypatch.setattr(metadata, "piexif", None)


@pytest.fixture()
def add_exif_information():
"""Fixture to retrieve a helper function that adds exif content to an image."""

def add_exif_information_impl(path: str, content):
assert exif.piexif is not None, "piexif required to add exif information"
exif_dict = exif.piexif.load(path)
assert metadata.piexif is not None, "piexif required to add exif information"
exif_dict = metadata.piexif.load(path)
for ifd, ifd_dict in content.items():
for key, value in ifd_dict.items():
exif_dict[ifd][key] = value
exif.piexif.insert(exif.piexif.dump(exif_dict), path)
metadata.piexif.insert(metadata.piexif.dump(exif_dict), path)

return add_exif_information_impl


@pytest.fixture()
def add_metadata_information():
"""Fixture to retrieve a helper function that adds metadata content to an image."""

def add_metadata_information_impl(path: str, content):
assert (
metadata.pyexiv2 is not None
), "pyexiv2 required to add metadata information"
_metadata = metadata.pyexiv2.ImageMetadata(path)
_metadata.read()

for tag in content.values():
_metadata[tag.key] = tag.value

_metadata.write()

return add_metadata_information_impl
61 changes: 0 additions & 61 deletions tests/unit/imutils/test_exif.py

This file was deleted.

Loading