exifdata


Nameexifdata JSON
Version 0.5.7 PyPI version JSON
download
home_pageNone
SummaryStreamlined EXIF, IPTC and XMP image metadata creation and parsing.
upload_time2025-08-23 19:50:47
maintainerNone
docs_urlNone
authorDaniel Sissman
requires_python>=3.10
licenseNone
keywords image metadata embedded exif iptc xmp
VCS
bugtrack_url
requirements enumerific caselessly deliciousbytes maxml tiffdata
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # EXIFData

The EXIFData library for Python provides a simplified and consistent way to work with
embedded image metadata in the EXIF, IPTC and XMP formats. The library can be used to
parse and create metadata in these formats which can be read from or embedded into image
files such as TIFF and JPEG images.

The EXIFData library provides support for parsing and creating raw metadata payloads of
these formats while delegating responsibility to PyVIPS to perform the extraction of and
embedding of the raw metadata payloads. Future versions of the library may offer support
for reading and writing a number of image file formats directly.

### Requirements

The EXIFData library has been tested to work with Python 3.10, 3.11, 3.12 and 3.13, but
has not been tested, nor is its use supported with earlier versions of Python.

### Installation

The library is available from the PyPI repository, so may be added easily to a project's
dependencies via its `requirements.txt` file or similar by referencing the library's
name, `exifdata`, or the library may be installed directly onto your local development
system using `pip install` by entering the following command:

	$ pip install exifdata

If you would like to install the optional `pyvips` dependency with the library, use:

	$ pip install "exifdata[pyvips]"

PyVIPS is needed if you wish to use open images from disk or to work with in-memory
images opened previously by PyVIPS. If you do not already have PyVIPS installed, it is
best to install it along with the library to ensure all functionality is available.

### Conceptual Model

The EXIFData library provides access to each of the supported metadata models as a class
that offers a number of namespaces, with each namespace offering the full selection of
metadata fields provided by that namespace.

The structure of the models is as follows, where each model offers several namespaces,
and each namespace offers many fields, that each provide access to one or more values
depending on the field, its data type, and its semantics:

```
                                            ┌─────────┐        ┌─────────┐
                                      ┌────▶│  Field  ├───────▶│  Value  │
                                      │     └─────────┘        └─────────┘
                    ┌─────────────┐   │     ┌─────────┐        ┌─────────┐
               ┌───▶│  Namespace  ├───┴────▶│  Field  ├───────▶│  Value  │
               │    └─────────────┘         └─────────┘        └─────────┘
┌─────────┐    │    ┌─────────────┐         ┌─────────┐        ┌─────────┐
│  Model  │────┼───▶│  Namespace  │────────▶│  Field  ├───────▶│  Value  │
└─────────┘    │    └─────────────┘         └─────────┘        └─────────┘
               │    ┌─────────────┐         ┌─────────┐        ┌─────────┐
               └───▶│  Namespace  │────┬───▶│  Field  ├───────▶│  Value  │
                    └─────────────┘    │    └─────────┘        └─────────┘
                                       │    ┌─────────┐        ┌─────────┐
                                       └───▶│  Field  ├───────▶│  Value  │
                                            └─────────┘        └─────────┘
```

For example, the `IPTC` model offers several namespaces including the `envelope`, and
`application`, namespaces, while the `XMP` model offers many namespaces of its own
including `basic`, `photoshop`, and `dc`. These namespaces then provide access to the
metadata fields for reading and writing.

To assign a value to the XMP metadata model's `dc.title` field for example, one would
either access an existing instance of the `XMP` model class, or create one, and would
then reference and assign a value to the `title` field held within the `dc` namespace
as follows:

<!--pytest.mark.skip-->

```python
xmp.dc.title = "this is a title"
```

In order to read a value from a field, one would just reference the field like any other
property, and if the field has an assigned value that can be decoded, its value will be
available as an instance of the library's `Value` class.

The `Value` class and its subclasses exist to support encoding and decoding of the raw
value types defined by each of the metadata standards.

<!--pytest.mark.skip-->

```python
print(xmp.dc.title)
```

Furthermore, where possible, the `Value` class types themselves subclass native Python
types including `str`, `int`, `float`, and `datetime`, so these `Value` class instances
can be used interchangeably like the corresponding native type would be used; however by
necessity some of the `Value` subclasses represent structured data types and provide
additional fields or methods to access and assign the nested values, so must be used
directly where the field requires it.

Each metadata model's supported namespaces and fields are documented with information
about the relevant value types, which detail how to access and assign values to each of
the supported fields.

The following table lists the currently supported metadata models along with links to
documentation, detailing each model's available namespaces and fields:

| Metadata Model | Documentation                                              |
|----------------|------------------------------------------------------------|
| EXIF           | [EXIF Namespaces & Fields](./documentation/models/exif.md) |
| IPTC           | [IPTC Namespaces & Fields](./documentation/models/iptc.md) |
| XMP            | [XMP Namespaces & Fields](./documentation/models/xmp.md)   |

The EXIFData library also offers some convenience methods to make it easy to read and
write the supported embedded metadata in supported image file formats; currently the
library relies on the PyVIPS library to read and write the image files, and perform the
extraction and insertion of the raw metadata payloads, before handing off responsibility
to the EXIFData library to decode and encode the raw metadata payloads and their nested
namespaces, fields and values.

See the [Classes & Methods](#classes-and-methods) section below for more information on
the available interfaces and their use; and see the [Supported File Formats](#file-formats)
section for more information on the image file formats that are currently supported by
the library, which includes JPEG, TIFF and Pyramidal TIFF images.

### Example Use: Reading Metadata

The code sample below illustrates the use of the EXIFData library to read metadata:

<!--pytest.mark.skip-->

```python
import exifdata

# Open an image file from disk and attempt to parse its embedded metadata
models = exifdata.Models.open("/path/to/image-file.jpg")

# Print out the existing metadata model assigned fields and values
for model in models:
    print(model.name)
    for field, value in model.items(all=False):
        print(" -> %s => %s" % (field, value))
```

### Example Use: Writing Metadata

The code sample below illustrates the use of the EXIFData library to write metadata:

<!--pytest.mark.skip-->

```python
import exifdata

models = exifdata.Models.open("/path/to/image-file.jpg")

models.xmp.basic.title = "test title"
models.iptc.credit = "test credit"

# Save the image back to disk
models.save()
```

### Example Use: Reading and Writing Metadata with an existing PyVIPS Image

<!--pytest.mark.skip-->

```python
import exifdata
import pyvips

# Open the desired image file using PyVIPS
image = pyvips.Image.new_from_file("/path/to/image-file.tiff")

# Attempt to decode the metadata models from the provided image using EXIFData
models = exifdata.Models.load(image)

# Print out the existing metadata model assigned fields and values
for model in models:
    print(model.name)
    for field, value in model.items(all=False):
        print(" -> %s => %s" % (field, value))

# Set or update the desired metadata fields
models.xmp.basic.title = "test title"
models.iptc.credit = "test credit"

# Encode the updated metadata and embed it into the in-memory image buffer
models.encode()

# Save the image back to disk or capture the image into a buffer as needed
image.tiffsave()
```

⚠️ **Note:** When working directly with a PyVIPS image held in an `Image` class instance
one must remember to save the image or otherwise do something with the updated in-memory
image buffer as the call to the `models.encode()` method only encodes and embeds the
metadata into the in-memory image buffer. While the in-memory image buffer will then
contain the metadata, if one needs to save the image back to disk, that must be handled
as a separate call to PyVIPS.

<a id="classes-and-methods"></a>
### Classes & Methods

#### Models Class Methods & Properties

The `Models` class offers the following methods:

* `adapt(adapter: Adapter)` – The `adapt()` method provides support for associating the
specified `Adapter` class type with the `Models` class to allow the specified adapter to
be used to assist in reading and writing image files.

* `load(filepath: str)` – The `load()` method provides support for loading the specified
image file from the `filepath` which must exist and reference an image in a usable image
file format. If the referenced image file does not exist or cannot be loaded an error is
reported.

* `associate(image: object)` – The `associate()` method provides support for associating
the specified in-memory image with the `Models` class instance, which sets the reference
to the image without attempting to extract or decode any of the pre-existing metadata in
the image.

* `open(image: object)` – The `open()` method provides support for associating the
specified in-memory image with the `Models` class instance, which sets the reference to
the image and then proceeds to attempt extracting and decoding any pre-existing metadata
in the image.

* `update(model: Metadata)` – The `update()` method provides support for updating the
metadata models held by the `Models` class instance with new `Metadata` model subclass
instances if needed; if a matching `Metadata` model subclass has already been registered
with the `Models` class then it will be replaced by the provided `Metadata` instance and
if no match is found then the the provided `Metadata` instance will be registered.

* `assign(name: str, value: object)` – The `assign()` method provides support to assign
metadata model values to any of the supported metadata models via the metadata field's
fully qualified name, along with a supported value. If the provided name can be matched
with a name associated with one or more metadata model fields, and if the provided value
is valid, then the value will be assigned to the matching metadata model fields. This
offers an alternative method to setting metadata model field values via the property
accessor pattern.

* `erase(payloads: list[str] = None)` – The `erase()` method provides support for erasing
erasable metadata held in the associated image from either the specified payloads if one
or more supported payload names are specified, or from all of the metadata payloads if
no payloads are specified. The payloads and/or their embedded fields that are removed
from an image are dependent on the metadata payload as some fields are mandatory so they
cannot be removed, such as many of the fields in the EXIF payload. 

* `decode(order: ByteOrder)` – The `decode()` method provides support for decoding the
embedded metadata payloads contained in the associated image file, and if metadata is
found within the image and can be successfully decoded, the relevant metadata model
field values will be populated with the decoded values. The values can then be read and
otherwise used, and if desired, the values can be modified or cleared, before saving the
updated metadata back to the associated image.

* `encode(order: ByteOrder)` – The `encode()` method provides support for encoding the
assigned metadata model field values into encoded metadata payloads suitable for storing
into the associated image file.

The `Models` class offers the following properties:

* `adapter` (`Adapter`) – The `adapter` property provides access to the reference to the
current `Adapter` class instance associated with the `Models` class. The `Adapter` class
is used by the `Models` class to interact with image data and raw metadata via various
libraries such as PyVIPS, EXIFTool and TIFFData.

* `model` (`Metadata`) - The `model` property provides support for assigning one or more
`Metadata` model class instances to the `Models` class. The property can only be used to
assign `Metadata` model class instances to the `Models` class, it cannot be used to get
any of the assigned `Metadata` model class instances; instead this can be achieved by
iterating over the `Models` class instance as the `Models` class supports the iterator
protocol to provide access to the assigned `Metadata` model class instances using the
standard `for ... in ...` pattern.

* `exif` (`EXIF`) – The `exif` property provides support for accessing the `EXIF` model
instance associated with the `Models` class, which can then be used to access any of the
decoded metadata model field values or to assign or clear metadata model field values
associated with the EXIF metadata model.

* `iptc` (`IPTC`) – The `iptc` property provides support for accessing the `IPTC` model
instance associated with the `Models` class, which can then be used to access any of the
decoded metadata model field values or to assign or clear metadata model field values
associated with the IPTC metadata model.

* `xmp` (`XMP`) – The `xmp` property provides support for accessing the `XMP` model
instance associated with the `Models` class, which can then be used to access any of the
decoded metadata model field values or to assign or clear metadata model field values
associated with the XMP metadata model.

#### Metadata

The `Metadata` class provides the following methods:

* `register_type(type: Type, klass: Value)` – The `register_type()` method is used by
the EXIFData library internally to register `Value` subclass types for field types, as
defined by their `Type` enumeration class option values. The `Value` subclasses provide
support for encoding and decoding metadata model field values according to the needs of
the specific metadata model. The method should not be used directly unless developing an
update for the EXIFData library.

* `register_types(*types: tuple[type])` – The `register_types()` method is used by the
EXIFData library internally to register multiple `Value` subclass types for field types.
The `Value` subclasses provide support for encoding and decoding metadata model field
values according to the needs of the specific metadata model. The method should not be
used directly unless developing an update for the EXIFData library.

* `type_by_name(name: str)` (`Value` | `None`) – The `type_by_name()` method provides
support for accessing a registered `Value` type subclass by its name. This method is
used internally by the library and likely does not need to be used directly unless
developing an update for the EXIFData library.

* `field_by_id(id: str)` (`Field` | `None`) – The `field_by_id()` provides support for
looking up a  field by its identifier. If a match can be found the matching `Field` will
be returned, otherwise the method will return `None`.

* `field_by_name(name: str)` (`Field` | `None`) – The `field_by_name()` provides support
for looking up a  field by its name. If a match can be found the matching `Field` will
be returned, otherwise the method will return `None`.

* `field_by_property(property: str, value: object)` (`Field` | `None`) – The
`field_by_property()` method provides support for looking up a field by one of its named
properties where a match is sought for the specified value. If a match can be found the
matching `Field` will be returned, otherwise the method will return `None`.

* `get(name: str, default: object = None)` – The `get()` method provides support for
obtaining the value set for the named metadata model class field, if a value has
previously been assigned. If no value was previously assigned the method will return the
default value if one has been assigned or `None`.

* `set(value: Value, name: str = None, field: Field = None, namespace: Namespace = None)`
– The `set()` method provides support for setting a value on the metadata model class.
If the provided value held in a `Value` subclass instance has its own reference to a
`Field` class instance, the field name can be determined from the `Field` and does not
need to be specified directly, otherwise the `name` argument can optionally be specified
to provide the field name. If a `Namespace` class instance is optionally specified via
the `namespace` argument, then the field value will be stored within that namespace; if
a namespace is not specified directly, but a `Field` class instance is referenced by the
value, then the namespace can be determined from the `Field` class instance.

* `items(all: bool = False)` (`Generator`) – The `items()` method provides support for
iterating over the metadata model's fields and associated values. The generator yields
`tuple` values that hold a `Field` class instance and its corresponding `Value` class
instance for all the metadata model fields that have assigned values. If the `all` flag
is set to `True` the method will yield a `tuple` holding a `Field` class instance and a
`Value` class instance for every registered field in the metadata model, even if some of
the fields do not have assigned values. The returned `Value` class instances in those
cases will hold `None` values indicating that the field does not have an assigned value.

* `keys()` (`list[str]`) – The `keys()` method provides support for obtaining a list of
all of the names of the fields associated with the metadata model class.

* `values()` (`list[Value]`) – The `values()` method provides support for obtaining a
list of all of the values of the fields associated with the metadata model class, where
the values are held in `Value` subclass instances. Where a field does not have a current
value, a `Value` subclass instance holding a `None` value will be returned in its place
indicating that the field does not have an assigned value; the order of the items in the
list matches the order of the field names provided by the `keys()` method so the two can
be used together if needed as an alternative way of accessing the field names and values.

* `encode(order: ByteOrder)` - The `encode()` method provides support for encoding the
metadata model's assigned metadata fields and values into a binary format suitable for
embedding within the associated image.

* `decode(order: ByteOrder)` - The `decode()` method provides support for decoding the
binary encoded metadata payload obtained from the associated image and attempting to
parse the fields and values from the payload, and if successful, assigning those fields
and corresponding values to the current metadata model class instance for later use.

* `dump(all: bool = False)` (`caselessdict[str, object]`) – The `dump()` method is used
for development and can be used to obtain a dictionary of the metadata model's assigned
values with each value being associated against the model's field name. A dictionary is
returned that supports case-less matching of its keys so values can be retrieved if a
match can be found for the key regardless of if the casing of the key. If the `all` flag
is set to `True` the dictionary will be populated with the full list of metadata model
fields even if no value has been assigned to that field in the current model instance.

The `Metadata` class provides the following properties:

* `name` (`str`) – The `name` property provides access to the `Metadata` model subclass'
name, such as "EXIF", "IPTC" and "XMP".

* `namespace` (`Namespace`) – The `namespace` property provides access to get and set
the model's currently assigned `Namespace` class instance. This property is used by the
library internally and likely does not need to be used directly unless developing an
update for the EXIFData library.

* `namespaces` (`dict[str, Namespace]`) – The `namespaces` property provides access to a
dictionary of the model's currently assigned `Namespace` class instances. This property
is used by the library internally and likely does not need to be used directly unless
developing an update for the EXIFData library.

* `aliases` (`dict[str, Namespace | Groupspace]`) – The `aliases` property provides
access to a dictionary of the model's currently assigned `Namespace` and `Groupspace`
class instances. These are used to keep track of aliases for the namespaces which make
working with the namespaces easier as some have long and unwieldy assigned names in the
specifications, and the library offers shorter more concise names where practical. This
property is used by the library internally and likely does not need to be used directly
unless developing an update for the EXIFData library.

* `fields` (`dict[str, Value]`) – The `fields` property provides access to the metadata
model's fields via a dictionary where the keys are the field names and the values are
the assigned `Field` class instances holding information about the field that has been
sourced from the metadata model configuration.

* `values` (`dict[str, Value]`) – The `values` property provides access to the metadata
model's currently assigned field values via a dictionary where the keys are the field
names and the values are the assigned `Value` subclass instances holding the value.

#### Namespace

The `Namespace` class provides a structured method for grouping metadata model fields by
their namespace, and providing support for a metadata model to hold multiple namespaces
simultaneously each with their own set of metadata fields and values. The namespaces are
created dynamically when the metadata model classes are parsed with the namespaces being
determined from the metadata model class' schema configuration.

The `Namespace` class provides the following methods:

* `get(metadata: Metadata, field: Field)` (`Value` | `None`) – The `get()` method can be
used to obtain the specified metadata model field value, if it has been set previously,
with the value being returned as a `Value` subclass instance if a value has been set.

* `set(metadata: Metadata, field: Field, value: Value)` – The `set()` method can be used
to set the specified metadata model field value to value held by the assigned `Value`
subclass instance.

* `items()` (`Generator`)  – The `items()` method provides support for iterating over
the namespace's assigned fields. The generator yields `tuple` values that hold the name
of the field and the corresponding `Field` class instance.

* `keys()` (`list[str]`) – The `keys()` method provides support for obtaining a list of
all of the names of the fields associated with the namespace class instance.

* `values()` (`list[Value]`) – The `values()` method provides support for obtaining a
list of all of the values of the fields associated with the namespace instance, where
the values are held in `Value` subclass instances. Where a field does not have a current
value, a `Value` subclass instance holding a `None` value will be returned in its place
indicating that the field does not have an assigned value; the order of the items in the
list matches the order of the field names provided by the `keys()` method so the two can
be used together if needed as an alternative way of accessing the field names and values.

The `Namespace` class provides the following properties:

* `id` (`str`) – The `id` property provides access to the namespace's identifier.

* `name` (`str`) – The `name` property provides access to the namespace's name.

* `uri` (`str`) – The `uri` property provides access to the namespace's URI.

* `prefix` (`str`) – The `prefix` property provides access to the namespace's prefix.

* `alias` (`str` | `None`) – The `alias` property provides access to the namespace's
alias, if one has been set, otherwise `None` will be returned.

* `definition` (`str` | `None`) – The `definition` property provides access to the
namespace's descriptive definition, sourced from the metadata model class' schema if one
has been set, otherwise `None` will be returned.

* `metadata` (`Metadata`) – The `metadata` property provides access to get and set the
namespace's associated `Metadata` model class instance.

* `structures` (`list[Structure]`) – The `structures` property provides access to the
list of `Structure` class instances associated with the namespace, if any have been set
in the metadata model class' schema.

* `utilized` (`bool`) – The `utilized` property provides support for determining if the
current `Namespace` class instance has been utilized in the current program, which means
that at least one metadata model field has been set within the namespace. The property
will return `True` if at least one field has been set or `False` otherwise. This status
is used internally by the library when encoding a metadata model's data, whereby if the
namespace has not been utilized, it will be excluded by the encoding process. 

* `unwrap` (`bool`) – The `unwrap` property provides access to the `unwrap` property set
in the metadata model class' schema, which the library uses to determine if it should
"unwrap" the namespaces fields into its parent's namespace – that is to make the fields
directly accessible from the parent `Metadata` model class rather than indirectly via
the namespace. This field is used internally by the library and likely does not need to
be used directly unless developing an update for the EXIFData library.

* `fields` (`dict[str, Field]`) – The `fields` property is used internally by the library
to associate registered metadata model fields against the namespace. The property expects
a dictionary with string keys holding the fully qualified field names and `Field` class
instances as the values. This field is used internally by the library and should not need
to be used directly unless developing an update for the EXIFData library.

* `field` (`Field`) – The `field` property is used internally by the library to associate
a registered metadata model field against the namespace. The property expects a `Field`
class instances as its value. This field is used internally by the library and should not
need to be used directly unless developing an update for the EXIFData library.

* `value` (`Value`) - The `value` property is used internally by the library to associate
assigned metadata model namespace field values with the namespace. The property expects
a `Value` class instances as its value. The `Value` class instance must hold references
to the relevant `Metadata` model class instance and `Field` class instance so that the
value can be assigned to the correct field under the correct metadata model. The field
is used internally by the library and should not need to be used directly unless
developing an update for the EXIFData library.

#### Groupspace

The `Groupspace` class provides a structured method for grouping one or more namespaces
together to make assigning field values to those namespaces easier for certain uses. The
`Groupspace` class instances streamline support for aliasing the namespaces and are used
internally by the library and likely does not need to be used directly unless developing
an update for the EXIFData library.

The `Groupspace` class provides its own implementations of the standard library getter
and setter methods to support assigning field values to the relevant `Namespace` class
instance held by the `Groupspace` class instance.

The `Groupspace` class provides the following properties:

* `namespaces` (`list[Namespace]`) – The `namespaces` property provides access to the
list of namespaces associated with the `Groupspace` class instance.

* `metadata` (`Metadata`) – The `metadata` property provides access to get and set the
associated `Metadata` model class instance for the `Groupspace` class instance. This is
used when interacting with the underlying `Namespace` class instances so that they can
interface with the correct `Metadata` model class instance.

#### Field

The `Field` class provides a controlled method for holding information about metadata
model fields, including their identifier, name, label, definition, acceptable value data
types, acceptable value ranges, whether the field can hold multiple values or not, and
all other relevant field configuration information that is used both when decoding raw
metadata payloads and assembling encoded payloads as well as during value assignment.

The `Field` class provides the following methods:

* `value(value: object, metadata: Metadata = None)` – The `value()` method provides
support for assigning a value to the field against its associated namespace and metadata
model class instance. The `metadata` argument is optional, but can be used to override
the metadata model that the field value will be assigned to if needed.

The `Field` class provides the following properties:

* `namespace` (`Namespace`) – The `namespace` property provides access to the `Field`
class associated namespace.

* `identifier` (`str` | `int`) – The `identifier` property provides access to the
field's identifier.

* `name` (`str`) – The `name` property provides access to the field's name.

* `type` (`str` | `list[str]` | `tuple[str]` | `set[str]`) – The `type` property provides
access to the field's accepted data type or types as defined by the name of the accepted
data types.

* `structure` (`Structure` | `str`) – The `structure` property provides access to the
field's associated `Structure` class instance or structure name if one has been defined.

* `alias` (`str` | `list[str]`) – The `alias` property provides access to the field's
associated field name alias or aliases if any have been defined. The field name aliases
provide support for accessing fields via aliases as well as their assigned names.

* `pseudonym` (`str` | `list[str]` | `dict[str, str]`) – The `pseudonym` property
provides access to the registered pseudonyms for a field, these are names that are used
for the field in other software such as EXIFTool which helps support interoperability.

* `encoding` (`Encoding` | `str`) – The `encoding` property provides access to the value
encoding used the field, expressed as an `Encoding` enumeration class option or string.

* `unit` (`str`) – The `unit` property provides access to the name of the measurement
unit associated with the values held by the field.

* `tag` (`int`) – The `tag` property provides access to the field's associated tag
identifier value, such as the tag identifiers used to uniquely identify the fields in
the EXIF metadata and IPTC metadata models.

* `ordered` (`bool`) – The `ordered` property provides access to the `ordered` flag that
notes if the value held by the field should have its ordering preserved or not.

* `minimum` (`int` | `float`) – The `minimum` property provides access to the minimum
numeric value that can be held by the field, when the field has been configured to hold
a numeric value with a defined minimum.

* `maximum` (`int` | `float`) – The `maximum` property provides access to the maximum
numeric value that can be held by the field, when the field has been configured to hold
a numeric value with a defined maximum.

* `options` (`list[object]`) – The `options` property provides access to the list of
acceptable values that can be held by the field for fields that have such a list.

* `closed` (`bool`) – The `closed` property provides access to the `closed` flag which
notes whether a field must be assigned a value from a predefined (closed) list of options
or whether the field can be assigned a value from the list of options as well as others.

* `nullable` (`bool`) – The `nullable` property provides access to the `nullable` flag
which notes if the field can hold a null (`None`) value or not.

* `required` (`bool`) – The `required` property provides access to the `required` flag
which notes if the field holds a required value or not, where a value must be assigned
if the field is marked as being required.

* `readonly` (`bool`) – The `readonly` property provides access to the `readonly` flag
which notes if the field holds a read only value or not. Fields with read only values
can be used to access values parsed and decoded from embedded metadata payloads but the
field cannot change its value.

* `count` (`int` | `tuple[int]`) – The `count` property provides access to the number or
numbers values that the field must hold if a count has been specified. This property is
also used to hold the minimum and maximum lengths of string and bytes fields.

* `multiple` (`bool`) – The `multiple` property provides access to the `multiple` flag
which notes if the field supports holding more than one value or not.

* `combine` (`bool`) – The `combine` property provides access to the `combine` flag that
notes whether the values held by the field should be combined or not.

* `label` (`str`) – The `label` property provides access to the field's label if one has
been set in the model class' schema.

* `definition` (`str`) – The `definition` property provides access to the field's
descriptive definition if one has been set in the model class' schema.

* `related` (`Field` | `str`) – The `related` property provides access to a reference to
the field's related `Field` if one has been specified.

* `section` (`str`) – The `section` property provides access to the documentation section
reference for the metadata field, if one has been set in the model class' schema.

#### Value

The `Value` class provides the following methods:

* `validate()` (`bool`) – The `validate()` method provides support for validating the
value held by the `Value` subclass instance to determine if it is valid according to the
metadata model class' schema configuration.

* `decode(value: bytes, order: ByteOrder)` (`Value`) – The `decode()` method provides
support for decoding a raw binary encoded value extracted from the metadata payload into
its corresponding value which will be returned as a `Value` subclass instance.

* `encode(order: ByteOrder)` (`bytes`) – The `encode()` method provides support for
encoding the value held by the `Value` subclass instance into a form suitable for use as
part of the metadata model's encoded payload.

The `Value` class provides the following properties:

* `value` (`object`) – The `value` property provides access to the underlying value held
by the `Value` subclass instance.

* `encoding` (`Encoding`) – The `encoding` property provides access to the associated
encoding of the value field, expressed as an `Encoding` enumeration class option value.

* `field` (`Field` | `None`) – The `field` property provides access to the associated
instance of the `Field` class if one has been assigned.

* `metadata` (`Metadata` | `None`) – The `metadata` property provides access to the
associated instance of the `Metadata` class if one has been assigned.

#### Structure

The `Structure` class provides a controlled method for holding metadata model field
structure information extracted and assigned dynamically from the metadata model class'
schema configuration. The structure information is used internally by the library when
encoding metadata into its encoded form as defined by the associated metadata standard.

The `Structure` class provides the following properties:

* `id` (`str`) – The `id` property provides access to the structure's identifier.

* `identifier` (`str`) – The `identifier` property provides access to the structure's identifier.

* `name` (`str`) – The `name` property provides access to the structure's name.

* `type` (`str`) – The `id` property provides access to the structure's type name.

* `kind` (`str`) – The `id` property provides access to the structure's kind descriptor.

#### Type

The `Type` class enumeration class provides a controlled method for keeping track of the
registered field value types supported by each metadata model. The field value types are
registered by the metadata model classes dynamically when they are parsed with the types
being determined from the metadata model class' schema configuration.

<a id="file-formats"></a>
### Supported File Formats

The EXIFData library has been tested with a range of image file formats to determine the
accessibility of and ability to write embedded metadata, those file formats are listed
in the table below and with whether the file format supports reading or writing or both.
As the library currently relies upon PyVIPS for loading and saving image files, it may
be the case that additional file formats are found to work with the library, or support
may be added for additional file formats over time. The EXIFData library's ability to
support an image file format depends on the file format itself as there are myriad image
file formats and embedded metadata standards. Although EXIF, IPTC and XMP are considered
the most common, these standards are not supported by every image file format.

| File Format | EXIF Read | EXIF Write | IPTC Read | IPTC Write | XMP Read | XMP Write |
| ----------- | :-------: | :--------: | :-------: | :--------: | :------: | :-------: |
| JPEG        | No*       | Yes        | Yes       | Yes        | No*      | Yes       |
| TIFF        | No*       | Yes        | Yes       | Yes        | No*      | Yes       |
| PyramidTIFF | No*       | Yes        | Yes       | Yes        | No*      | Yes       |
| PNG         | *         | *          | *         | *          | *        | *         |
| HEIF        | *         | *          | *         | *          | *        | *         |

* EXIF and XMP read capability is in development and will be added in a future release.
* Support for other image file formats is currently in development.

### Disclaimer

While every effort has been made to ensure that the library works reliably with embedded
image metadata, you must ensure that all files are backed up before using the EXIFData
library with any files especially as the library is still in early development.

Furthermore, the library may not be able to read nor preserve all metadata field values
from an image file, especially if manufacturer specific or custom metadata model values
are present, so it is possible that loss of embedded metadata could occur if an image is
loaded into the library and is then overwritten if the file is saved to the same path.

Use of the library is entirely at your own risk and the authors bear no responsibility
for losses of any kind. By using the software you assume all such risk and liability.

THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
OR OTHER DEALINGS IN THE SOFTWARE.

### Credits & References

The EXIF, IPTC and XMP metadata model specifications were researched across various
sources. Please visit these valuable online resources to learn more about the metadata
model specifications and to support these world class organizations and their products:

 * EXIF Metadata Model & Fields
   * https://www.cipa.jp/e/index.html
   * https://www.loc.gov/preservation/digital/formats/fdd/fdd000146.shtml
   * https://exiftool.org/TagNames/EXIF.html
   * https://www.media.mit.edu/pia/Research/deepview/exif.html
   * https://exiv2.org/tags.html

 * IPTC Metadata Model & Fields
   * https://www.iptc.org/std/photometadata/specification/IPTC-PhotoMetadata
   * https://exiftool.org/TagNames/IPTC.html

 * XMP Metadata Model & Fields
   * https://www.adobe.com/products/xmp.html
   * https://exiftool.org/TagNames/XMP.html

### Copyright & License Information

Copyright © 2024–2025 Daniel Sissman; licensed under the MIT License.

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "exifdata",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.10",
    "maintainer_email": null,
    "keywords": "image, metadata, embedded, exif, iptc, xmp",
    "author": "Daniel Sissman",
    "author_email": null,
    "download_url": "https://files.pythonhosted.org/packages/cb/8b/7f50d895533ea4d45398558a5dd8ca04f72542e671e5b598ae777a934098/exifdata-0.5.7.tar.gz",
    "platform": "any",
    "description": "# EXIFData\n\nThe EXIFData library for Python provides a simplified and consistent way to work with\nembedded image metadata in the EXIF, IPTC and XMP formats. The library can be used to\nparse and create metadata in these formats which can be read from or embedded into image\nfiles such as TIFF and JPEG images.\n\nThe EXIFData library provides support for parsing and creating raw metadata payloads of\nthese formats while delegating responsibility to PyVIPS to perform the extraction of and\nembedding of the raw metadata payloads. Future versions of the library may offer support\nfor reading and writing a number of image file formats directly.\n\n### Requirements\n\nThe EXIFData library has been tested to work with Python 3.10, 3.11, 3.12 and 3.13, but\nhas not been tested, nor is its use supported with earlier versions of Python.\n\n### Installation\n\nThe library is available from the PyPI repository, so may be added easily to a project's\ndependencies via its `requirements.txt` file or similar by referencing the library's\nname, `exifdata`, or the library may be installed directly onto your local development\nsystem using `pip install` by entering the following command:\n\n\t$ pip install exifdata\n\nIf you would like to install the optional `pyvips` dependency with the library, use:\n\n\t$ pip install \"exifdata[pyvips]\"\n\nPyVIPS is needed if you wish to use open images from disk or to work with in-memory\nimages opened previously by PyVIPS. If you do not already have PyVIPS installed, it is\nbest to install it along with the library to ensure all functionality is available.\n\n### Conceptual Model\n\nThe EXIFData library provides access to each of the supported metadata models as a class\nthat offers a number of namespaces, with each namespace offering the full selection of\nmetadata fields provided by that namespace.\n\nThe structure of the models is as follows, where each model offers several namespaces,\nand each namespace offers many fields, that each provide access to one or more values\ndepending on the field, its data type, and its semantics:\n\n```\n                                            \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510        \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n                                      \u250c\u2500\u2500\u2500\u2500\u25b6\u2502  Field  \u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25b6\u2502  Value  \u2502\n                                      \u2502     \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518        \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n                    \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510   \u2502     \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510        \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n               \u250c\u2500\u2500\u2500\u25b6\u2502  Namespace  \u251c\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u25b6\u2502  Field  \u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25b6\u2502  Value  \u2502\n               \u2502    \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518         \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518        \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510    \u2502    \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510         \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510        \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502  Model  \u2502\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u25b6\u2502  Namespace  \u2502\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25b6\u2502  Field  \u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25b6\u2502  Value  \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518    \u2502    \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518         \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518        \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n               \u2502    \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510         \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510        \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n               \u2514\u2500\u2500\u2500\u25b6\u2502  Namespace  \u2502\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u25b6\u2502  Field  \u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25b6\u2502  Value  \u2502\n                    \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518    \u2502    \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518        \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n                                       \u2502    \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510        \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n                                       \u2514\u2500\u2500\u2500\u25b6\u2502  Field  \u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25b6\u2502  Value  \u2502\n                                            \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518        \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n```\n\nFor example, the `IPTC` model offers several namespaces including the `envelope`, and\n`application`, namespaces, while the `XMP` model offers many namespaces of its own\nincluding `basic`, `photoshop`, and `dc`. These namespaces then provide access to the\nmetadata fields for reading and writing.\n\nTo assign a value to the XMP metadata model's `dc.title` field for example, one would\neither access an existing instance of the `XMP` model class, or create one, and would\nthen reference and assign a value to the `title` field held within the `dc` namespace\nas follows:\n\n<!--pytest.mark.skip-->\n\n```python\nxmp.dc.title = \"this is a title\"\n```\n\nIn order to read a value from a field, one would just reference the field like any other\nproperty, and if the field has an assigned value that can be decoded, its value will be\navailable as an instance of the library's `Value` class.\n\nThe `Value` class and its subclasses exist to support encoding and decoding of the raw\nvalue types defined by each of the metadata standards.\n\n<!--pytest.mark.skip-->\n\n```python\nprint(xmp.dc.title)\n```\n\nFurthermore, where possible, the `Value` class types themselves subclass native Python\ntypes including `str`, `int`, `float`, and `datetime`, so these `Value` class instances\ncan be used interchangeably like the corresponding native type would be used; however by\nnecessity some of the `Value` subclasses represent structured data types and provide\nadditional fields or methods to access and assign the nested values, so must be used\ndirectly where the field requires it.\n\nEach metadata model's supported namespaces and fields are documented with information\nabout the relevant value types, which detail how to access and assign values to each of\nthe supported fields.\n\nThe following table lists the currently supported metadata models along with links to\ndocumentation, detailing each model's available namespaces and fields:\n\n| Metadata Model | Documentation                                              |\n|----------------|------------------------------------------------------------|\n| EXIF           | [EXIF Namespaces & Fields](./documentation/models/exif.md) |\n| IPTC           | [IPTC Namespaces & Fields](./documentation/models/iptc.md) |\n| XMP            | [XMP Namespaces & Fields](./documentation/models/xmp.md)   |\n\nThe EXIFData library also offers some convenience methods to make it easy to read and\nwrite the supported embedded metadata in supported image file formats; currently the\nlibrary relies on the PyVIPS library to read and write the image files, and perform the\nextraction and insertion of the raw metadata payloads, before handing off responsibility\nto the EXIFData library to decode and encode the raw metadata payloads and their nested\nnamespaces, fields and values.\n\nSee the [Classes & Methods](#classes-and-methods) section below for more information on\nthe available interfaces and their use; and see the [Supported File Formats](#file-formats)\nsection for more information on the image file formats that are currently supported by\nthe library, which includes JPEG, TIFF and Pyramidal TIFF images.\n\n### Example Use: Reading Metadata\n\nThe code sample below illustrates the use of the EXIFData library to read metadata:\n\n<!--pytest.mark.skip-->\n\n```python\nimport exifdata\n\n# Open an image file from disk and attempt to parse its embedded metadata\nmodels = exifdata.Models.open(\"/path/to/image-file.jpg\")\n\n# Print out the existing metadata model assigned fields and values\nfor model in models:\n    print(model.name)\n    for field, value in model.items(all=False):\n        print(\" -> %s => %s\" % (field, value))\n```\n\n### Example Use: Writing Metadata\n\nThe code sample below illustrates the use of the EXIFData library to write metadata:\n\n<!--pytest.mark.skip-->\n\n```python\nimport exifdata\n\nmodels = exifdata.Models.open(\"/path/to/image-file.jpg\")\n\nmodels.xmp.basic.title = \"test title\"\nmodels.iptc.credit = \"test credit\"\n\n# Save the image back to disk\nmodels.save()\n```\n\n### Example Use: Reading and Writing Metadata with an existing PyVIPS Image\n\n<!--pytest.mark.skip-->\n\n```python\nimport exifdata\nimport pyvips\n\n# Open the desired image file using PyVIPS\nimage = pyvips.Image.new_from_file(\"/path/to/image-file.tiff\")\n\n# Attempt to decode the metadata models from the provided image using EXIFData\nmodels = exifdata.Models.load(image)\n\n# Print out the existing metadata model assigned fields and values\nfor model in models:\n    print(model.name)\n    for field, value in model.items(all=False):\n        print(\" -> %s => %s\" % (field, value))\n\n# Set or update the desired metadata fields\nmodels.xmp.basic.title = \"test title\"\nmodels.iptc.credit = \"test credit\"\n\n# Encode the updated metadata and embed it into the in-memory image buffer\nmodels.encode()\n\n# Save the image back to disk or capture the image into a buffer as needed\nimage.tiffsave()\n```\n\n\u26a0\ufe0f **Note:** When working directly with a PyVIPS image held in an `Image` class instance\none must remember to save the image or otherwise do something with the updated in-memory\nimage buffer as the call to the `models.encode()` method only encodes and embeds the\nmetadata into the in-memory image buffer. While the in-memory image buffer will then\ncontain the metadata, if one needs to save the image back to disk, that must be handled\nas a separate call to PyVIPS.\n\n<a id=\"classes-and-methods\"></a>\n### Classes & Methods\n\n#### Models Class Methods & Properties\n\nThe `Models` class offers the following methods:\n\n* `adapt(adapter: Adapter)` \u2013 The `adapt()` method provides support for associating the\nspecified `Adapter` class type with the `Models` class to allow the specified adapter to\nbe used to assist in reading and writing image files.\n\n* `load(filepath: str)` \u2013 The `load()` method provides support for loading the specified\nimage file from the `filepath` which must exist and reference an image in a usable image\nfile format. If the referenced image file does not exist or cannot be loaded an error is\nreported.\n\n* `associate(image: object)` \u2013 The `associate()` method provides support for associating\nthe specified in-memory image with the `Models` class instance, which sets the reference\nto the image without attempting to extract or decode any of the pre-existing metadata in\nthe image.\n\n* `open(image: object)` \u2013 The `open()` method provides support for associating the\nspecified in-memory image with the `Models` class instance, which sets the reference to\nthe image and then proceeds to attempt extracting and decoding any pre-existing metadata\nin the image.\n\n* `update(model: Metadata)` \u2013 The `update()` method provides support for updating the\nmetadata models held by the `Models` class instance with new `Metadata` model subclass\ninstances if needed; if a matching `Metadata` model subclass has already been registered\nwith the `Models` class then it will be replaced by the provided `Metadata` instance and\nif no match is found then the the provided `Metadata` instance will be registered.\n\n* `assign(name: str, value: object)` \u2013 The `assign()` method provides support to assign\nmetadata model values to any of the supported metadata models via the metadata field's\nfully qualified name, along with a supported value. If the provided name can be matched\nwith a name associated with one or more metadata model fields, and if the provided value\nis valid, then the value will be assigned to the matching metadata model fields. This\noffers an alternative method to setting metadata model field values via the property\naccessor pattern.\n\n* `erase(payloads: list[str] = None)` \u2013 The `erase()` method provides support for erasing\nerasable metadata held in the associated image from either the specified payloads if one\nor more supported payload names are specified, or from all of the metadata payloads if\nno payloads are specified. The payloads and/or their embedded fields that are removed\nfrom an image are dependent on the metadata payload as some fields are mandatory so they\ncannot be removed, such as many of the fields in the EXIF payload. \n\n* `decode(order: ByteOrder)` \u2013 The `decode()` method provides support for decoding the\nembedded metadata payloads contained in the associated image file, and if metadata is\nfound within the image and can be successfully decoded, the relevant metadata model\nfield values will be populated with the decoded values. The values can then be read and\notherwise used, and if desired, the values can be modified or cleared, before saving the\nupdated metadata back to the associated image.\n\n* `encode(order: ByteOrder)` \u2013 The `encode()` method provides support for encoding the\nassigned metadata model field values into encoded metadata payloads suitable for storing\ninto the associated image file.\n\nThe `Models` class offers the following properties:\n\n* `adapter` (`Adapter`) \u2013 The `adapter` property provides access to the reference to the\ncurrent `Adapter` class instance associated with the `Models` class. The `Adapter` class\nis used by the `Models` class to interact with image data and raw metadata via various\nlibraries such as PyVIPS, EXIFTool and TIFFData.\n\n* `model` (`Metadata`) - The `model` property provides support for assigning one or more\n`Metadata` model class instances to the `Models` class. The property can only be used to\nassign `Metadata` model class instances to the `Models` class, it cannot be used to get\nany of the assigned `Metadata` model class instances; instead this can be achieved by\niterating over the `Models` class instance as the `Models` class supports the iterator\nprotocol to provide access to the assigned `Metadata` model class instances using the\nstandard `for ... in ...` pattern.\n\n* `exif` (`EXIF`) \u2013 The `exif` property provides support for accessing the `EXIF` model\ninstance associated with the `Models` class, which can then be used to access any of the\ndecoded metadata model field values or to assign or clear metadata model field values\nassociated with the EXIF metadata model.\n\n* `iptc` (`IPTC`) \u2013 The `iptc` property provides support for accessing the `IPTC` model\ninstance associated with the `Models` class, which can then be used to access any of the\ndecoded metadata model field values or to assign or clear metadata model field values\nassociated with the IPTC metadata model.\n\n* `xmp` (`XMP`) \u2013 The `xmp` property provides support for accessing the `XMP` model\ninstance associated with the `Models` class, which can then be used to access any of the\ndecoded metadata model field values or to assign or clear metadata model field values\nassociated with the XMP metadata model.\n\n#### Metadata\n\nThe `Metadata` class provides the following methods:\n\n* `register_type(type: Type, klass: Value)` \u2013 The `register_type()` method is used by\nthe EXIFData library internally to register `Value` subclass types for field types, as\ndefined by their `Type` enumeration class option values. The `Value` subclasses provide\nsupport for encoding and decoding metadata model field values according to the needs of\nthe specific metadata model. The method should not be used directly unless developing an\nupdate for the EXIFData library.\n\n* `register_types(*types: tuple[type])` \u2013 The `register_types()` method is used by the\nEXIFData library internally to register multiple `Value` subclass types for field types.\nThe `Value` subclasses provide support for encoding and decoding metadata model field\nvalues according to the needs of the specific metadata model. The method should not be\nused directly unless developing an update for the EXIFData library.\n\n* `type_by_name(name: str)` (`Value` | `None`) \u2013 The `type_by_name()` method provides\nsupport for accessing a registered `Value` type subclass by its name. This method is\nused internally by the library and likely does not need to be used directly unless\ndeveloping an update for the EXIFData library.\n\n* `field_by_id(id: str)` (`Field` | `None`) \u2013 The `field_by_id()` provides support for\nlooking up a  field by its identifier. If a match can be found the matching `Field` will\nbe returned, otherwise the method will return `None`.\n\n* `field_by_name(name: str)` (`Field` | `None`) \u2013 The `field_by_name()` provides support\nfor looking up a  field by its name. If a match can be found the matching `Field` will\nbe returned, otherwise the method will return `None`.\n\n* `field_by_property(property: str, value: object)` (`Field` | `None`) \u2013 The\n`field_by_property()` method provides support for looking up a field by one of its named\nproperties where a match is sought for the specified value. If a match can be found the\nmatching `Field` will be returned, otherwise the method will return `None`.\n\n* `get(name: str, default: object = None)` \u2013 The `get()` method provides support for\nobtaining the value set for the named metadata model class field, if a value has\npreviously been assigned. If no value was previously assigned the method will return the\ndefault value if one has been assigned or `None`.\n\n* `set(value: Value, name: str = None, field: Field = None, namespace: Namespace = None)`\n\u2013 The `set()` method provides support for setting a value on the metadata model class.\nIf the provided value held in a `Value` subclass instance has its own reference to a\n`Field` class instance, the field name can be determined from the `Field` and does not\nneed to be specified directly, otherwise the `name` argument can optionally be specified\nto provide the field name. If a `Namespace` class instance is optionally specified via\nthe `namespace` argument, then the field value will be stored within that namespace; if\na namespace is not specified directly, but a `Field` class instance is referenced by the\nvalue, then the namespace can be determined from the `Field` class instance.\n\n* `items(all: bool = False)` (`Generator`) \u2013 The `items()` method provides support for\niterating over the metadata model's fields and associated values. The generator yields\n`tuple` values that hold a `Field` class instance and its corresponding `Value` class\ninstance for all the metadata model fields that have assigned values. If the `all` flag\nis set to `True` the method will yield a `tuple` holding a `Field` class instance and a\n`Value` class instance for every registered field in the metadata model, even if some of\nthe fields do not have assigned values. The returned `Value` class instances in those\ncases will hold `None` values indicating that the field does not have an assigned value.\n\n* `keys()` (`list[str]`) \u2013 The `keys()` method provides support for obtaining a list of\nall of the names of the fields associated with the metadata model class.\n\n* `values()` (`list[Value]`) \u2013 The `values()` method provides support for obtaining a\nlist of all of the values of the fields associated with the metadata model class, where\nthe values are held in `Value` subclass instances. Where a field does not have a current\nvalue, a `Value` subclass instance holding a `None` value will be returned in its place\nindicating that the field does not have an assigned value; the order of the items in the\nlist matches the order of the field names provided by the `keys()` method so the two can\nbe used together if needed as an alternative way of accessing the field names and values.\n\n* `encode(order: ByteOrder)` - The `encode()` method provides support for encoding the\nmetadata model's assigned metadata fields and values into a binary format suitable for\nembedding within the associated image.\n\n* `decode(order: ByteOrder)` - The `decode()` method provides support for decoding the\nbinary encoded metadata payload obtained from the associated image and attempting to\nparse the fields and values from the payload, and if successful, assigning those fields\nand corresponding values to the current metadata model class instance for later use.\n\n* `dump(all: bool = False)` (`caselessdict[str, object]`) \u2013 The `dump()` method is used\nfor development and can be used to obtain a dictionary of the metadata model's assigned\nvalues with each value being associated against the model's field name. A dictionary is\nreturned that supports case-less matching of its keys so values can be retrieved if a\nmatch can be found for the key regardless of if the casing of the key. If the `all` flag\nis set to `True` the dictionary will be populated with the full list of metadata model\nfields even if no value has been assigned to that field in the current model instance.\n\nThe `Metadata` class provides the following properties:\n\n* `name` (`str`) \u2013 The `name` property provides access to the `Metadata` model subclass'\nname, such as \"EXIF\", \"IPTC\" and \"XMP\".\n\n* `namespace` (`Namespace`) \u2013 The `namespace` property provides access to get and set\nthe model's currently assigned `Namespace` class instance. This property is used by the\nlibrary internally and likely does not need to be used directly unless developing an\nupdate for the EXIFData library.\n\n* `namespaces` (`dict[str, Namespace]`) \u2013 The `namespaces` property provides access to a\ndictionary of the model's currently assigned `Namespace` class instances. This property\nis used by the library internally and likely does not need to be used directly unless\ndeveloping an update for the EXIFData library.\n\n* `aliases` (`dict[str, Namespace | Groupspace]`) \u2013 The `aliases` property provides\naccess to a dictionary of the model's currently assigned `Namespace` and `Groupspace`\nclass instances. These are used to keep track of aliases for the namespaces which make\nworking with the namespaces easier as some have long and unwieldy assigned names in the\nspecifications, and the library offers shorter more concise names where practical. This\nproperty is used by the library internally and likely does not need to be used directly\nunless developing an update for the EXIFData library.\n\n* `fields` (`dict[str, Value]`) \u2013 The `fields` property provides access to the metadata\nmodel's fields via a dictionary where the keys are the field names and the values are\nthe assigned `Field` class instances holding information about the field that has been\nsourced from the metadata model configuration.\n\n* `values` (`dict[str, Value]`) \u2013 The `values` property provides access to the metadata\nmodel's currently assigned field values via a dictionary where the keys are the field\nnames and the values are the assigned `Value` subclass instances holding the value.\n\n#### Namespace\n\nThe `Namespace` class provides a structured method for grouping metadata model fields by\ntheir namespace, and providing support for a metadata model to hold multiple namespaces\nsimultaneously each with their own set of metadata fields and values. The namespaces are\ncreated dynamically when the metadata model classes are parsed with the namespaces being\ndetermined from the metadata model class' schema configuration.\n\nThe `Namespace` class provides the following methods:\n\n* `get(metadata: Metadata, field: Field)` (`Value` | `None`) \u2013 The `get()` method can be\nused to obtain the specified metadata model field value, if it has been set previously,\nwith the value being returned as a `Value` subclass instance if a value has been set.\n\n* `set(metadata: Metadata, field: Field, value: Value)` \u2013 The `set()` method can be used\nto set the specified metadata model field value to value held by the assigned `Value`\nsubclass instance.\n\n* `items()` (`Generator`)  \u2013 The `items()` method provides support for iterating over\nthe namespace's assigned fields. The generator yields `tuple` values that hold the name\nof the field and the corresponding `Field` class instance.\n\n* `keys()` (`list[str]`) \u2013 The `keys()` method provides support for obtaining a list of\nall of the names of the fields associated with the namespace class instance.\n\n* `values()` (`list[Value]`) \u2013 The `values()` method provides support for obtaining a\nlist of all of the values of the fields associated with the namespace instance, where\nthe values are held in `Value` subclass instances. Where a field does not have a current\nvalue, a `Value` subclass instance holding a `None` value will be returned in its place\nindicating that the field does not have an assigned value; the order of the items in the\nlist matches the order of the field names provided by the `keys()` method so the two can\nbe used together if needed as an alternative way of accessing the field names and values.\n\nThe `Namespace` class provides the following properties:\n\n* `id` (`str`) \u2013 The `id` property provides access to the namespace's identifier.\n\n* `name` (`str`) \u2013 The `name` property provides access to the namespace's name.\n\n* `uri` (`str`) \u2013 The `uri` property provides access to the namespace's URI.\n\n* `prefix` (`str`) \u2013 The `prefix` property provides access to the namespace's prefix.\n\n* `alias` (`str` | `None`) \u2013 The `alias` property provides access to the namespace's\nalias, if one has been set, otherwise `None` will be returned.\n\n* `definition` (`str` | `None`) \u2013 The `definition` property provides access to the\nnamespace's descriptive definition, sourced from the metadata model class' schema if one\nhas been set, otherwise `None` will be returned.\n\n* `metadata` (`Metadata`) \u2013 The `metadata` property provides access to get and set the\nnamespace's associated `Metadata` model class instance.\n\n* `structures` (`list[Structure]`) \u2013 The `structures` property provides access to the\nlist of `Structure` class instances associated with the namespace, if any have been set\nin the metadata model class' schema.\n\n* `utilized` (`bool`) \u2013 The `utilized` property provides support for determining if the\ncurrent `Namespace` class instance has been utilized in the current program, which means\nthat at least one metadata model field has been set within the namespace. The property\nwill return `True` if at least one field has been set or `False` otherwise. This status\nis used internally by the library when encoding a metadata model's data, whereby if the\nnamespace has not been utilized, it will be excluded by the encoding process. \n\n* `unwrap` (`bool`) \u2013 The `unwrap` property provides access to the `unwrap` property set\nin the metadata model class' schema, which the library uses to determine if it should\n\"unwrap\" the namespaces fields into its parent's namespace \u2013 that is to make the fields\ndirectly accessible from the parent `Metadata` model class rather than indirectly via\nthe namespace. This field is used internally by the library and likely does not need to\nbe used directly unless developing an update for the EXIFData library.\n\n* `fields` (`dict[str, Field]`) \u2013 The `fields` property is used internally by the library\nto associate registered metadata model fields against the namespace. The property expects\na dictionary with string keys holding the fully qualified field names and `Field` class\ninstances as the values. This field is used internally by the library and should not need\nto be used directly unless developing an update for the EXIFData library.\n\n* `field` (`Field`) \u2013 The `field` property is used internally by the library to associate\na registered metadata model field against the namespace. The property expects a `Field`\nclass instances as its value. This field is used internally by the library and should not\nneed to be used directly unless developing an update for the EXIFData library.\n\n* `value` (`Value`) - The `value` property is used internally by the library to associate\nassigned metadata model namespace field values with the namespace. The property expects\na `Value` class instances as its value. The `Value` class instance must hold references\nto the relevant `Metadata` model class instance and `Field` class instance so that the\nvalue can be assigned to the correct field under the correct metadata model. The field\nis used internally by the library and should not need to be used directly unless\ndeveloping an update for the EXIFData library.\n\n#### Groupspace\n\nThe `Groupspace` class provides a structured method for grouping one or more namespaces\ntogether to make assigning field values to those namespaces easier for certain uses. The\n`Groupspace` class instances streamline support for aliasing the namespaces and are used\ninternally by the library and likely does not need to be used directly unless developing\nan update for the EXIFData library.\n\nThe `Groupspace` class provides its own implementations of the standard library getter\nand setter methods to support assigning field values to the relevant `Namespace` class\ninstance held by the `Groupspace` class instance.\n\nThe `Groupspace` class provides the following properties:\n\n* `namespaces` (`list[Namespace]`) \u2013 The `namespaces` property provides access to the\nlist of namespaces associated with the `Groupspace` class instance.\n\n* `metadata` (`Metadata`) \u2013 The `metadata` property provides access to get and set the\nassociated `Metadata` model class instance for the `Groupspace` class instance. This is\nused when interacting with the underlying `Namespace` class instances so that they can\ninterface with the correct `Metadata` model class instance.\n\n#### Field\n\nThe `Field` class provides a controlled method for holding information about metadata\nmodel fields, including their identifier, name, label, definition, acceptable value data\ntypes, acceptable value ranges, whether the field can hold multiple values or not, and\nall other relevant field configuration information that is used both when decoding raw\nmetadata payloads and assembling encoded payloads as well as during value assignment.\n\nThe `Field` class provides the following methods:\n\n* `value(value: object, metadata: Metadata = None)` \u2013 The `value()` method provides\nsupport for assigning a value to the field against its associated namespace and metadata\nmodel class instance. The `metadata` argument is optional, but can be used to override\nthe metadata model that the field value will be assigned to if needed.\n\nThe `Field` class provides the following properties:\n\n* `namespace` (`Namespace`) \u2013 The `namespace` property provides access to the `Field`\nclass associated namespace.\n\n* `identifier` (`str` | `int`) \u2013 The `identifier` property provides access to the\nfield's identifier.\n\n* `name` (`str`) \u2013 The `name` property provides access to the field's name.\n\n* `type` (`str` | `list[str]` | `tuple[str]` | `set[str]`) \u2013 The `type` property provides\naccess to the field's accepted data type or types as defined by the name of the accepted\ndata types.\n\n* `structure` (`Structure` | `str`) \u2013 The `structure` property provides access to the\nfield's associated `Structure` class instance or structure name if one has been defined.\n\n* `alias` (`str` | `list[str]`) \u2013 The `alias` property provides access to the field's\nassociated field name alias or aliases if any have been defined. The field name aliases\nprovide support for accessing fields via aliases as well as their assigned names.\n\n* `pseudonym` (`str` | `list[str]` | `dict[str, str]`) \u2013 The `pseudonym` property\nprovides access to the registered pseudonyms for a field, these are names that are used\nfor the field in other software such as EXIFTool which helps support interoperability.\n\n* `encoding` (`Encoding` | `str`) \u2013 The `encoding` property provides access to the value\nencoding used the field, expressed as an `Encoding` enumeration class option or string.\n\n* `unit` (`str`) \u2013 The `unit` property provides access to the name of the measurement\nunit associated with the values held by the field.\n\n* `tag` (`int`) \u2013 The `tag` property provides access to the field's associated tag\nidentifier value, such as the tag identifiers used to uniquely identify the fields in\nthe EXIF metadata and IPTC metadata models.\n\n* `ordered` (`bool`) \u2013 The `ordered` property provides access to the `ordered` flag that\nnotes if the value held by the field should have its ordering preserved or not.\n\n* `minimum` (`int` | `float`) \u2013 The `minimum` property provides access to the minimum\nnumeric value that can be held by the field, when the field has been configured to hold\na numeric value with a defined minimum.\n\n* `maximum` (`int` | `float`) \u2013 The `maximum` property provides access to the maximum\nnumeric value that can be held by the field, when the field has been configured to hold\na numeric value with a defined maximum.\n\n* `options` (`list[object]`) \u2013 The `options` property provides access to the list of\nacceptable values that can be held by the field for fields that have such a list.\n\n* `closed` (`bool`) \u2013 The `closed` property provides access to the `closed` flag which\nnotes whether a field must be assigned a value from a predefined (closed) list of options\nor whether the field can be assigned a value from the list of options as well as others.\n\n* `nullable` (`bool`) \u2013 The `nullable` property provides access to the `nullable` flag\nwhich notes if the field can hold a null (`None`) value or not.\n\n* `required` (`bool`) \u2013 The `required` property provides access to the `required` flag\nwhich notes if the field holds a required value or not, where a value must be assigned\nif the field is marked as being required.\n\n* `readonly` (`bool`) \u2013 The `readonly` property provides access to the `readonly` flag\nwhich notes if the field holds a read only value or not. Fields with read only values\ncan be used to access values parsed and decoded from embedded metadata payloads but the\nfield cannot change its value.\n\n* `count` (`int` | `tuple[int]`) \u2013 The `count` property provides access to the number or\nnumbers values that the field must hold if a count has been specified. This property is\nalso used to hold the minimum and maximum lengths of string and bytes fields.\n\n* `multiple` (`bool`) \u2013 The `multiple` property provides access to the `multiple` flag\nwhich notes if the field supports holding more than one value or not.\n\n* `combine` (`bool`) \u2013 The `combine` property provides access to the `combine` flag that\nnotes whether the values held by the field should be combined or not.\n\n* `label` (`str`) \u2013 The `label` property provides access to the field's label if one has\nbeen set in the model class' schema.\n\n* `definition` (`str`) \u2013 The `definition` property provides access to the field's\ndescriptive definition if one has been set in the model class' schema.\n\n* `related` (`Field` | `str`) \u2013 The `related` property provides access to a reference to\nthe field's related `Field` if one has been specified.\n\n* `section` (`str`) \u2013 The `section` property provides access to the documentation section\nreference for the metadata field, if one has been set in the model class' schema.\n\n#### Value\n\nThe `Value` class provides the following methods:\n\n* `validate()` (`bool`) \u2013 The `validate()` method provides support for validating the\nvalue held by the `Value` subclass instance to determine if it is valid according to the\nmetadata model class' schema configuration.\n\n* `decode(value: bytes, order: ByteOrder)` (`Value`) \u2013 The `decode()` method provides\nsupport for decoding a raw binary encoded value extracted from the metadata payload into\nits corresponding value which will be returned as a `Value` subclass instance.\n\n* `encode(order: ByteOrder)` (`bytes`) \u2013 The `encode()` method provides support for\nencoding the value held by the `Value` subclass instance into a form suitable for use as\npart of the metadata model's encoded payload.\n\nThe `Value` class provides the following properties:\n\n* `value` (`object`) \u2013 The `value` property provides access to the underlying value held\nby the `Value` subclass instance.\n\n* `encoding` (`Encoding`) \u2013 The `encoding` property provides access to the associated\nencoding of the value field, expressed as an `Encoding` enumeration class option value.\n\n* `field` (`Field` | `None`) \u2013 The `field` property provides access to the associated\ninstance of the `Field` class if one has been assigned.\n\n* `metadata` (`Metadata` | `None`) \u2013 The `metadata` property provides access to the\nassociated instance of the `Metadata` class if one has been assigned.\n\n#### Structure\n\nThe `Structure` class provides a controlled method for holding metadata model field\nstructure information extracted and assigned dynamically from the metadata model class'\nschema configuration. The structure information is used internally by the library when\nencoding metadata into its encoded form as defined by the associated metadata standard.\n\nThe `Structure` class provides the following properties:\n\n* `id` (`str`) \u2013 The `id` property provides access to the structure's identifier.\n\n* `identifier` (`str`) \u2013 The `identifier` property provides access to the structure's identifier.\n\n* `name` (`str`) \u2013 The `name` property provides access to the structure's name.\n\n* `type` (`str`) \u2013 The `id` property provides access to the structure's type name.\n\n* `kind` (`str`) \u2013 The `id` property provides access to the structure's kind descriptor.\n\n#### Type\n\nThe `Type` class enumeration class provides a controlled method for keeping track of the\nregistered field value types supported by each metadata model. The field value types are\nregistered by the metadata model classes dynamically when they are parsed with the types\nbeing determined from the metadata model class' schema configuration.\n\n<a id=\"file-formats\"></a>\n### Supported File Formats\n\nThe EXIFData library has been tested with a range of image file formats to determine the\naccessibility of and ability to write embedded metadata, those file formats are listed\nin the table below and with whether the file format supports reading or writing or both.\nAs the library currently relies upon PyVIPS for loading and saving image files, it may\nbe the case that additional file formats are found to work with the library, or support\nmay be added for additional file formats over time. The EXIFData library's ability to\nsupport an image file format depends on the file format itself as there are myriad image\nfile formats and embedded metadata standards. Although EXIF, IPTC and XMP are considered\nthe most common, these standards are not supported by every image file format.\n\n| File Format | EXIF Read | EXIF Write | IPTC Read | IPTC Write | XMP Read | XMP Write |\n| ----------- | :-------: | :--------: | :-------: | :--------: | :------: | :-------: |\n| JPEG        | No*       | Yes        | Yes       | Yes        | No*      | Yes       |\n| TIFF        | No*       | Yes        | Yes       | Yes        | No*      | Yes       |\n| PyramidTIFF | No*       | Yes        | Yes       | Yes        | No*      | Yes       |\n| PNG         | *         | *          | *         | *          | *        | *         |\n| HEIF        | *         | *          | *         | *          | *        | *         |\n\n* EXIF and XMP read capability is in development and will be added in a future release.\n* Support for other image file formats is currently in development.\n\n### Disclaimer\n\nWhile every effort has been made to ensure that the library works reliably with embedded\nimage metadata, you must ensure that all files are backed up before using the EXIFData\nlibrary with any files especially as the library is still in early development.\n\nFurthermore, the library may not be able to read nor preserve all metadata field values\nfrom an image file, especially if manufacturer specific or custom metadata model values\nare present, so it is possible that loss of embedded metadata could occur if an image is\nloaded into the library and is then overwritten if the file is saved to the same path.\n\nUse of the library is entirely at your own risk and the authors bear no responsibility\nfor losses of any kind. By using the software you assume all such risk and liability.\n\nTHIS SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,\nINCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR\nPURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE\nOR OTHER DEALINGS IN THE SOFTWARE.\n\n### Credits & References\n\nThe EXIF, IPTC and XMP metadata model specifications were researched across various\nsources. Please visit these valuable online resources to learn more about the metadata\nmodel specifications and to support these world class organizations and their products:\n\n * EXIF Metadata Model & Fields\n   * https://www.cipa.jp/e/index.html\n   * https://www.loc.gov/preservation/digital/formats/fdd/fdd000146.shtml\n   * https://exiftool.org/TagNames/EXIF.html\n   * https://www.media.mit.edu/pia/Research/deepview/exif.html\n   * https://exiv2.org/tags.html\n\n * IPTC Metadata Model & Fields\n   * https://www.iptc.org/std/photometadata/specification/IPTC-PhotoMetadata\n   * https://exiftool.org/TagNames/IPTC.html\n\n * XMP Metadata Model & Fields\n   * https://www.adobe.com/products/xmp.html\n   * https://exiftool.org/TagNames/XMP.html\n\n### Copyright & License Information\n\nCopyright \u00a9 2024\u20132025 Daniel Sissman; licensed under the MIT License.\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "Streamlined EXIF, IPTC and XMP image metadata creation and parsing.",
    "version": "0.5.7",
    "project_urls": {
        "changelog": "https://github.com/bluebinary/exifdata/blob/main/CHANGELOG.md",
        "documentation": "https://github.com/bluebinary/exifdata/blob/main/README.md",
        "homepage": "https://github.com/bluebinary/exifdata",
        "issues": "https://github.com/bluebinary/exifdata/issues",
        "repository": "https://github.com/bluebinary/exifdata"
    },
    "split_keywords": [
        "image",
        " metadata",
        " embedded",
        " exif",
        " iptc",
        " xmp"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "b2adbd3261391b851f81a5cadf37fe6fbe6cb617ef63db78e653b7aaccb4985a",
                "md5": "31e88e400bf781bbe2e5b83ec0113ca1",
                "sha256": "a4530cf3da63cd9b556fdcd3567996bed1dbc7c3ad6176019e5474f14a6bd127"
            },
            "downloads": -1,
            "filename": "exifdata-0.5.7-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "31e88e400bf781bbe2e5b83ec0113ca1",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.10",
            "size": 101938,
            "upload_time": "2025-08-23T19:50:45",
            "upload_time_iso_8601": "2025-08-23T19:50:45.686599Z",
            "url": "https://files.pythonhosted.org/packages/b2/ad/bd3261391b851f81a5cadf37fe6fbe6cb617ef63db78e653b7aaccb4985a/exifdata-0.5.7-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "cb8b7f50d895533ea4d45398558a5dd8ca04f72542e671e5b598ae777a934098",
                "md5": "d30c4785dca6eed9484c7dd502213990",
                "sha256": "8cb4b6131a1308e7828dd5be5591e5aecdf65d26f3304dd11f5ea386c397908d"
            },
            "downloads": -1,
            "filename": "exifdata-0.5.7.tar.gz",
            "has_sig": false,
            "md5_digest": "d30c4785dca6eed9484c7dd502213990",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.10",
            "size": 108579,
            "upload_time": "2025-08-23T19:50:47",
            "upload_time_iso_8601": "2025-08-23T19:50:47.143375Z",
            "url": "https://files.pythonhosted.org/packages/cb/8b/7f50d895533ea4d45398558a5dd8ca04f72542e671e5b598ae777a934098/exifdata-0.5.7.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-08-23 19:50:47",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "bluebinary",
    "github_project": "exifdata",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "requirements": [
        {
            "name": "enumerific",
            "specs": [
                [
                    ">=",
                    "1.0.5"
                ]
            ]
        },
        {
            "name": "caselessly",
            "specs": [
                [
                    ">=",
                    "1.0.0"
                ]
            ]
        },
        {
            "name": "deliciousbytes",
            "specs": [
                [
                    ">=",
                    "1.0.4"
                ]
            ]
        },
        {
            "name": "maxml",
            "specs": [
                [
                    ">=",
                    "1.0.2"
                ]
            ]
        },
        {
            "name": "tiffdata",
            "specs": [
                [
                    ">=",
                    "0.5.4"
                ]
            ]
        }
    ],
    "lcname": "exifdata"
}
        
Elapsed time: 1.49887s