Compare commits

...

2 Commits

Author SHA1 Message Date
Jean-Claude 5a6f29d957
Update to latest interface version 2023-06-24 16:22:57 +02:00
Jean-Claude a3f33e86c2
Refactor for vimiv metadata changes 2023-02-19 12:46:09 +01:00
1 changed files with 61 additions and 36 deletions

View File

@ -1,18 +1,18 @@
# vim: ft=python fileencoding=utf-8 sw=4 et sts=4
"""Utility functions and classes for exif handling.
"""Metadata plugin based on gexiv2 (https://wiki.gnome.org/Projects/gexiv2) backend.
All exif related tasks are implemented in this module. The heavy lifting is done using
one of the supported exif libraries, i.e.
* piexif (https://pypi.org/project/piexif/) and
* pyexiv2 (https://pypi.org/project/py3exiv2/).
Properties:
- Gnome dependencies.
- Formatted Metadata.
- Reads Exif, IPTC and XMP.
"""
import contextlib
from typing import Any, Sequence, Iterable
from vimiv.imutils import exif
from vimiv.utils import log, lazy, is_hex
from vimiv.imutils import metadata
from vimiv.utils import log, is_hex
import gi
@ -22,58 +22,83 @@ from gi.repository import GExiv2 as gexiv2
_logger = log.module_logger(__name__)
class ExifHandlerGexiv(exif._ExifHandlerBase):
"""Main ExifHandler implementation based on gexiv2."""
class MetadataGexiv2(metadata.MetadataPlugin):
"""Provides metadata support based on gexiv2.
MESSAGE_SUFFIX = " by gexiv2."
Implements `get_metadata`, `get_keys`, `copy_metadata`, and `get_date_time`.
"""
def __init__(self, path: str) -> None:
self._path = path
def __init__(self, filename=""):
super().__init__(filename)
try:
self._metadata = gexiv2.Metadata(filename)
self._metadata = gexiv2.Metadata(path)
except gi.repository.GLib.GError:
_logger.debug("File %s not found", filename)
_logger.debug("File %s not found", path)
self._metadata = None
def get_formatted_exif(self, desired_keys: Sequence[str]) -> exif.ExifDictT:
exif = {}
@staticmethod
def name() -> str:
"""Get the name of the used backend."""
return "gexiv2"
for base_key in desired_keys:
# For backwards compability, assume it has one of the following prefixes
for prefix in ["", "Exif.Image.", "Exif.Photo."]:
key = f"{prefix}{base_key}"
try:
exif[key] = (
self._metadata.try_get_tag_label(key),
self._metadata.try_get_tag_interpreted_string(key),
)
break
@staticmethod
def version() -> str:
"""Get the version of the used backend."""
return "0.10"
except gi.repository.GLib.GError:
_logger.debug("Key %s is invalid for the current image", key)
def get_metadata(self, desired_keys: Sequence[str]) -> metadata.MetadataDictT:
"""Get value of all desired keys for the current image."""
out = {}
return exif
if self._metadata is None:
return {}
for key in desired_keys:
try:
out[key] = (
self._metadata.try_get_tag_label(key),
self._metadata.try_get_tag_interpreted_string(key),
)
except gi.repository.GLib.GError:
_logger.debug("Key %s is invalid for the current image", key)
return out
def get_keys(self) -> Iterable[str]:
"""Get the keys for all metadata values available for the current image."""
if self._metadata is None:
return iter([])
return (key for key in self._metadata if not is_hex(key.rpartition(".")[2]))
def copy_exif(self, dest: str, reset_orientation: bool = True) -> None:
def copy_metadata(self, dest: str, reset_orientation: bool = True) -> bool:
"""Copy metadata from the current image to dest image."""
if self._metadata is None:
return False
if reset_orientation:
with contextlib.suppress(KeyError):
self._metadata.set_orientation(exif.ExifOrientation.Normal)
self._metadata.set_orientation(metadata.ExifOrientation.Normal)
try:
self._metadata.save_file(dest)
_logger.debug("Successfully wrote exif data for '%s'", dest)
return True
# TODO error handling
except gi.repository.GLib.GError as e:
_logger.debug("Failed to write exif data for '%s': '%s'", dest, str(e))
_logger.debug("Failed to write metadata for '%s': '%s'", dest, str(e))
return False
def get_date_time(self) -> str:
"""Get creation date and time of the current image as formatted string."""
if self._metadata is None:
return ""
def exif_date_time(self) -> str:
with contextlib.suppress(gi.repository.GLib.GError):
return self._metadata.get_tag_raw("Exif.Image.DateTime")
return ""
def init(*_args: Any, **_kwargs: Any) -> None:
exif.set_handler(ExifHandlerGexiv)
metadata.register(MetadataGexiv2)