1# -*- coding: utf-8 -*-
2# imageio is distributed under the terms of the (new) BSD License.
3
4# flake8: noqa
5
6"""
7Here you can find documentation on how to write your own plugin to allow
8ImageIO to access a new backend. Plugins are quite object oriented, and
9the relevant classes and their interaction are documented here:
10
11.. currentmodule:: imageio
12
13.. autosummary::
14 :toctree: ../_autosummary
15 :template: better_class.rst
16
17 imageio.core.Format
18 imageio.core.Request
19
20.. note::
21 You can always check existing plugins if you want to see examples.
22
23What methods to implement
24-------------------------
25
26To implement a new plugin, create a new class that inherits from
27:class:`imageio.core.Format`. and implement the following functions:
28
29.. autosummary::
30 :toctree: ../_autosummary
31
32 imageio.core.Format.__init__
33 imageio.core.Format._can_read
34 imageio.core.Format._can_write
35
36Further, each format contains up to two nested classes; one for reading and
37one for writing. To support reading and/or writing, the respective classes
38need to be defined.
39
40For reading, create a nested class that inherits from
41``imageio.core.Format.Reader`` and that implements the following functions:
42
43 * Implement ``_open(**kwargs)`` to initialize the reader. Deal with the
44 user-provided keyword arguments here.
45 * Implement ``_close()`` to clean up.
46 * Implement ``_get_length()`` to provide a suitable length based on what
47 the user expects. Can be ``inf`` for streaming data.
48 * Implement ``_get_data(index)`` to return an array and a meta-data dict.
49 * Implement ``_get_meta_data(index)`` to return a meta-data dict. If index
50 is None, it should return the 'global' meta-data.
51
52For writing, create a nested class that inherits from
53``imageio.core.Format.Writer`` and implement the following functions:
54
55 * Implement ``_open(**kwargs)`` to initialize the writer. Deal with the
56 user-provided keyword arguments here.
57 * Implement ``_close()`` to clean up.
58 * Implement ``_append_data(im, meta)`` to add data (and meta-data).
59 * Implement ``_set_meta_data(meta)`` to set the global meta-data.
60
61"""
62
63import importlib
64import os
65import warnings
66
67
68# v2 imports remove in v3
69from .. import formats
70
71# v2 allows formatting plugins by environment variable
72# this is done here.
73env_plugin_order = os.getenv("IMAGEIO_FORMAT_ORDER", None)
74if env_plugin_order is not None: # pragma: no cover
75 warnings.warn(
76 "Setting plugin priority through an environment variable is"
77 " deprecated and will be removed in ImageIO v3. There is no"
78 " replacement planned for this feature. If you have an"
79 " active use-case for it, please reach out to us on GitHub.",
80 DeprecationWarning,
81 )
82
83 formats.sort(*os.getenv("IMAGEIO_FORMAT_ORDER", "").split(","))
84
85
86# this class replaces plugin module. For details
87# see https://stackoverflow.com/questions/2447353/getattr-on-a-module
88def __getattr__(name):
89 """Lazy-Import Plugins
90
91 This function dynamically loads plugins into the imageio.plugin
92 namespace upon first access. For example, the following snippet will
93 delay importing freeimage until the second line:
94
95 >>> import imageio
96 >>> imageio.plugins.freeimage.download()
97
98 """
99
100 try:
101 return importlib.import_module(f"imageio.plugins.{name}")
102 except ImportError:
103 raise AttributeError(f"module '{__name__}' has no attribute '{name}'") from None