__init__.py 3.4 KB

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