prasb commited on
Commit
ab8fdef
·
verified ·
1 Parent(s): 1bb680b

Add files using upload-large-folder tool

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitattributes +4 -0
  2. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/__pycache__/__init__.cpython-38.pyc +0 -0
  3. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/__pycache__/__main__.cpython-38.pyc +0 -0
  4. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/__pycache__/freeze.cpython-38.pyc +0 -0
  5. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/__pycache__/testing.cpython-38.pyc +0 -0
  6. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/__pycache__/typing.cpython-38.pyc +0 -0
  7. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/__pycache__/v2.cpython-38.pyc +0 -0
  8. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/__pycache__/v3.cpython-38.pyc +0 -0
  9. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/config/__init__.py +16 -0
  10. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/config/extensions.py +1919 -0
  11. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/config/plugins.py +784 -0
  12. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/core/__init__.py +16 -0
  13. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/core/__pycache__/__init__.cpython-38.pyc +0 -0
  14. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/core/__pycache__/legacy_plugin_wrapper.cpython-38.pyc +0 -0
  15. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/core/__pycache__/request.cpython-38.pyc +0 -0
  16. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/core/findlib.py +161 -0
  17. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/core/format.py +856 -0
  18. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/core/imopen.py +303 -0
  19. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/core/legacy_plugin_wrapper.py +322 -0
  20. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/core/request.py +752 -0
  21. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/core/v3_plugin_api.py +367 -0
  22. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/plugins/__pycache__/__init__.cpython-38.pyc +0 -0
  23. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/plugins/__pycache__/_bsdf.cpython-38.pyc +0 -0
  24. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/plugins/__pycache__/_dicom.cpython-38.pyc +0 -0
  25. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/plugins/__pycache__/_freeimage.cpython-38.pyc +0 -0
  26. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/plugins/__pycache__/_swf.cpython-38.pyc +0 -0
  27. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/plugins/__pycache__/feisem.cpython-38.pyc +0 -0
  28. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/plugins/__pycache__/fits.cpython-38.pyc +0 -0
  29. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/plugins/__pycache__/freeimage.cpython-38.pyc +0 -0
  30. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/plugins/__pycache__/gdal.cpython-38.pyc +0 -0
  31. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/plugins/__pycache__/lytro.cpython-38.pyc +0 -0
  32. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/plugins/__pycache__/npz.cpython-38.pyc +0 -0
  33. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/plugins/__pycache__/opencv.cpython-38.pyc +0 -0
  34. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/plugins/__pycache__/pillow.cpython-38.pyc +0 -0
  35. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/plugins/__pycache__/pillow_info.cpython-38.pyc +0 -0
  36. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/plugins/__pycache__/pillow_legacy.cpython-38.pyc +0 -0
  37. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/plugins/__pycache__/pillowmulti.cpython-38.pyc +0 -0
  38. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/plugins/__pycache__/simpleitk.cpython-38.pyc +0 -0
  39. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/plugins/__pycache__/swf.cpython-38.pyc +0 -0
  40. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/plugins/__pycache__/tifffile.cpython-38.pyc +0 -0
  41. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/plugins/_dicom.py +925 -0
  42. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/plugins/_tifffile.py +0 -0
  43. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/plugins/example.py +148 -0
  44. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/plugins/gdal.py +71 -0
  45. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/plugins/npz.py +85 -0
  46. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/resources/images/realshort.mp4 +0 -0
  47. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/matplotlib/__pycache__/patches.cpython-38.pyc +3 -0
  48. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/matplotlib/mpl-data/fonts/ttf/DejaVuSerif-Bold.ttf +3 -0
  49. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/matplotlib/mpl-data/fonts/ttf/STIXGeneralBolIta.ttf +3 -0
  50. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/matplotlib/mpl-data/fonts/ttf/STIXGeneralItalic.ttf +3 -0
.gitattributes CHANGED
@@ -375,3 +375,7 @@ my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/pkg_resourc
375
  my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/matplotlib/__pycache__/backend_bases.cpython-38.pyc filter=lfs diff=lfs merge=lfs -text
376
  my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/lxml/objectify.cpython-38-x86_64-linux-gnu.so filter=lfs diff=lfs merge=lfs -text
377
  my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/matplotlib/__pycache__/figure.cpython-38.pyc filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
375
  my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/matplotlib/__pycache__/backend_bases.cpython-38.pyc filter=lfs diff=lfs merge=lfs -text
376
  my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/lxml/objectify.cpython-38-x86_64-linux-gnu.so filter=lfs diff=lfs merge=lfs -text
377
  my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/matplotlib/__pycache__/figure.cpython-38.pyc filter=lfs diff=lfs merge=lfs -text
378
+ my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/matplotlib/__pycache__/patches.cpython-38.pyc filter=lfs diff=lfs merge=lfs -text
379
+ my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/matplotlib/mpl-data/fonts/ttf/STIXGeneralBolIta.ttf filter=lfs diff=lfs merge=lfs -text
380
+ my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/matplotlib/mpl-data/fonts/ttf/STIXGeneralItalic.ttf filter=lfs diff=lfs merge=lfs -text
381
+ my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/matplotlib/mpl-data/fonts/ttf/DejaVuSerif-Bold.ttf filter=lfs diff=lfs merge=lfs -text
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/__pycache__/__init__.cpython-38.pyc ADDED
Binary file (2.66 kB). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/__pycache__/__main__.cpython-38.pyc ADDED
Binary file (4.19 kB). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/__pycache__/freeze.cpython-38.pyc ADDED
Binary file (476 Bytes). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/__pycache__/testing.cpython-38.pyc ADDED
Binary file (1.51 kB). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/__pycache__/typing.cpython-38.pyc ADDED
Binary file (479 Bytes). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/__pycache__/v2.cpython-38.pyc ADDED
Binary file (15.5 kB). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/__pycache__/v3.cpython-38.pyc ADDED
Binary file (9.77 kB). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/config/__init__.py ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from .extensions import (
2
+ extension_list,
3
+ known_extensions,
4
+ FileExtension,
5
+ video_extensions,
6
+ )
7
+ from .plugins import known_plugins, PluginConfig
8
+
9
+ __all__ = [
10
+ "known_plugins",
11
+ "PluginConfig",
12
+ "extension_list",
13
+ "known_extensions",
14
+ "FileExtension",
15
+ "video_extensions",
16
+ ]
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/config/extensions.py ADDED
@@ -0,0 +1,1919 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ A set of objects representing each file extension recognized by ImageIO. If an
3
+ extension is not listed here it is still supported, as long as there exists a
4
+ supporting backend.
5
+
6
+ """
7
+
8
+
9
+ class FileExtension:
10
+ """File Extension Metadata
11
+
12
+ This class holds information about a image file format associated with a
13
+ given extension. This information is used to track plugins that are known to
14
+ be able to handle a particular format. It also contains additional
15
+ information about a format, which is used when creating the supported format
16
+ docs.
17
+
18
+ Plugins known to be able to handle this format are ordered by a ``priority``
19
+ list. This list is used to determine the ideal plugin to use when choosing a
20
+ plugin based on file extension.
21
+
22
+ Parameters
23
+ ----------
24
+ extension : str
25
+ The name of the extension including the initial dot, e.g. ".png".
26
+ priority : List
27
+ A list of plugin names (entries in config.known_plugins) that can handle
28
+ this format. The position of a plugin expresses a preference, e.g.
29
+ ["plugin1", "plugin2"] indicates that, if available, plugin1 should be
30
+ preferred over plugin2 when handling a request related to this format.
31
+ name : str
32
+ The full name of the format.
33
+ description : str
34
+ A description of the format.
35
+ external_link : str
36
+ A link to further information about the format. Typically, the format's
37
+ specification.
38
+
39
+ Examples
40
+ --------
41
+ >>> FileExtension(
42
+ name="Bitmap",
43
+ extension=".bmp",
44
+ priority=["pillow", "BMP-PIL", "BMP-FI", "ITK"],
45
+ external_link="https://en.wikipedia.org/wiki/BMP_file_format",
46
+ )
47
+
48
+ """
49
+
50
+ def __init__(
51
+ self, *, extension, priority, name=None, description=None, external_link=None
52
+ ):
53
+ self.extension = extension
54
+ self.priority = priority
55
+ self.name = name
56
+ self.description = description
57
+ self.external_link = external_link
58
+ self.default_priority = priority.copy()
59
+
60
+ def reset(self):
61
+ self.priority = self.default_priority.copy()
62
+
63
+
64
+ extension_list = [
65
+ FileExtension(
66
+ name="Hasselblad raw",
67
+ extension=".3fr",
68
+ priority=["RAW-FI"],
69
+ ),
70
+ FileExtension(
71
+ name="Sony alpha",
72
+ extension=".arw",
73
+ priority=["RAW-FI"],
74
+ ),
75
+ FileExtension(
76
+ name="Animated Portable Network Graphics",
77
+ external_link="https://en.wikipedia.org/wiki/APNG",
78
+ extension=".apng",
79
+ priority=["pillow", "pyav"],
80
+ ),
81
+ FileExtension(
82
+ name="Audio Video Interleave",
83
+ extension=".avi",
84
+ priority=["FFMPEG"],
85
+ ),
86
+ FileExtension(
87
+ name="Casio raw format",
88
+ extension=".bay",
89
+ priority=["RAW-FI"],
90
+ ),
91
+ FileExtension(
92
+ extension=".blp",
93
+ priority=["pillow"],
94
+ ),
95
+ FileExtension(
96
+ name="Bitmap",
97
+ extension=".bmp",
98
+ priority=["pillow", "BMP-PIL", "BMP-FI", "ITK", "pyav", "opencv"],
99
+ external_link="https://en.wikipedia.org/wiki/BMP_file_format",
100
+ ),
101
+ FileExtension(
102
+ name="Device-Independent Bitmap",
103
+ extension=".dip",
104
+ priority=["opencv"],
105
+ external_link="https://en.wikipedia.org/wiki/BMP_file_format",
106
+ ),
107
+ FileExtension(
108
+ name="Re-Volt mipmap",
109
+ extension=".bmq",
110
+ priority=["RAW-FI"],
111
+ ),
112
+ FileExtension(
113
+ name="Binary Structured Data Format",
114
+ extension=".bsdf",
115
+ priority=["BSDF"],
116
+ external_link="http://bsdf.io/",
117
+ ),
118
+ FileExtension(
119
+ name="Binary Universal Form for the Representation of meteorological data",
120
+ extension=".bufr",
121
+ priority=["pillow", "BUFR-PIL"],
122
+ ),
123
+ FileExtension(
124
+ name="Silicon Graphics Image",
125
+ extension=".bw",
126
+ priority=["pillow", "SGI-PIL", "SGI-FI"],
127
+ ),
128
+ FileExtension(
129
+ name="Scirra Construct",
130
+ extension=".cap",
131
+ priority=["RAW-FI"],
132
+ ),
133
+ FileExtension(
134
+ name="AMETEK High Speed Camera Format",
135
+ extension=".cine",
136
+ priority=["RAW-FI"],
137
+ external_link="https://phantomhighspeed-knowledge.secure.force.com/servlet/fileField?id=0BE1N000000kD2i#:~:text=Cine%20is%20a%20video%20file,camera%20model%20and%20image%20resolution",
138
+ ),
139
+ FileExtension(extension=".cr2", priority=["RAW-FI"]),
140
+ FileExtension(
141
+ extension=".crw",
142
+ priority=["RAW-FI"],
143
+ ),
144
+ FileExtension(
145
+ extension=".cs1",
146
+ priority=["RAW-FI"],
147
+ ),
148
+ FileExtension(
149
+ name="Computerized Tomography",
150
+ extension=".ct",
151
+ priority=["DICOM"],
152
+ ),
153
+ FileExtension(
154
+ name="Windows Cursor Icons",
155
+ extension=".cur",
156
+ priority=["pillow", "CUR-PIL"],
157
+ ),
158
+ FileExtension(
159
+ name="Dr. Halo",
160
+ extension=".cut",
161
+ priority=["CUT-FI"],
162
+ ),
163
+ FileExtension(
164
+ extension=".dc2",
165
+ priority=["RAW-FI"],
166
+ ),
167
+ FileExtension(
168
+ name="DICOM file format",
169
+ extension=".dcm",
170
+ priority=["DICOM", "ITK"],
171
+ ),
172
+ FileExtension(
173
+ extension=".dcr",
174
+ priority=["RAW-FI"],
175
+ ),
176
+ FileExtension(
177
+ name="Intel DCX",
178
+ extension=".dcx",
179
+ priority=["pillow", "DCX-PIL"],
180
+ ),
181
+ FileExtension(
182
+ name="DirectX Texture Container",
183
+ extension=".dds",
184
+ priority=["pillow", "DDS-FI", "DDS-PIL"],
185
+ ),
186
+ FileExtension(
187
+ name="Windows Bitmap",
188
+ extension=".dib",
189
+ priority=["pillow", "DIB-PIL"],
190
+ ),
191
+ FileExtension(
192
+ name="DICOM file format",
193
+ extension=".dicom",
194
+ priority=["ITK"],
195
+ ),
196
+ FileExtension(
197
+ extension=".dng",
198
+ priority=["RAW-FI"],
199
+ ),
200
+ FileExtension(
201
+ extension=".drf",
202
+ priority=["RAW-FI"],
203
+ ),
204
+ FileExtension(
205
+ extension=".dsc",
206
+ priority=["RAW-FI"],
207
+ ),
208
+ FileExtension(
209
+ name="Enhanced Compression Wavelet",
210
+ extension=".ecw",
211
+ priority=["GDAL"],
212
+ ),
213
+ FileExtension(
214
+ name="Windows Metafile",
215
+ extension=".emf",
216
+ priority=["pillow", "WMF-PIL"],
217
+ ),
218
+ FileExtension(
219
+ name="Encapsulated Postscript",
220
+ extension=".eps",
221
+ priority=["pillow", "EPS-PIL"],
222
+ ),
223
+ FileExtension(
224
+ extension=".erf",
225
+ priority=["RAW-FI"],
226
+ ),
227
+ FileExtension(
228
+ name="ILM OpenEXR",
229
+ extension=".exr",
230
+ priority=["EXR-FI", "pyav", "opencv"],
231
+ ),
232
+ FileExtension(
233
+ extension=".fff",
234
+ priority=["RAW-FI"],
235
+ ),
236
+ FileExtension(
237
+ name="Flexible Image Transport System File",
238
+ extension=".fit",
239
+ priority=["pillow", "FITS-PIL", "FITS"],
240
+ ),
241
+ FileExtension(
242
+ name="Flexible Image Transport System File",
243
+ extension=".fits",
244
+ priority=["pillow", "FITS-PIL", "FITS", "pyav"],
245
+ ),
246
+ FileExtension(
247
+ name="Autodesk FLC Animation",
248
+ extension=".flc",
249
+ priority=["pillow", "FLI-PIL"],
250
+ ),
251
+ FileExtension(
252
+ name="Autodesk FLI Animation",
253
+ extension=".fli",
254
+ priority=["pillow", "FLI-PIL"],
255
+ ),
256
+ FileExtension(
257
+ name="Kodak FlashPix",
258
+ extension=".fpx",
259
+ priority=["pillow", "FPX-PIL"],
260
+ ),
261
+ FileExtension(
262
+ name="Independence War 2: Edge Of Chaos Texture Format",
263
+ extension=".ftc",
264
+ priority=["pillow", "FTEX-PIL"],
265
+ ),
266
+ FileExtension(
267
+ name="Flexible Image Transport System File",
268
+ extension=".fts",
269
+ priority=["FITS"],
270
+ ),
271
+ FileExtension(
272
+ name="Independence War 2: Edge Of Chaos Texture Format",
273
+ extension=".ftu",
274
+ priority=["pillow", "FTEX-PIL"],
275
+ ),
276
+ FileExtension(
277
+ name="Flexible Image Transport System File",
278
+ extension=".fz",
279
+ priority=["FITS"],
280
+ ),
281
+ FileExtension(
282
+ name="Raw fax format CCITT G.3",
283
+ extension=".g3",
284
+ priority=["G3-FI"],
285
+ ),
286
+ FileExtension(
287
+ name="GIMP brush file",
288
+ extension=".gbr",
289
+ priority=["pillow", "GBR-PIL"],
290
+ ),
291
+ FileExtension(
292
+ name="Grassroots DICOM",
293
+ extension=".gdcm",
294
+ priority=["ITK"],
295
+ ),
296
+ FileExtension(
297
+ name="Graphics Interchange Format",
298
+ extension=".gif",
299
+ priority=["pillow", "GIF-PIL", "pyav"],
300
+ ),
301
+ FileExtension(
302
+ name="UMDS GIPL",
303
+ extension=".gipl",
304
+ priority=["ITK"],
305
+ ),
306
+ FileExtension(
307
+ name="gridded meteorological data",
308
+ extension=".grib",
309
+ priority=["pillow", "GRIB-PIL"],
310
+ ),
311
+ FileExtension(
312
+ name="Hierarchical Data Format 5",
313
+ extension=".h5",
314
+ priority=["pillow", "HDF5-PIL"],
315
+ ),
316
+ FileExtension(
317
+ name="Hierarchical Data Format 5",
318
+ extension=".hdf",
319
+ priority=["pillow", "HDF5-PIL"],
320
+ ),
321
+ FileExtension(
322
+ name="Hierarchical Data Format 5",
323
+ extension=".hdf5",
324
+ priority=["ITK"],
325
+ ),
326
+ FileExtension(
327
+ name="JPEG Extended Range",
328
+ extension=".hdp",
329
+ priority=["JPEG-XR-FI"],
330
+ ),
331
+ FileExtension(
332
+ name="High Dynamic Range Image",
333
+ extension=".hdr",
334
+ priority=["HDR-FI", "ITK", "opencv"],
335
+ ),
336
+ FileExtension(
337
+ extension=".ia",
338
+ priority=["RAW-FI"],
339
+ ),
340
+ FileExtension(
341
+ extension=".icb",
342
+ priority=["pillow"],
343
+ ),
344
+ FileExtension(
345
+ name="Mac OS Icon File",
346
+ extension=".icns",
347
+ priority=["pillow", "ICNS-PIL"],
348
+ ),
349
+ FileExtension(
350
+ name="Windows Icon File",
351
+ extension=".ico",
352
+ priority=["pillow", "ICO-FI", "ICO-PIL", "pyav"],
353
+ ),
354
+ FileExtension(
355
+ name="ILBM Interleaved Bitmap",
356
+ extension=".iff",
357
+ priority=["IFF-FI"],
358
+ ),
359
+ FileExtension(
360
+ name="IPTC/NAA",
361
+ extension=".iim",
362
+ priority=["pillow", "IPTC-PIL"],
363
+ ),
364
+ FileExtension(
365
+ extension=".iiq",
366
+ priority=["RAW-FI"],
367
+ ),
368
+ FileExtension(
369
+ name="IFUNC Image Memory",
370
+ extension=".im",
371
+ priority=["pillow", "IM-PIL"],
372
+ ),
373
+ FileExtension(
374
+ extension=".img",
375
+ priority=["ITK", "GDAL"],
376
+ ),
377
+ FileExtension(
378
+ extension=".img.gz",
379
+ priority=["ITK"],
380
+ ),
381
+ FileExtension(
382
+ name="IM Tools",
383
+ extension=".IMT",
384
+ priority=["pillow", "IMT-PIL"],
385
+ ),
386
+ FileExtension(
387
+ name="Image Processing Lab",
388
+ extension=".ipl",
389
+ priority=["ITK"],
390
+ ),
391
+ FileExtension(
392
+ name="JPEG 2000",
393
+ extension=".j2c",
394
+ priority=["pillow", "J2K-FI", "JPEG2000-PIL", "pyav"],
395
+ ),
396
+ FileExtension(
397
+ name="JPEG 2000",
398
+ extension=".j2k",
399
+ priority=["pillow", "J2K-FI", "JPEG2000-PIL", "pyav"],
400
+ ),
401
+ FileExtension(
402
+ name="JPEG",
403
+ extension=".jfif",
404
+ priority=["pillow", "JPEG-PIL"],
405
+ ),
406
+ FileExtension(
407
+ name="JPEG",
408
+ extension=".jif",
409
+ priority=["JPEG-FI"],
410
+ ),
411
+ FileExtension(
412
+ name="JPEG Network Graphics",
413
+ extension=".jng",
414
+ priority=["JNG-FI"],
415
+ ),
416
+ FileExtension(
417
+ name="JPEG 2000",
418
+ extension=".jp2",
419
+ priority=["pillow", "JP2-FI", "JPEG2000-PIL", "pyav", "opencv"],
420
+ ),
421
+ FileExtension(
422
+ name="JPEG 2000",
423
+ extension=".jpc",
424
+ priority=["pillow", "JPEG2000-PIL"],
425
+ ),
426
+ FileExtension(
427
+ name="JPEG",
428
+ extension=".jpe",
429
+ priority=["pillow", "JPEG-FI", "JPEG-PIL", "opencv"],
430
+ ),
431
+ FileExtension(
432
+ name="Joint Photographic Experts Group",
433
+ extension=".jpeg",
434
+ priority=["pillow", "JPEG-PIL", "JPEG-FI", "ITK", "GDAL", "pyav", "opencv"],
435
+ ),
436
+ FileExtension(
437
+ name="JPEG 2000",
438
+ extension=".jpf",
439
+ priority=["pillow", "JPEG2000-PIL"],
440
+ ),
441
+ FileExtension(
442
+ name="Joint Photographic Experts Group",
443
+ extension=".jpg",
444
+ priority=["pillow", "JPEG-PIL", "JPEG-FI", "ITK", "GDAL", "pyav", "opencv"],
445
+ ),
446
+ FileExtension(
447
+ name="JPEG 2000",
448
+ extension=".jpx",
449
+ priority=["pillow", "JPEG2000-PIL"],
450
+ ),
451
+ FileExtension(
452
+ name="JPEG Extended Range",
453
+ extension=".jxr",
454
+ priority=["JPEG-XR-FI"],
455
+ ),
456
+ FileExtension(
457
+ extension=".k25",
458
+ priority=["RAW-FI"],
459
+ ),
460
+ FileExtension(
461
+ extension=".kc2",
462
+ priority=["RAW-FI"],
463
+ ),
464
+ FileExtension(
465
+ extension=".kdc",
466
+ priority=["RAW-FI"],
467
+ ),
468
+ FileExtension(
469
+ name="C64 Koala Graphics",
470
+ extension=".koa",
471
+ priority=["KOALA-FI"],
472
+ ),
473
+ FileExtension(
474
+ name="ILBM Interleaved Bitmap",
475
+ extension=".lbm",
476
+ priority=["IFF-FI"],
477
+ ),
478
+ FileExtension(
479
+ name="Lytro F01",
480
+ extension=".lfp",
481
+ priority=["LYTRO-LFP"],
482
+ ),
483
+ FileExtension(
484
+ name="Lytro Illum",
485
+ extension=".lfr",
486
+ priority=["LYTRO-LFR"],
487
+ ),
488
+ FileExtension(
489
+ name="ZEISS LSM",
490
+ extension=".lsm",
491
+ priority=["ITK", "TIFF"],
492
+ ),
493
+ FileExtension(
494
+ name="McIdas area file",
495
+ extension=".MCIDAS",
496
+ priority=["pillow", "MCIDAS-PIL"],
497
+ external_link="https://www.ssec.wisc.edu/mcidas/doc/prog_man/2003print/progman2003-formats.html",
498
+ ),
499
+ FileExtension(
500
+ extension=".mdc",
501
+ priority=["RAW-FI"],
502
+ ),
503
+ FileExtension(
504
+ extension=".mef",
505
+ priority=["RAW-FI"],
506
+ ),
507
+ FileExtension(
508
+ name="FreeSurfer File Format",
509
+ extension=".mgh",
510
+ priority=["ITK"],
511
+ ),
512
+ FileExtension(
513
+ name="ITK MetaImage",
514
+ extension=".mha",
515
+ priority=["ITK"],
516
+ ),
517
+ FileExtension(
518
+ name="ITK MetaImage Header",
519
+ extension=".mhd",
520
+ priority=["ITK"],
521
+ ),
522
+ FileExtension(
523
+ name="Microsoft Image Composer",
524
+ extension=".mic",
525
+ priority=["pillow", "MIC-PIL"],
526
+ ),
527
+ FileExtension(
528
+ name="Matroska Multimedia Container",
529
+ extension=".mkv",
530
+ priority=["FFMPEG", "pyav"],
531
+ ),
532
+ FileExtension(
533
+ name="Medical Imaging NetCDF",
534
+ extension=".mnc",
535
+ priority=["ITK"],
536
+ ),
537
+ FileExtension(
538
+ name="Medical Imaging NetCDF 2",
539
+ extension=".mnc2",
540
+ priority=["ITK"],
541
+ ),
542
+ FileExtension(
543
+ name="Leaf Raw Image Format",
544
+ extension=".mos",
545
+ priority=["RAW-FI"],
546
+ ),
547
+ FileExtension(
548
+ name="QuickTime File Format",
549
+ extension=".mov",
550
+ priority=["FFMPEG", "pyav"],
551
+ ),
552
+ FileExtension(
553
+ name="MPEG-4 Part 14",
554
+ extension=".mp4",
555
+ priority=["FFMPEG", "pyav"],
556
+ ),
557
+ FileExtension(
558
+ name="MPEG-1 Moving Picture Experts Group",
559
+ extension=".mpeg",
560
+ priority=["FFMPEG", "pyav"],
561
+ ),
562
+ FileExtension(
563
+ name="Moving Picture Experts Group",
564
+ extension=".mpg",
565
+ priority=["pillow", "FFMPEG", "pyav"],
566
+ ),
567
+ FileExtension(
568
+ name="JPEG Multi-Picture Format",
569
+ extension=".mpo",
570
+ priority=["pillow", "MPO-PIL"],
571
+ ),
572
+ FileExtension(
573
+ name="Magnetic resonance imaging",
574
+ extension=".mri",
575
+ priority=["DICOM"],
576
+ ),
577
+ FileExtension(
578
+ extension=".mrw",
579
+ priority=["RAW-FI"],
580
+ ),
581
+ FileExtension(
582
+ name="Windows Paint",
583
+ extension=".msp",
584
+ priority=["pillow", "MSP-PIL"],
585
+ ),
586
+ FileExtension(
587
+ extension=".nef",
588
+ priority=["RAW-FI"],
589
+ ),
590
+ FileExtension(
591
+ extension=".nhdr",
592
+ priority=["ITK"],
593
+ ),
594
+ FileExtension(
595
+ extension=".nia",
596
+ priority=["ITK"],
597
+ ),
598
+ FileExtension(
599
+ extension=".nii",
600
+ priority=["ITK"],
601
+ ),
602
+ FileExtension(
603
+ name="nii.gz",
604
+ extension=".nii.gz",
605
+ priority=["ITK"],
606
+ ),
607
+ FileExtension(
608
+ name="Numpy Array",
609
+ extension=".npz",
610
+ priority=["NPZ"],
611
+ ),
612
+ FileExtension(
613
+ extension=".nrrd",
614
+ priority=["ITK"],
615
+ ),
616
+ FileExtension(
617
+ extension=".nrw",
618
+ priority=["RAW-FI"],
619
+ ),
620
+ FileExtension(
621
+ extension=".orf",
622
+ priority=["RAW-FI"],
623
+ ),
624
+ FileExtension(
625
+ extension=".palm",
626
+ priority=["pillow"],
627
+ ),
628
+ FileExtension(
629
+ name="Portable Bitmap",
630
+ extension=".pbm",
631
+ priority=["PGM-FI", "PGMRAW-FI", "pyav", "opencv"],
632
+ ),
633
+ FileExtension(
634
+ name="Kodak PhotoCD",
635
+ extension=".pcd",
636
+ priority=["pillow", "PCD-FI", "PCD-PIL"],
637
+ ),
638
+ FileExtension(
639
+ name="Macintosh PICT",
640
+ extension=".pct",
641
+ priority=["PICT-FI"],
642
+ ),
643
+ FileExtension(
644
+ name="Zsoft Paintbrush",
645
+ extension=".PCX",
646
+ priority=["pillow", "PCX-FI", "PCX-PIL"],
647
+ ),
648
+ FileExtension(
649
+ extension=".pdf",
650
+ priority=["pillow"],
651
+ ),
652
+ FileExtension(
653
+ extension=".pef",
654
+ priority=["RAW-FI"],
655
+ ),
656
+ FileExtension(
657
+ extension=".pfm",
658
+ priority=["PFM-FI", "pyav", "opencv"],
659
+ ),
660
+ FileExtension(
661
+ name="Portable Greymap",
662
+ extension=".pgm",
663
+ priority=["pillow", "PGM-FI", "PGMRAW-FI", "pyav", "opencv"],
664
+ ),
665
+ FileExtension(
666
+ name="Macintosh PICT",
667
+ extension=".pic",
668
+ priority=["PICT-FI", "ITK", "opencv"],
669
+ ),
670
+ FileExtension(
671
+ name="Macintosh PICT",
672
+ extension=".pict",
673
+ priority=["PICT-FI"],
674
+ ),
675
+ FileExtension(
676
+ name="Portable Network Graphics",
677
+ extension=".png",
678
+ priority=["pillow", "PNG-PIL", "PNG-FI", "ITK", "pyav", "opencv"],
679
+ ),
680
+ FileExtension(
681
+ name="Portable Image Format",
682
+ extension=".pnm",
683
+ priority=["pillow", "opencv"],
684
+ ),
685
+ FileExtension(
686
+ name="Pbmplus image",
687
+ extension=".ppm",
688
+ priority=["pillow", "PPM-PIL", "pyav"],
689
+ ),
690
+ FileExtension(
691
+ name="Pbmplus image",
692
+ extension=".pbm",
693
+ priority=["pillow", "PPM-PIL", "PPM-FI"],
694
+ ),
695
+ FileExtension(
696
+ name="Portable image format",
697
+ extension=".pxm",
698
+ priority=["opencv"],
699
+ ),
700
+ FileExtension(
701
+ name="Portable Pixelmap (ASCII)",
702
+ extension=".ppm",
703
+ priority=["PPM-FI", "opencv"],
704
+ ),
705
+ FileExtension(
706
+ name="Portable Pixelmap (Raw)",
707
+ extension=".ppm",
708
+ priority=["PPMRAW-FI"],
709
+ ),
710
+ FileExtension(
711
+ name="Ghostscript",
712
+ extension=".ps",
713
+ priority=["pillow", "EPS-PIL"],
714
+ ),
715
+ FileExtension(
716
+ name="Adope Photoshop 2.5 and 3.0",
717
+ extension=".psd",
718
+ priority=["pillow", "PSD-PIL", "PSD-FI"],
719
+ ),
720
+ FileExtension(
721
+ extension=".ptx",
722
+ priority=["RAW-FI"],
723
+ ),
724
+ FileExtension(
725
+ extension=".pxn",
726
+ priority=["RAW-FI"],
727
+ ),
728
+ FileExtension(
729
+ name="PIXAR raster image",
730
+ extension=".pxr",
731
+ priority=["pillow", "PIXAR-PIL"],
732
+ ),
733
+ FileExtension(
734
+ extension=".qtk",
735
+ priority=["RAW-FI"],
736
+ ),
737
+ FileExtension(
738
+ extension=".raf",
739
+ priority=["RAW-FI"],
740
+ ),
741
+ FileExtension(
742
+ name="Sun Raster File",
743
+ extension=".ras",
744
+ priority=["pillow", "SUN-PIL", "RAS-FI", "pyav", "opencv"],
745
+ ),
746
+ FileExtension(
747
+ name="Sun Raster File",
748
+ extension=".sr",
749
+ priority=["opencv"],
750
+ ),
751
+ FileExtension(
752
+ extension=".raw",
753
+ priority=["RAW-FI", "LYTRO-ILLUM-RAW", "LYTRO-F01-RAW"],
754
+ ),
755
+ FileExtension(
756
+ extension=".rdc",
757
+ priority=["RAW-FI"],
758
+ ),
759
+ FileExtension(
760
+ name="Silicon Graphics Image",
761
+ extension=".rgb",
762
+ priority=["pillow", "SGI-PIL"],
763
+ ),
764
+ FileExtension(
765
+ name="Silicon Graphics Image",
766
+ extension=".rgba",
767
+ priority=["pillow", "SGI-PIL"],
768
+ ),
769
+ FileExtension(
770
+ extension=".rw2",
771
+ priority=["RAW-FI"],
772
+ ),
773
+ FileExtension(
774
+ extension=".rwl",
775
+ priority=["RAW-FI"],
776
+ ),
777
+ FileExtension(
778
+ extension=".rwz",
779
+ priority=["RAW-FI"],
780
+ ),
781
+ FileExtension(
782
+ name="Silicon Graphics Image",
783
+ extension=".sgi",
784
+ priority=["pillow", "SGI-PIL", "pyav"],
785
+ ),
786
+ FileExtension(
787
+ name="SPE File Format",
788
+ extension=".spe",
789
+ priority=["SPE"],
790
+ ),
791
+ FileExtension(
792
+ extension=".SPIDER",
793
+ priority=["pillow", "SPIDER-PIL"],
794
+ ),
795
+ FileExtension(
796
+ extension=".sr2",
797
+ priority=["RAW-FI"],
798
+ ),
799
+ FileExtension(
800
+ extension=".srf",
801
+ priority=["RAW-FI"],
802
+ ),
803
+ FileExtension(
804
+ extension=".srw",
805
+ priority=["RAW-FI"],
806
+ ),
807
+ FileExtension(
808
+ extension=".sti",
809
+ priority=["RAW-FI"],
810
+ ),
811
+ FileExtension(
812
+ extension=".stk",
813
+ priority=["TIFF"],
814
+ ),
815
+ FileExtension(
816
+ name="ShockWave Flash",
817
+ extension=".swf",
818
+ priority=["SWF", "pyav"],
819
+ ),
820
+ FileExtension(
821
+ name="Truevision TGA",
822
+ extension=".targa",
823
+ priority=["pillow", "TARGA-FI"],
824
+ ),
825
+ FileExtension(
826
+ name="Truevision TGA",
827
+ extension=".tga",
828
+ priority=["pillow", "TGA-PIL", "TARGA-FI", "pyav"],
829
+ ),
830
+ FileExtension(
831
+ name="Tagged Image File",
832
+ extension=".tif",
833
+ priority=[
834
+ "TIFF",
835
+ "pillow",
836
+ "TIFF-PIL",
837
+ "TIFF-FI",
838
+ "FEI",
839
+ "ITK",
840
+ "GDAL",
841
+ "pyav",
842
+ "opencv",
843
+ ],
844
+ ),
845
+ FileExtension(
846
+ name="Tagged Image File Format",
847
+ extension=".tiff",
848
+ priority=[
849
+ "TIFF",
850
+ "pillow",
851
+ "TIFF-PIL",
852
+ "TIFF-FI",
853
+ "FEI",
854
+ "ITK",
855
+ "GDAL",
856
+ "pyav",
857
+ "opencv",
858
+ ],
859
+ ),
860
+ FileExtension(
861
+ extension=".vda",
862
+ priority=["pillow"],
863
+ ),
864
+ FileExtension(
865
+ extension=".vst",
866
+ priority=["pillow"],
867
+ ),
868
+ FileExtension(
869
+ extension=".vtk",
870
+ priority=["ITK"],
871
+ ),
872
+ FileExtension(
873
+ name="Wireless Bitmap",
874
+ extension=".wap",
875
+ priority=["WBMP-FI"],
876
+ ),
877
+ FileExtension(
878
+ name="Wireless Bitmap",
879
+ extension=".wbm",
880
+ priority=["WBMP-FI"],
881
+ ),
882
+ FileExtension(
883
+ name="Wireless Bitmap",
884
+ extension=".wbmp",
885
+ priority=["WBMP-FI"],
886
+ ),
887
+ FileExtension(
888
+ name="JPEG Extended Range",
889
+ extension=".wdp",
890
+ priority=["JPEG-XR-FI"],
891
+ ),
892
+ FileExtension(
893
+ name="Matroska",
894
+ extension=".webm",
895
+ priority=["FFMPEG", "pyav"],
896
+ ),
897
+ FileExtension(
898
+ name="Google WebP",
899
+ extension=".webp",
900
+ priority=["pillow", "WEBP-FI", "pyav", "opencv"],
901
+ ),
902
+ FileExtension(
903
+ name="Windows Meta File",
904
+ extension=".wmf",
905
+ priority=["pillow", "WMF-PIL"],
906
+ ),
907
+ FileExtension(
908
+ name="Windows Media Video",
909
+ extension=".wmv",
910
+ priority=["FFMPEG"],
911
+ ),
912
+ FileExtension(
913
+ name="X11 Bitmap",
914
+ extension=".xbm",
915
+ priority=["pillow", "XBM-PIL", "XBM-FI", "pyav"],
916
+ ),
917
+ FileExtension(
918
+ name="X11 Pixel Map",
919
+ extension=".xpm",
920
+ priority=["pillow", "XPM-PIL", "XPM-FI"],
921
+ ),
922
+ FileExtension(
923
+ name="Thumbnail Image",
924
+ extension=".XVTHUMB",
925
+ priority=["pillow", "XVTHUMB-PIL"],
926
+ ),
927
+ FileExtension(
928
+ extension=".dpx",
929
+ priority=["pyav"],
930
+ ),
931
+ FileExtension(
932
+ extension=".im1",
933
+ priority=["pyav"],
934
+ ),
935
+ FileExtension(
936
+ extension=".im24",
937
+ priority=["pyav"],
938
+ ),
939
+ FileExtension(
940
+ extension=".im8",
941
+ priority=["pyav"],
942
+ ),
943
+ FileExtension(
944
+ extension=".jls",
945
+ priority=["pyav"],
946
+ ),
947
+ FileExtension(
948
+ extension=".ljpg",
949
+ priority=["pyav"],
950
+ ),
951
+ FileExtension(
952
+ extension=".pam",
953
+ priority=["pyav"],
954
+ ),
955
+ FileExtension(
956
+ extension=".pcx",
957
+ priority=["pyav"],
958
+ ),
959
+ FileExtension(
960
+ extension=".pgmyuv",
961
+ priority=["pyav"],
962
+ ),
963
+ FileExtension(
964
+ extension=".pix",
965
+ priority=["pyav"],
966
+ ),
967
+ FileExtension(
968
+ extension=".ppm",
969
+ priority=["pyav"],
970
+ ),
971
+ FileExtension(
972
+ extension=".rs",
973
+ priority=["pyav"],
974
+ ),
975
+ FileExtension(
976
+ extension=".sun",
977
+ priority=["pyav"],
978
+ ),
979
+ FileExtension(
980
+ extension=".sunras",
981
+ priority=["pyav"],
982
+ ),
983
+ FileExtension(
984
+ extension=".xface",
985
+ priority=["pyav"],
986
+ ),
987
+ FileExtension(
988
+ extension=".xwd",
989
+ priority=["pyav"],
990
+ ),
991
+ FileExtension(
992
+ extension=".y",
993
+ priority=["pyav"],
994
+ ),
995
+ FileExtension(
996
+ name="3GP (3GPP file format)",
997
+ extension=".3g2",
998
+ priority=["pyav"],
999
+ ),
1000
+ FileExtension(
1001
+ name="3GP (3GPP file format)",
1002
+ extension=".3gp",
1003
+ priority=["pyav"],
1004
+ ),
1005
+ FileExtension(
1006
+ name="3GP (3GPP file format)",
1007
+ extension=".f4v",
1008
+ priority=["pyav"],
1009
+ ),
1010
+ FileExtension(
1011
+ name="3GP (3GPP file format)",
1012
+ extension=".ism",
1013
+ priority=["pyav"],
1014
+ ),
1015
+ FileExtension(
1016
+ name="3GP (3GPP file format)",
1017
+ extension=".isma",
1018
+ priority=["pyav"],
1019
+ ),
1020
+ FileExtension(
1021
+ name="3GP (3GPP file format)",
1022
+ extension=".ismv",
1023
+ priority=["pyav"],
1024
+ ),
1025
+ FileExtension(
1026
+ name="3GP (3GPP file format)",
1027
+ extension=".m4a",
1028
+ priority=["pyav"],
1029
+ ),
1030
+ FileExtension(
1031
+ name="3GP (3GPP file format)",
1032
+ extension=".m4b",
1033
+ priority=["pyav"],
1034
+ ),
1035
+ FileExtension(
1036
+ name="3GP (3GPP file format)",
1037
+ extension=".mj2",
1038
+ priority=["pyav"],
1039
+ ),
1040
+ FileExtension(
1041
+ name="3GP (3GPP file format)",
1042
+ extension=".psp",
1043
+ priority=["pyav"],
1044
+ ),
1045
+ FileExtension(
1046
+ name="3GP2 (3GPP2 file format)",
1047
+ extension=".3g2",
1048
+ priority=["pyav"],
1049
+ ),
1050
+ FileExtension(
1051
+ name="3GP2 (3GPP2 file format)",
1052
+ extension=".3gp",
1053
+ priority=["pyav"],
1054
+ ),
1055
+ FileExtension(
1056
+ name="3GP2 (3GPP2 file format)",
1057
+ extension=".f4v",
1058
+ priority=["pyav"],
1059
+ ),
1060
+ FileExtension(
1061
+ name="3GP2 (3GPP2 file format)",
1062
+ extension=".ism",
1063
+ priority=["pyav"],
1064
+ ),
1065
+ FileExtension(
1066
+ name="3GP2 (3GPP2 file format)",
1067
+ extension=".isma",
1068
+ priority=["pyav"],
1069
+ ),
1070
+ FileExtension(
1071
+ name="3GP2 (3GPP2 file format)",
1072
+ extension=".ismv",
1073
+ priority=["pyav"],
1074
+ ),
1075
+ FileExtension(
1076
+ name="3GP2 (3GPP2 file format)",
1077
+ extension=".m4a",
1078
+ priority=["pyav"],
1079
+ ),
1080
+ FileExtension(
1081
+ name="3GP2 (3GPP2 file format)",
1082
+ extension=".m4b",
1083
+ priority=["pyav"],
1084
+ ),
1085
+ FileExtension(
1086
+ name="3GP2 (3GPP2 file format)",
1087
+ extension=".mj2",
1088
+ priority=["pyav"],
1089
+ ),
1090
+ FileExtension(
1091
+ name="3GP2 (3GPP2 file format)",
1092
+ extension=".psp",
1093
+ priority=["pyav"],
1094
+ ),
1095
+ FileExtension(
1096
+ name="3GPP AMR",
1097
+ extension=".amr",
1098
+ priority=["pyav"],
1099
+ ),
1100
+ FileExtension(
1101
+ name="a64 - video for Commodore 64",
1102
+ extension=".A64",
1103
+ priority=["pyav"],
1104
+ ),
1105
+ FileExtension(
1106
+ name="a64 - video for Commodore 64",
1107
+ extension=".a64",
1108
+ priority=["pyav"],
1109
+ ),
1110
+ FileExtension(
1111
+ name="Adobe Filmstrip",
1112
+ extension=".flm",
1113
+ priority=["pyav"],
1114
+ ),
1115
+ FileExtension(
1116
+ name="AMV",
1117
+ extension=".amv",
1118
+ priority=["pyav"],
1119
+ ),
1120
+ FileExtension(
1121
+ name="ASF (Advanced / Active Streaming Format)",
1122
+ extension=".asf",
1123
+ priority=["pyav"],
1124
+ ),
1125
+ FileExtension(
1126
+ name="ASF (Advanced / Active Streaming Format)",
1127
+ extension=".asf",
1128
+ priority=["pyav"],
1129
+ ),
1130
+ FileExtension(
1131
+ name="ASF (Advanced / Active Streaming Format)",
1132
+ extension=".wmv",
1133
+ priority=["pyav"],
1134
+ ),
1135
+ FileExtension(
1136
+ name="ASF (Advanced / Active Streaming Format)",
1137
+ extension=".wmv",
1138
+ priority=["pyav"],
1139
+ ),
1140
+ FileExtension(
1141
+ name="AV1 Annex B",
1142
+ extension=".obu",
1143
+ priority=["pyav"],
1144
+ ),
1145
+ FileExtension(
1146
+ name="AV1 low overhead OBU",
1147
+ extension=".obu",
1148
+ priority=["pyav"],
1149
+ ),
1150
+ FileExtension(
1151
+ name="AVI (Audio Video Interleaved)",
1152
+ extension=".avi",
1153
+ priority=["pyav"],
1154
+ ),
1155
+ FileExtension(
1156
+ name="AVR (Audio Visual Research)",
1157
+ extension=".avr",
1158
+ priority=["pyav"],
1159
+ ),
1160
+ FileExtension(
1161
+ name="Beam Software SIFF",
1162
+ extension=".vb",
1163
+ priority=["pyav"],
1164
+ ),
1165
+ FileExtension(
1166
+ name="CD Graphics",
1167
+ extension=".cdg",
1168
+ priority=["pyav"],
1169
+ ),
1170
+ FileExtension(
1171
+ name="Commodore CDXL video",
1172
+ extension=".cdxl",
1173
+ priority=["pyav"],
1174
+ ),
1175
+ FileExtension(
1176
+ name="Commodore CDXL video",
1177
+ extension=".xl",
1178
+ priority=["pyav"],
1179
+ ),
1180
+ FileExtension(
1181
+ name="DASH Muxer",
1182
+ extension=".mpd",
1183
+ priority=["pyav"],
1184
+ ),
1185
+ FileExtension(
1186
+ name="Digital Pictures SGA",
1187
+ extension=".sga",
1188
+ priority=["pyav"],
1189
+ ),
1190
+ FileExtension(
1191
+ name="Discworld II BMV",
1192
+ extension=".bmv",
1193
+ priority=["pyav"],
1194
+ ),
1195
+ FileExtension(
1196
+ name="DV (Digital Video)",
1197
+ extension=".dif",
1198
+ priority=["pyav"],
1199
+ ),
1200
+ FileExtension(
1201
+ name="DV (Digital Video)",
1202
+ extension=".dv",
1203
+ priority=["pyav"],
1204
+ ),
1205
+ FileExtension(
1206
+ name="F4V Adobe Flash Video",
1207
+ extension=".f4v",
1208
+ priority=["pyav"],
1209
+ ),
1210
+ FileExtension(
1211
+ name="FLV (Flash Video)",
1212
+ extension=".flv",
1213
+ priority=["pyav"],
1214
+ ),
1215
+ FileExtension(
1216
+ name="GXF (General eXchange Format)",
1217
+ extension=".gxf",
1218
+ priority=["pyav"],
1219
+ ),
1220
+ FileExtension(
1221
+ name="iCE Draw File",
1222
+ extension=".idf",
1223
+ priority=["pyav"],
1224
+ ),
1225
+ FileExtension(
1226
+ name="IFV CCTV DVR",
1227
+ extension=".ifv",
1228
+ priority=["pyav"],
1229
+ ),
1230
+ FileExtension(
1231
+ name="iPod H.264 MP4 (MPEG-4 Part 14)",
1232
+ extension=".m4a",
1233
+ priority=["pyav"],
1234
+ ),
1235
+ FileExtension(
1236
+ name="iPod H.264 MP4 (MPEG-4 Part 14)",
1237
+ extension=".m4b",
1238
+ priority=["pyav"],
1239
+ ),
1240
+ FileExtension(
1241
+ name="iPod H.264 MP4 (MPEG-4 Part 14)",
1242
+ extension=".m4v",
1243
+ priority=["pyav"],
1244
+ ),
1245
+ FileExtension(
1246
+ name="IVR (Internet Video Recording)",
1247
+ extension=".ivr",
1248
+ priority=["pyav"],
1249
+ ),
1250
+ FileExtension(
1251
+ name="Konami PS2 SVAG",
1252
+ extension=".svag",
1253
+ priority=["pyav"],
1254
+ ),
1255
+ FileExtension(
1256
+ name="KUX (YouKu)",
1257
+ extension=".kux",
1258
+ priority=["pyav"],
1259
+ ),
1260
+ FileExtension(
1261
+ name="live RTMP FLV (Flash Video)",
1262
+ extension=".flv",
1263
+ priority=["pyav"],
1264
+ ),
1265
+ FileExtension(
1266
+ name="Loki SDL MJPEG",
1267
+ extension=".mjpg",
1268
+ priority=["pyav"],
1269
+ ),
1270
+ FileExtension(
1271
+ name="LVF",
1272
+ extension=".lvf",
1273
+ priority=["pyav"],
1274
+ ),
1275
+ FileExtension(
1276
+ name="Matroska / WebM",
1277
+ extension=".mk3d",
1278
+ priority=["pyav"],
1279
+ ),
1280
+ FileExtension(
1281
+ name="Matroska / WebM",
1282
+ extension=".mka",
1283
+ priority=["pyav"],
1284
+ ),
1285
+ FileExtension(
1286
+ name="Matroska / WebM",
1287
+ extension=".mks",
1288
+ priority=["pyav"],
1289
+ ),
1290
+ FileExtension(
1291
+ name="Microsoft XMV",
1292
+ extension=".xmv",
1293
+ priority=["pyav"],
1294
+ ),
1295
+ FileExtension(
1296
+ name="MIME multipart JPEG",
1297
+ extension=".mjpg",
1298
+ priority=["pyav"],
1299
+ ),
1300
+ FileExtension(
1301
+ name="MobiClip MODS",
1302
+ extension=".mods",
1303
+ priority=["pyav"],
1304
+ ),
1305
+ FileExtension(
1306
+ name="MobiClip MOFLEX",
1307
+ extension=".moflex",
1308
+ priority=["pyav"],
1309
+ ),
1310
+ FileExtension(
1311
+ name="Motion Pixels MVI",
1312
+ extension=".mvi",
1313
+ priority=["pyav"],
1314
+ ),
1315
+ FileExtension(
1316
+ name="MP4 (MPEG-4 Part 14)",
1317
+ extension=".3g2",
1318
+ priority=["pyav"],
1319
+ ),
1320
+ FileExtension(
1321
+ name="MP4 (MPEG-4 Part 14)",
1322
+ extension=".3gp",
1323
+ priority=["pyav"],
1324
+ ),
1325
+ FileExtension(
1326
+ name="MP4 (MPEG-4 Part 14)",
1327
+ extension=".f4v",
1328
+ priority=["pyav"],
1329
+ ),
1330
+ FileExtension(
1331
+ name="MP4 (MPEG-4 Part 14)",
1332
+ extension=".ism",
1333
+ priority=["pyav"],
1334
+ ),
1335
+ FileExtension(
1336
+ name="MP4 (MPEG-4 Part 14)",
1337
+ extension=".isma",
1338
+ priority=["pyav"],
1339
+ ),
1340
+ FileExtension(
1341
+ name="MP4 (MPEG-4 Part 14)",
1342
+ extension=".ismv",
1343
+ priority=["pyav"],
1344
+ ),
1345
+ FileExtension(
1346
+ name="MP4 (MPEG-4 Part 14)",
1347
+ extension=".m4a",
1348
+ priority=["pyav"],
1349
+ ),
1350
+ FileExtension(
1351
+ name="MP4 (MPEG-4 Part 14)",
1352
+ extension=".m4b",
1353
+ priority=["pyav"],
1354
+ ),
1355
+ FileExtension(
1356
+ name="MP4 (MPEG-4 Part 14)",
1357
+ extension=".mj2",
1358
+ priority=["pyav"],
1359
+ ),
1360
+ FileExtension(
1361
+ name="MP4 (MPEG-4 Part 14)",
1362
+ extension=".psp",
1363
+ priority=["pyav"],
1364
+ ),
1365
+ FileExtension(
1366
+ name="MPEG-2 PS (DVD VOB)",
1367
+ extension=".dvd",
1368
+ priority=["pyav"],
1369
+ ),
1370
+ FileExtension(
1371
+ name="MPEG-2 PS (SVCD)",
1372
+ extension=".vob",
1373
+ priority=["pyav"],
1374
+ ),
1375
+ FileExtension(
1376
+ name="MPEG-2 PS (VOB)",
1377
+ extension=".vob",
1378
+ priority=["pyav"],
1379
+ ),
1380
+ FileExtension(
1381
+ name="MPEG-TS (MPEG-2 Transport Stream)",
1382
+ extension=".m2t",
1383
+ priority=["pyav"],
1384
+ ),
1385
+ FileExtension(
1386
+ name="MPEG-TS (MPEG-2 Transport Stream)",
1387
+ extension=".m2ts",
1388
+ priority=["pyav"],
1389
+ ),
1390
+ FileExtension(
1391
+ name="MPEG-TS (MPEG-2 Transport Stream)",
1392
+ extension=".mts",
1393
+ priority=["pyav"],
1394
+ ),
1395
+ FileExtension(
1396
+ name="MPEG-TS (MPEG-2 Transport Stream)",
1397
+ extension=".ts",
1398
+ priority=["pyav"],
1399
+ ),
1400
+ FileExtension(
1401
+ name="Musepack",
1402
+ extension=".mpc",
1403
+ priority=["pyav"],
1404
+ ),
1405
+ FileExtension(
1406
+ name="MXF (Material eXchange Format) Operational Pattern Atom",
1407
+ extension=".mxf",
1408
+ priority=["pyav"],
1409
+ ),
1410
+ FileExtension(
1411
+ name="MXF (Material eXchange Format)",
1412
+ extension=".mxf",
1413
+ priority=["pyav"],
1414
+ ),
1415
+ FileExtension(
1416
+ name="MxPEG clip",
1417
+ extension=".mxg",
1418
+ priority=["pyav"],
1419
+ ),
1420
+ FileExtension(
1421
+ name="NC camera feed",
1422
+ extension=".v",
1423
+ priority=["pyav"],
1424
+ ),
1425
+ FileExtension(
1426
+ name="NUT",
1427
+ extension=".nut",
1428
+ priority=["pyav"],
1429
+ ),
1430
+ FileExtension(
1431
+ name="Ogg Video",
1432
+ extension=".ogv",
1433
+ priority=["pyav"],
1434
+ ),
1435
+ FileExtension(
1436
+ name="Ogg",
1437
+ extension=".ogg",
1438
+ priority=["pyav"],
1439
+ ),
1440
+ FileExtension(
1441
+ name="On2 IVF",
1442
+ extension=".ivf",
1443
+ priority=["pyav"],
1444
+ ),
1445
+ FileExtension(
1446
+ name="PSP MP4 (MPEG-4 Part 14)",
1447
+ extension=".psp",
1448
+ priority=["pyav"],
1449
+ ),
1450
+ FileExtension(
1451
+ name="Psygnosis YOP",
1452
+ extension=".yop",
1453
+ priority=["pyav"],
1454
+ ),
1455
+ FileExtension(
1456
+ name="QuickTime / MOV",
1457
+ extension=".3g2",
1458
+ priority=["pyav"],
1459
+ ),
1460
+ FileExtension(
1461
+ name="QuickTime / MOV",
1462
+ extension=".3gp",
1463
+ priority=["pyav"],
1464
+ ),
1465
+ FileExtension(
1466
+ name="QuickTime / MOV",
1467
+ extension=".f4v",
1468
+ priority=["pyav"],
1469
+ ),
1470
+ FileExtension(
1471
+ name="QuickTime / MOV",
1472
+ extension=".ism",
1473
+ priority=["pyav"],
1474
+ ),
1475
+ FileExtension(
1476
+ name="QuickTime / MOV",
1477
+ extension=".isma",
1478
+ priority=["pyav"],
1479
+ ),
1480
+ FileExtension(
1481
+ name="QuickTime / MOV",
1482
+ extension=".ismv",
1483
+ priority=["pyav"],
1484
+ ),
1485
+ FileExtension(
1486
+ name="QuickTime / MOV",
1487
+ extension=".m4a",
1488
+ priority=["pyav"],
1489
+ ),
1490
+ FileExtension(
1491
+ name="QuickTime / MOV",
1492
+ extension=".m4b",
1493
+ priority=["pyav"],
1494
+ ),
1495
+ FileExtension(
1496
+ name="QuickTime / MOV",
1497
+ extension=".mj2",
1498
+ priority=["pyav"],
1499
+ ),
1500
+ FileExtension(
1501
+ name="QuickTime / MOV",
1502
+ extension=".psp",
1503
+ priority=["pyav"],
1504
+ ),
1505
+ FileExtension(
1506
+ name="raw AVS2-P2/IEEE1857.4 video",
1507
+ extension=".avs",
1508
+ priority=["pyav"],
1509
+ ),
1510
+ FileExtension(
1511
+ name="raw AVS2-P2/IEEE1857.4 video",
1512
+ extension=".avs2",
1513
+ priority=["pyav"],
1514
+ ),
1515
+ FileExtension(
1516
+ name="raw AVS3-P2/IEEE1857.10",
1517
+ extension=".avs3",
1518
+ priority=["pyav"],
1519
+ ),
1520
+ FileExtension(
1521
+ name="raw Chinese AVS (Audio Video Standard) video",
1522
+ extension=".cavs",
1523
+ priority=["pyav"],
1524
+ ),
1525
+ FileExtension(
1526
+ name="raw Dirac",
1527
+ extension=".drc",
1528
+ priority=["pyav"],
1529
+ ),
1530
+ FileExtension(
1531
+ name="raw Dirac",
1532
+ extension=".vc2",
1533
+ priority=["pyav"],
1534
+ ),
1535
+ FileExtension(
1536
+ name="raw DNxHD (SMPTE VC-3)",
1537
+ extension=".dnxhd",
1538
+ priority=["pyav"],
1539
+ ),
1540
+ FileExtension(
1541
+ name="raw DNxHD (SMPTE VC-3)",
1542
+ extension=".dnxhr",
1543
+ priority=["pyav"],
1544
+ ),
1545
+ FileExtension(
1546
+ name="raw GSM",
1547
+ extension=".gsm",
1548
+ priority=["pyav"],
1549
+ ),
1550
+ FileExtension(
1551
+ name="raw H.261",
1552
+ extension=".h261",
1553
+ priority=["pyav"],
1554
+ ),
1555
+ FileExtension(
1556
+ name="raw H.263",
1557
+ extension=".h263",
1558
+ priority=["pyav"],
1559
+ ),
1560
+ FileExtension(
1561
+ name="raw H.264 video",
1562
+ extension=".264",
1563
+ priority=["pyav"],
1564
+ ),
1565
+ FileExtension(
1566
+ name="raw H.264 video",
1567
+ extension=".avc",
1568
+ priority=["pyav"],
1569
+ ),
1570
+ FileExtension(
1571
+ name="raw H.264 video",
1572
+ extension=".h264",
1573
+ priority=["pyav"],
1574
+ ),
1575
+ FileExtension(
1576
+ name="raw H.264 video",
1577
+ extension=".h26l",
1578
+ priority=["pyav"],
1579
+ ),
1580
+ FileExtension(
1581
+ name="raw HEVC video",
1582
+ extension=".265",
1583
+ priority=["pyav"],
1584
+ ),
1585
+ FileExtension(
1586
+ name="raw HEVC video",
1587
+ extension=".h265",
1588
+ priority=["pyav"],
1589
+ ),
1590
+ FileExtension(
1591
+ name="raw HEVC video",
1592
+ extension=".hevc",
1593
+ priority=["pyav"],
1594
+ ),
1595
+ FileExtension(
1596
+ name="raw id RoQ",
1597
+ extension=".roq",
1598
+ priority=["pyav"],
1599
+ ),
1600
+ FileExtension(
1601
+ name="raw Ingenient MJPEG",
1602
+ extension=".cgi",
1603
+ priority=["pyav"],
1604
+ ),
1605
+ FileExtension(
1606
+ name="raw IPU Video",
1607
+ extension=".ipu",
1608
+ priority=["pyav"],
1609
+ ),
1610
+ FileExtension(
1611
+ name="raw MJPEG 2000 video",
1612
+ extension=".j2k",
1613
+ priority=["pyav"],
1614
+ ),
1615
+ FileExtension(
1616
+ name="raw MJPEG video",
1617
+ extension=".mjpeg",
1618
+ priority=["pyav"],
1619
+ ),
1620
+ FileExtension(
1621
+ name="raw MJPEG video",
1622
+ extension=".mjpg",
1623
+ priority=["pyav"],
1624
+ ),
1625
+ FileExtension(
1626
+ name="raw MJPEG video",
1627
+ extension=".mpo",
1628
+ priority=["pyav"],
1629
+ ),
1630
+ FileExtension(
1631
+ name="raw MPEG-1 video",
1632
+ extension=".m1v",
1633
+ priority=["pyav"],
1634
+ ),
1635
+ FileExtension(
1636
+ name="raw MPEG-1 video",
1637
+ extension=".mpeg",
1638
+ priority=["pyav"],
1639
+ ),
1640
+ FileExtension(
1641
+ name="raw MPEG-1 video",
1642
+ extension=".mpg",
1643
+ priority=["pyav"],
1644
+ ),
1645
+ FileExtension(
1646
+ name="raw MPEG-2 video",
1647
+ extension=".m2v",
1648
+ priority=["pyav"],
1649
+ ),
1650
+ FileExtension(
1651
+ name="raw MPEG-4 video",
1652
+ extension=".m4v",
1653
+ priority=["pyav"],
1654
+ ),
1655
+ FileExtension(
1656
+ name="raw VC-1 video",
1657
+ extension=".vc1",
1658
+ priority=["pyav"],
1659
+ ),
1660
+ FileExtension(
1661
+ name="raw video",
1662
+ extension=".cif",
1663
+ priority=["pyav"],
1664
+ ),
1665
+ FileExtension(
1666
+ name="raw video",
1667
+ extension=".qcif",
1668
+ priority=["pyav"],
1669
+ ),
1670
+ FileExtension(
1671
+ name="raw video",
1672
+ extension=".rgb",
1673
+ priority=["pyav"],
1674
+ ),
1675
+ FileExtension(
1676
+ name="raw video",
1677
+ extension=".yuv",
1678
+ priority=["pyav"],
1679
+ ),
1680
+ FileExtension(
1681
+ name="RealMedia",
1682
+ extension=".rm",
1683
+ priority=["pyav"],
1684
+ ),
1685
+ FileExtension(
1686
+ name="SDR2",
1687
+ extension=".sdr2",
1688
+ priority=["pyav"],
1689
+ ),
1690
+ FileExtension(
1691
+ name="Sega FILM / CPK",
1692
+ extension=".cpk",
1693
+ priority=["pyav"],
1694
+ ),
1695
+ FileExtension(
1696
+ name="SER (Simple uncompressed video format for astronomical capturing)",
1697
+ extension=".ser",
1698
+ priority=["pyav"],
1699
+ ),
1700
+ FileExtension(
1701
+ name="Simbiosis Interactive IMX",
1702
+ extension=".imx",
1703
+ priority=["pyav"],
1704
+ ),
1705
+ FileExtension(
1706
+ name="Square SVS",
1707
+ extension=".svs",
1708
+ priority=["pyav"],
1709
+ ),
1710
+ FileExtension(
1711
+ name="TiVo TY Stream",
1712
+ extension=".ty",
1713
+ priority=["pyav"],
1714
+ ),
1715
+ FileExtension(
1716
+ name="TiVo TY Stream",
1717
+ extension=".ty+",
1718
+ priority=["pyav"],
1719
+ ),
1720
+ FileExtension(
1721
+ name="Uncompressed 4:2:2 10-bit",
1722
+ extension=".v210",
1723
+ priority=["pyav"],
1724
+ ),
1725
+ FileExtension(
1726
+ name="Uncompressed 4:2:2 10-bit",
1727
+ extension=".yuv10",
1728
+ priority=["pyav"],
1729
+ ),
1730
+ FileExtension(
1731
+ name="VC-1 test bitstream",
1732
+ extension=".rcv",
1733
+ priority=["pyav"],
1734
+ ),
1735
+ FileExtension(
1736
+ name="Video CCTV DAT",
1737
+ extension=".dat",
1738
+ priority=["pyav"],
1739
+ ),
1740
+ FileExtension(
1741
+ name="Video DAV",
1742
+ extension=".dav",
1743
+ priority=["pyav"],
1744
+ ),
1745
+ FileExtension(
1746
+ name="Vivo",
1747
+ extension=".viv",
1748
+ priority=["pyav"],
1749
+ ),
1750
+ FileExtension(
1751
+ name="WebM Chunk Muxer",
1752
+ extension=".chk",
1753
+ priority=["pyav"],
1754
+ ),
1755
+ FileExtension(
1756
+ name="WebM",
1757
+ extension=".mk3d",
1758
+ priority=["pyav"],
1759
+ ),
1760
+ FileExtension(
1761
+ name="WebM",
1762
+ extension=".mka",
1763
+ priority=["pyav"],
1764
+ ),
1765
+ FileExtension(
1766
+ name="WebM",
1767
+ extension=".mks",
1768
+ priority=["pyav"],
1769
+ ),
1770
+ FileExtension(
1771
+ name="Windows Television (WTV)",
1772
+ extension=".wtv",
1773
+ priority=["pyav"],
1774
+ ),
1775
+ FileExtension(
1776
+ name="Xilam DERF",
1777
+ extension=".adp",
1778
+ priority=["pyav"],
1779
+ ),
1780
+ FileExtension(
1781
+ name="YUV4MPEG pipe",
1782
+ extension=".y4m",
1783
+ priority=["pyav"],
1784
+ ),
1785
+ ]
1786
+ extension_list.sort(key=lambda x: x.extension)
1787
+
1788
+
1789
+ known_extensions = dict()
1790
+ for ext in extension_list:
1791
+ if ext.extension not in known_extensions:
1792
+ known_extensions[ext.extension] = list()
1793
+ known_extensions[ext.extension].append(ext)
1794
+
1795
+ extension_list = [ext for ext_list in known_extensions.values() for ext in ext_list]
1796
+
1797
+ _video_extension_strings = [
1798
+ ".264",
1799
+ ".265",
1800
+ ".3g2",
1801
+ ".3gp",
1802
+ ".a64",
1803
+ ".A64",
1804
+ ".adp",
1805
+ ".amr",
1806
+ ".amv",
1807
+ ".asf",
1808
+ ".avc",
1809
+ ".avi",
1810
+ ".avr",
1811
+ ".avs",
1812
+ ".avs2",
1813
+ ".avs3",
1814
+ ".bmv",
1815
+ ".cavs",
1816
+ ".cdg",
1817
+ ".cdxl",
1818
+ ".cgi",
1819
+ ".chk",
1820
+ ".cif",
1821
+ ".cpk",
1822
+ ".dat",
1823
+ ".dav",
1824
+ ".dif",
1825
+ ".dnxhd",
1826
+ ".dnxhr",
1827
+ ".drc",
1828
+ ".dv",
1829
+ ".dvd",
1830
+ ".f4v",
1831
+ ".flm",
1832
+ ".flv",
1833
+ ".gsm",
1834
+ ".gxf",
1835
+ ".h261",
1836
+ ".h263",
1837
+ ".h264",
1838
+ ".h265",
1839
+ ".h26l",
1840
+ ".hevc",
1841
+ ".idf",
1842
+ ".ifv",
1843
+ ".imx",
1844
+ ".ipu",
1845
+ ".ism",
1846
+ ".isma",
1847
+ ".ismv",
1848
+ ".ivf",
1849
+ ".ivr",
1850
+ ".j2k",
1851
+ ".kux",
1852
+ ".lvf",
1853
+ ".m1v",
1854
+ ".m2t",
1855
+ ".m2ts",
1856
+ ".m2v",
1857
+ ".m4a",
1858
+ ".m4b",
1859
+ ".m4v",
1860
+ ".mj2",
1861
+ ".mjpeg",
1862
+ ".mjpg",
1863
+ ".mk3d",
1864
+ ".mka",
1865
+ ".mks",
1866
+ ".mkv",
1867
+ ".mods",
1868
+ ".moflex",
1869
+ ".mov",
1870
+ ".mp4",
1871
+ ".mpc",
1872
+ ".mpd",
1873
+ ".mpeg",
1874
+ ".mpg",
1875
+ ".mpo",
1876
+ ".mts",
1877
+ ".mvi",
1878
+ ".mxf",
1879
+ ".mxg",
1880
+ ".nut",
1881
+ ".obu",
1882
+ ".ogg",
1883
+ ".ogv",
1884
+ ".psp",
1885
+ ".qcif",
1886
+ ".rcv",
1887
+ ".rgb",
1888
+ ".rm",
1889
+ ".roq",
1890
+ ".sdr2",
1891
+ ".ser",
1892
+ ".sga",
1893
+ ".svag",
1894
+ ".svs",
1895
+ ".ts",
1896
+ ".ty",
1897
+ ".ty+",
1898
+ ".v",
1899
+ ".v210",
1900
+ ".vb",
1901
+ ".vc1",
1902
+ ".vc2",
1903
+ ".viv",
1904
+ ".vob",
1905
+ ".webm",
1906
+ ".wmv",
1907
+ ".wtv",
1908
+ ".xl",
1909
+ ".xmv",
1910
+ ".y4m",
1911
+ ".yop",
1912
+ ".yuv",
1913
+ ".yuv10",
1914
+ ]
1915
+ video_extensions = list()
1916
+ for ext_string in _video_extension_strings:
1917
+ formats = known_extensions[ext_string]
1918
+ video_extensions.append(formats[0])
1919
+ video_extensions.sort(key=lambda x: x.extension)
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/config/plugins.py ADDED
@@ -0,0 +1,784 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import importlib
2
+
3
+ from ..core.legacy_plugin_wrapper import LegacyPlugin
4
+
5
+
6
+ class PluginConfig:
7
+ """Plugin Configuration Metadata
8
+
9
+ This class holds the information needed to lazy-import plugins.
10
+
11
+ Parameters
12
+ ----------
13
+ name : str
14
+ The name of the plugin.
15
+ class_name : str
16
+ The name of the plugin class inside the plugin module.
17
+ module_name : str
18
+ The name of the module/package from which to import the plugin.
19
+ is_legacy : bool
20
+ If True, this plugin is a v2 plugin and will be wrapped in a
21
+ LegacyPlugin. Default: False.
22
+ package_name : str
23
+ If the given module name points to a relative module, then the package
24
+ name determines the package it is relative to.
25
+ install_name : str
26
+ The name of the optional dependency that can be used to install this
27
+ plugin if it is missing.
28
+ legacy_args : Dict
29
+ A dictionary of kwargs to pass to the v2 plugin (Format) upon construction.
30
+
31
+ Examples
32
+ --------
33
+ >>> PluginConfig(
34
+ name="TIFF",
35
+ class_name="TiffFormat",
36
+ module_name="imageio.plugins.tifffile",
37
+ is_legacy=True,
38
+ install_name="tifffile",
39
+ legacy_args={
40
+ "description": "TIFF format",
41
+ "extensions": ".tif .tiff .stk .lsm",
42
+ "modes": "iIvV",
43
+ },
44
+ )
45
+ >>> PluginConfig(
46
+ name="pillow",
47
+ class_name="PillowPlugin",
48
+ module_name="imageio.plugins.pillow"
49
+ )
50
+
51
+ """
52
+
53
+ def __init__(
54
+ self,
55
+ name,
56
+ class_name,
57
+ module_name,
58
+ *,
59
+ is_legacy=False,
60
+ package_name=None,
61
+ install_name=None,
62
+ legacy_args=None,
63
+ ):
64
+ legacy_args = legacy_args or dict()
65
+
66
+ self.name = name
67
+ self.class_name = class_name
68
+ self.module_name = module_name
69
+ self.package_name = package_name
70
+
71
+ self.is_legacy = is_legacy
72
+ self.install_name = install_name or self.name
73
+ self.legacy_args = {"name": name, "description": "A legacy plugin"}
74
+ self.legacy_args.update(legacy_args)
75
+
76
+ @property
77
+ def format(self):
78
+ """For backwards compatibility with FormatManager
79
+
80
+ Delete when migrating to v3
81
+ """
82
+ if not self.is_legacy:
83
+ raise RuntimeError("Can only get format for legacy plugins.")
84
+
85
+ module = importlib.import_module(self.module_name, self.package_name)
86
+ clazz = getattr(module, self.class_name)
87
+ return clazz(**self.legacy_args)
88
+
89
+ @property
90
+ def plugin_class(self):
91
+ """Get the plugin class (import if needed)
92
+
93
+ Returns
94
+ -------
95
+ plugin_class : Any
96
+ The class that can be used to instantiate plugins.
97
+
98
+ """
99
+
100
+ module = importlib.import_module(self.module_name, self.package_name)
101
+ clazz = getattr(module, self.class_name)
102
+
103
+ if self.is_legacy:
104
+ legacy_plugin = clazz(**self.legacy_args)
105
+
106
+ def partial_legacy_plugin(request):
107
+ return LegacyPlugin(request, legacy_plugin)
108
+
109
+ clazz = partial_legacy_plugin
110
+
111
+ return clazz
112
+
113
+
114
+ known_plugins = dict()
115
+ known_plugins["pillow"] = PluginConfig(
116
+ name="pillow", class_name="PillowPlugin", module_name="imageio.plugins.pillow"
117
+ )
118
+ known_plugins["pyav"] = PluginConfig(
119
+ name="pyav", class_name="PyAVPlugin", module_name="imageio.plugins.pyav"
120
+ )
121
+ known_plugins["opencv"] = PluginConfig(
122
+ name="opencv", class_name="OpenCVPlugin", module_name="imageio.plugins.opencv"
123
+ )
124
+
125
+ # Legacy plugins
126
+ # ==============
127
+ #
128
+ # Which are partly registered by format, partly by plugin, and partly by a mix
129
+ # of both. We keep the naming here for backwards compatibility.
130
+ # In v3 this should become a single entry per plugin named after the plugin
131
+ # We can choose extension-specific priority in ``config.extensions``.
132
+ #
133
+ # Note: Since python 3.7 order of insertion determines the order of dict().keys()
134
+ # This means that the order here determines the order by which plugins are
135
+ # checked during the full fallback search. We don't advertise this downstream,
136
+ # but it could be a useful thing to keep in mind to choose a sensible default
137
+ # search order.
138
+
139
+ known_plugins["TIFF"] = PluginConfig(
140
+ name="TIFF",
141
+ class_name="TiffFormat",
142
+ module_name="imageio.plugins.tifffile",
143
+ is_legacy=True,
144
+ install_name="tifffile",
145
+ legacy_args={
146
+ "description": "TIFF format",
147
+ "extensions": ".tif .tiff .stk .lsm",
148
+ "modes": "iIvV",
149
+ },
150
+ )
151
+
152
+ # PILLOW plugin formats (legacy)
153
+ PILLOW_FORMATS = [
154
+ ("BMP", "Windows Bitmap", ".bmp", "PillowFormat"),
155
+ ("BUFR", "BUFR", ".bufr", "PillowFormat"),
156
+ ("CUR", "Windows Cursor", ".cur", "PillowFormat"),
157
+ ("DCX", "Intel DCX", ".dcx", "PillowFormat"),
158
+ ("DDS", "DirectDraw Surface", ".dds", "PillowFormat"),
159
+ ("DIB", "Windows Bitmap", "", "PillowFormat"),
160
+ ("EPS", "Encapsulated Postscript", ".ps .eps", "PillowFormat"),
161
+ ("FITS", "FITS", ".fit .fits", "PillowFormat"),
162
+ ("FLI", "Autodesk FLI/FLC Animation", ".fli .flc", "PillowFormat"),
163
+ ("FPX", "FlashPix", ".fpx", "PillowFormat"),
164
+ ("FTEX", "Texture File Format (IW2:EOC)", ".ftc .ftu", "PillowFormat"),
165
+ ("GBR", "GIMP brush file", ".gbr", "PillowFormat"),
166
+ ("GIF", "Compuserve GIF", ".gif", "GIFFormat"),
167
+ ("GRIB", "GRIB", ".grib", "PillowFormat"),
168
+ ("HDF5", "HDF5", ".h5 .hdf", "PillowFormat"),
169
+ ("ICNS", "Mac OS icns resource", ".icns", "PillowFormat"),
170
+ ("ICO", "Windows Icon", ".ico", "PillowFormat"),
171
+ ("IM", "IFUNC Image Memory", ".im", "PillowFormat"),
172
+ ("IMT", "IM Tools", "", "PillowFormat"),
173
+ ("IPTC", "IPTC/NAA", ".iim", "PillowFormat"),
174
+ ("JPEG", "JPEG (ISO 10918)", ".jfif .jpe .jpg .jpeg", "JPEGFormat"),
175
+ (
176
+ "JPEG2000",
177
+ "JPEG 2000 (ISO 15444)",
178
+ ".jp2 .j2k .jpc .jpf .jpx .j2c",
179
+ "JPEG2000Format",
180
+ ),
181
+ ("MCIDAS", "McIdas area file", "", "PillowFormat"),
182
+ ("MIC", "Microsoft Image Composer", ".mic", "PillowFormat"),
183
+ # skipped in legacy pillow
184
+ # ("MPEG", "MPEG", ".mpg .mpeg", "PillowFormat"),
185
+ ("MPO", "MPO (CIPA DC-007)", ".mpo", "PillowFormat"),
186
+ ("MSP", "Windows Paint", ".msp", "PillowFormat"),
187
+ ("PCD", "Kodak PhotoCD", ".pcd", "PillowFormat"),
188
+ ("PCX", "Paintbrush", ".pcx", "PillowFormat"),
189
+ ("PIXAR", "PIXAR raster image", ".pxr", "PillowFormat"),
190
+ ("PNG", "Portable network graphics", ".png", "PNGFormat"),
191
+ ("PPM", "Pbmplus image", ".pbm .pgm .ppm", "PillowFormat"),
192
+ ("PSD", "Adobe Photoshop", ".psd", "PillowFormat"),
193
+ ("SGI", "SGI Image File Format", ".bw .rgb .rgba .sgi", "PillowFormat"),
194
+ ("SPIDER", "Spider 2D image", "", "PillowFormat"),
195
+ ("SUN", "Sun Raster File", ".ras", "PillowFormat"),
196
+ ("TGA", "Targa", ".tga", "PillowFormat"),
197
+ ("TIFF", "Adobe TIFF", ".tif .tiff", "TIFFFormat"),
198
+ ("WMF", "Windows Metafile", ".wmf .emf", "PillowFormat"),
199
+ ("XBM", "X11 Bitmap", ".xbm", "PillowFormat"),
200
+ ("XPM", "X11 Pixel Map", ".xpm", "PillowFormat"),
201
+ ("XVTHUMB", "XV thumbnail image", "", "PillowFormat"),
202
+ ]
203
+ for id, summary, ext, class_name in PILLOW_FORMATS:
204
+ config = PluginConfig(
205
+ name=id.upper() + "-PIL",
206
+ class_name=class_name,
207
+ module_name="imageio.plugins.pillow_legacy",
208
+ is_legacy=True,
209
+ install_name="pillow",
210
+ legacy_args={
211
+ "description": summary + " via Pillow",
212
+ "extensions": ext,
213
+ "modes": "iI" if class_name == "GIFFormat" else "i",
214
+ "plugin_id": id,
215
+ },
216
+ )
217
+ known_plugins[config.name] = config
218
+
219
+ known_plugins["FFMPEG"] = PluginConfig(
220
+ name="FFMPEG",
221
+ class_name="FfmpegFormat",
222
+ module_name="imageio.plugins.ffmpeg",
223
+ is_legacy=True,
224
+ install_name="ffmpeg",
225
+ legacy_args={
226
+ "description": "Many video formats and cameras (via ffmpeg)",
227
+ "extensions": ".mov .avi .mpg .mpeg .mp4 .mkv .webm .wmv",
228
+ "modes": "I",
229
+ },
230
+ )
231
+
232
+ known_plugins["BSDF"] = PluginConfig(
233
+ name="BSDF",
234
+ class_name="BsdfFormat",
235
+ module_name="imageio.plugins.bsdf",
236
+ is_legacy=True,
237
+ install_name="bsdf",
238
+ legacy_args={
239
+ "description": "Format based on the Binary Structured Data Format",
240
+ "extensions": ".bsdf",
241
+ "modes": "iIvV",
242
+ },
243
+ )
244
+
245
+ known_plugins["DICOM"] = PluginConfig(
246
+ name="DICOM",
247
+ class_name="DicomFormat",
248
+ module_name="imageio.plugins.dicom",
249
+ is_legacy=True,
250
+ install_name="dicom",
251
+ legacy_args={
252
+ "description": "Digital Imaging and Communications in Medicine",
253
+ "extensions": ".dcm .ct .mri",
254
+ "modes": "iIvV",
255
+ },
256
+ )
257
+
258
+ known_plugins["FEI"] = PluginConfig(
259
+ name="FEI",
260
+ class_name="FEISEMFormat",
261
+ module_name="imageio.plugins.feisem",
262
+ is_legacy=True,
263
+ install_name="feisem",
264
+ legacy_args={
265
+ "description": "FEI-SEM TIFF format",
266
+ "extensions": [".tif", ".tiff"],
267
+ "modes": "iv",
268
+ },
269
+ )
270
+
271
+ known_plugins["FITS"] = PluginConfig(
272
+ name="FITS",
273
+ class_name="FitsFormat",
274
+ module_name="imageio.plugins.fits",
275
+ is_legacy=True,
276
+ install_name="fits",
277
+ legacy_args={
278
+ "description": "Flexible Image Transport System (FITS) format",
279
+ "extensions": ".fits .fit .fts .fz",
280
+ "modes": "iIvV",
281
+ },
282
+ )
283
+
284
+ known_plugins["GDAL"] = PluginConfig(
285
+ name="GDAL",
286
+ class_name="GdalFormat",
287
+ module_name="imageio.plugins.gdal",
288
+ is_legacy=True,
289
+ install_name="gdal",
290
+ legacy_args={
291
+ "description": "Geospatial Data Abstraction Library",
292
+ "extensions": ".tiff .tif .img .ecw .jpg .jpeg",
293
+ "modes": "iIvV",
294
+ },
295
+ )
296
+
297
+ known_plugins["ITK"] = PluginConfig(
298
+ name="ITK",
299
+ class_name="ItkFormat",
300
+ module_name="imageio.plugins.simpleitk",
301
+ is_legacy=True,
302
+ install_name="simpleitk",
303
+ legacy_args={
304
+ "description": "Insight Segmentation and Registration Toolkit (ITK) format",
305
+ "extensions": " ".join(
306
+ (
307
+ ".gipl",
308
+ ".ipl",
309
+ ".mha",
310
+ ".mhd",
311
+ ".nhdr",
312
+ ".nia",
313
+ ".hdr",
314
+ ".nrrd",
315
+ ".nii",
316
+ ".nii.gz",
317
+ ".img",
318
+ ".img.gz",
319
+ ".vtk",
320
+ ".hdf5",
321
+ ".lsm",
322
+ ".mnc",
323
+ ".mnc2",
324
+ ".mgh",
325
+ ".mnc",
326
+ ".pic",
327
+ ".bmp",
328
+ ".jpeg",
329
+ ".jpg",
330
+ ".png",
331
+ ".tiff",
332
+ ".tif",
333
+ ".dicom",
334
+ ".dcm",
335
+ ".gdcm",
336
+ )
337
+ ),
338
+ "modes": "iIvV",
339
+ },
340
+ )
341
+
342
+ known_plugins["NPZ"] = PluginConfig(
343
+ name="NPZ",
344
+ class_name="NpzFormat",
345
+ module_name="imageio.plugins.npz",
346
+ is_legacy=True,
347
+ install_name="numpy",
348
+ legacy_args={
349
+ "description": "Numpy's compressed array format",
350
+ "extensions": ".npz",
351
+ "modes": "iIvV",
352
+ },
353
+ )
354
+
355
+ known_plugins["SPE"] = PluginConfig(
356
+ name="SPE",
357
+ class_name="SpeFormat",
358
+ module_name="imageio.plugins.spe",
359
+ is_legacy=True,
360
+ install_name="spe",
361
+ legacy_args={
362
+ "description": "SPE file format",
363
+ "extensions": ".spe",
364
+ "modes": "iIvV",
365
+ },
366
+ )
367
+
368
+ known_plugins["SWF"] = PluginConfig(
369
+ name="SWF",
370
+ class_name="SWFFormat",
371
+ module_name="imageio.plugins.swf",
372
+ is_legacy=True,
373
+ install_name="swf",
374
+ legacy_args={
375
+ "description": "Shockwave flash",
376
+ "extensions": ".swf",
377
+ "modes": "I",
378
+ },
379
+ )
380
+
381
+ known_plugins["SCREENGRAB"] = PluginConfig(
382
+ name="SCREENGRAB",
383
+ class_name="ScreenGrabFormat",
384
+ module_name="imageio.plugins.grab",
385
+ is_legacy=True,
386
+ install_name="pillow",
387
+ legacy_args={
388
+ "description": "Grab screenshots (Windows and OS X only)",
389
+ "extensions": [],
390
+ "modes": "i",
391
+ },
392
+ )
393
+
394
+ known_plugins["CLIPBOARDGRAB"] = PluginConfig(
395
+ name="CLIPBOARDGRAB",
396
+ class_name="ClipboardGrabFormat",
397
+ module_name="imageio.plugins.grab",
398
+ is_legacy=True,
399
+ install_name="pillow",
400
+ legacy_args={
401
+ "description": "Grab from clipboard (Windows only)",
402
+ "extensions": [],
403
+ "modes": "i",
404
+ },
405
+ )
406
+
407
+ # LYTRO plugin (legacy)
408
+ lytro_formats = [
409
+ ("lytro-lfr", "Lytro Illum lfr image file", ".lfr", "i", "LytroLfrFormat"),
410
+ (
411
+ "lytro-illum-raw",
412
+ "Lytro Illum raw image file",
413
+ ".raw",
414
+ "i",
415
+ "LytroIllumRawFormat",
416
+ ),
417
+ ("lytro-lfp", "Lytro F01 lfp image file", ".lfp", "i", "LytroLfpFormat"),
418
+ ("lytro-f01-raw", "Lytro F01 raw image file", ".raw", "i", "LytroF01RawFormat"),
419
+ ]
420
+ for name, des, ext, mode, class_name in lytro_formats:
421
+ config = PluginConfig(
422
+ name=name.upper(),
423
+ class_name=class_name,
424
+ module_name="imageio.plugins.lytro",
425
+ is_legacy=True,
426
+ install_name="lytro",
427
+ legacy_args={
428
+ "description": des,
429
+ "extensions": ext,
430
+ "modes": mode,
431
+ },
432
+ )
433
+ known_plugins[config.name] = config
434
+
435
+ # FreeImage plugin (legacy)
436
+ FREEIMAGE_FORMATS = [
437
+ (
438
+ "BMP",
439
+ 0,
440
+ "Windows or OS/2 Bitmap",
441
+ ".bmp",
442
+ "i",
443
+ "FreeimageBmpFormat",
444
+ "imageio.plugins.freeimage",
445
+ ),
446
+ (
447
+ "CUT",
448
+ 21,
449
+ "Dr. Halo",
450
+ ".cut",
451
+ "i",
452
+ "FreeimageFormat",
453
+ "imageio.plugins.freeimage",
454
+ ),
455
+ (
456
+ "DDS",
457
+ 24,
458
+ "DirectX Surface",
459
+ ".dds",
460
+ "i",
461
+ "FreeimageFormat",
462
+ "imageio.plugins.freeimage",
463
+ ),
464
+ (
465
+ "EXR",
466
+ 29,
467
+ "ILM OpenEXR",
468
+ ".exr",
469
+ "i",
470
+ "FreeimageFormat",
471
+ "imageio.plugins.freeimage",
472
+ ),
473
+ (
474
+ "G3",
475
+ 27,
476
+ "Raw fax format CCITT G.3",
477
+ ".g3",
478
+ "i",
479
+ "FreeimageFormat",
480
+ "imageio.plugins.freeimage",
481
+ ),
482
+ (
483
+ "GIF",
484
+ 25,
485
+ "Static and animated gif (FreeImage)",
486
+ ".gif",
487
+ "iI",
488
+ "GifFormat",
489
+ "imageio.plugins.freeimagemulti",
490
+ ),
491
+ (
492
+ "HDR",
493
+ 26,
494
+ "High Dynamic Range Image",
495
+ ".hdr",
496
+ "i",
497
+ "FreeimageFormat",
498
+ "imageio.plugins.freeimage",
499
+ ),
500
+ (
501
+ "ICO",
502
+ 1,
503
+ "Windows Icon",
504
+ ".ico",
505
+ "iI",
506
+ "IcoFormat",
507
+ "imageio.plugins.freeimagemulti",
508
+ ),
509
+ (
510
+ "IFF",
511
+ 5,
512
+ "IFF Interleaved Bitmap",
513
+ ".iff .lbm",
514
+ "i",
515
+ "FreeimageFormat",
516
+ "imageio.plugins.freeimage",
517
+ ),
518
+ (
519
+ "J2K",
520
+ 30,
521
+ "JPEG-2000 codestream",
522
+ ".j2k .j2c",
523
+ "i",
524
+ "FreeimageFormat",
525
+ "imageio.plugins.freeimage",
526
+ ),
527
+ (
528
+ "JNG",
529
+ 3,
530
+ "JPEG Network Graphics",
531
+ ".jng",
532
+ "i",
533
+ "FreeimageFormat",
534
+ "imageio.plugins.freeimage",
535
+ ),
536
+ (
537
+ "JP2",
538
+ 31,
539
+ "JPEG-2000 File Format",
540
+ ".jp2",
541
+ "i",
542
+ "FreeimageFormat",
543
+ "imageio.plugins.freeimage",
544
+ ),
545
+ (
546
+ "JPEG",
547
+ 2,
548
+ "JPEG - JFIF Compliant",
549
+ ".jpg .jif .jpeg .jpe",
550
+ "i",
551
+ "FreeimageJpegFormat",
552
+ "imageio.plugins.freeimage",
553
+ ),
554
+ (
555
+ "JPEG-XR",
556
+ 36,
557
+ "JPEG XR image format",
558
+ ".jxr .wdp .hdp",
559
+ "i",
560
+ "FreeimageFormat",
561
+ "imageio.plugins.freeimage",
562
+ ),
563
+ (
564
+ "KOALA",
565
+ 4,
566
+ "C64 Koala Graphics",
567
+ ".koa",
568
+ "i",
569
+ "FreeimageFormat",
570
+ "imageio.plugins.freeimage",
571
+ ),
572
+ # not registered in legacy pillow
573
+ # ("MNG", 6, "Multiple-image Network Graphics", ".mng", "i", "FreeimageFormat", "imageio.plugins.freeimage"),
574
+ (
575
+ "PBM",
576
+ 7,
577
+ "Portable Bitmap (ASCII)",
578
+ ".pbm",
579
+ "i",
580
+ "FreeimageFormat",
581
+ "imageio.plugins.freeimage",
582
+ ),
583
+ (
584
+ "PBMRAW",
585
+ 8,
586
+ "Portable Bitmap (RAW)",
587
+ ".pbm",
588
+ "i",
589
+ "FreeimageFormat",
590
+ "imageio.plugins.freeimage",
591
+ ),
592
+ (
593
+ "PCD",
594
+ 9,
595
+ "Kodak PhotoCD",
596
+ ".pcd",
597
+ "i",
598
+ "FreeimageFormat",
599
+ "imageio.plugins.freeimage",
600
+ ),
601
+ (
602
+ "PCX",
603
+ 10,
604
+ "Zsoft Paintbrush",
605
+ ".pcx",
606
+ "i",
607
+ "FreeimageFormat",
608
+ "imageio.plugins.freeimage",
609
+ ),
610
+ (
611
+ "PFM",
612
+ 32,
613
+ "Portable floatmap",
614
+ ".pfm",
615
+ "i",
616
+ "FreeimageFormat",
617
+ "imageio.plugins.freeimage",
618
+ ),
619
+ (
620
+ "PGM",
621
+ 11,
622
+ "Portable Greymap (ASCII)",
623
+ ".pgm",
624
+ "i",
625
+ "FreeimageFormat",
626
+ "imageio.plugins.freeimage",
627
+ ),
628
+ (
629
+ "PGMRAW",
630
+ 12,
631
+ "Portable Greymap (RAW)",
632
+ ".pgm",
633
+ "i",
634
+ "FreeimageFormat",
635
+ "imageio.plugins.freeimage",
636
+ ),
637
+ (
638
+ "PICT",
639
+ 33,
640
+ "Macintosh PICT",
641
+ ".pct .pict .pic",
642
+ "i",
643
+ "FreeimageFormat",
644
+ "imageio.plugins.freeimage",
645
+ ),
646
+ (
647
+ "PNG",
648
+ 13,
649
+ "Portable Network Graphics",
650
+ ".png",
651
+ "i",
652
+ "FreeimagePngFormat",
653
+ "imageio.plugins.freeimage",
654
+ ),
655
+ (
656
+ "PPM",
657
+ 14,
658
+ "Portable Pixelmap (ASCII)",
659
+ ".ppm",
660
+ "i",
661
+ "FreeimagePnmFormat",
662
+ "imageio.plugins.freeimage",
663
+ ),
664
+ (
665
+ "PPMRAW",
666
+ 15,
667
+ "Portable Pixelmap (RAW)",
668
+ ".ppm",
669
+ "i",
670
+ "FreeimagePnmFormat",
671
+ "imageio.plugins.freeimage",
672
+ ),
673
+ (
674
+ "PSD",
675
+ 20,
676
+ "Adobe Photoshop",
677
+ ".psd",
678
+ "i",
679
+ "FreeimageFormat",
680
+ "imageio.plugins.freeimage",
681
+ ),
682
+ (
683
+ "RAS",
684
+ 16,
685
+ "Sun Raster Image",
686
+ ".ras",
687
+ "i",
688
+ "FreeimageFormat",
689
+ "imageio.plugins.freeimage",
690
+ ),
691
+ (
692
+ "RAW",
693
+ 34,
694
+ "RAW camera image",
695
+ ".3fr .arw .bay .bmq .cap .cine .cr2 .crw .cs1 .dc2 "
696
+ ".dcr .drf .dsc .dng .erf .fff .ia .iiq .k25 .kc2 .kdc .mdc .mef .mos .mrw .nef .nrw .orf "
697
+ ".pef .ptx .pxn .qtk .raf .raw .rdc .rw2 .rwl .rwz .sr2 .srf .srw .sti",
698
+ "i",
699
+ "FreeimageFormat",
700
+ "imageio.plugins.freeimage",
701
+ ),
702
+ (
703
+ "SGI",
704
+ 28,
705
+ "SGI Image Format",
706
+ ".sgi .rgb .rgba .bw",
707
+ "i",
708
+ "FreeimageFormat",
709
+ "imageio.plugins.freeimage",
710
+ ),
711
+ (
712
+ "TARGA",
713
+ 17,
714
+ "Truevision Targa",
715
+ ".tga .targa",
716
+ "i",
717
+ "FreeimageFormat",
718
+ "imageio.plugins.freeimage",
719
+ ),
720
+ (
721
+ "TIFF",
722
+ 18,
723
+ "Tagged Image File Format",
724
+ ".tif .tiff",
725
+ "i",
726
+ "FreeimageFormat",
727
+ "imageio.plugins.freeimage",
728
+ ),
729
+ (
730
+ "WBMP",
731
+ 19,
732
+ "Wireless Bitmap",
733
+ ".wap .wbmp .wbm",
734
+ "i",
735
+ "FreeimageFormat",
736
+ "imageio.plugins.freeimage",
737
+ ),
738
+ (
739
+ "WebP",
740
+ 35,
741
+ "Google WebP image format",
742
+ ".webp",
743
+ "i",
744
+ "FreeimageFormat",
745
+ "imageio.plugins.freeimage",
746
+ ),
747
+ (
748
+ "XBM",
749
+ 22,
750
+ "X11 Bitmap Format",
751
+ ".xbm",
752
+ "i",
753
+ "FreeimageFormat",
754
+ "imageio.plugins.freeimage",
755
+ ),
756
+ (
757
+ "XPM",
758
+ 23,
759
+ "X11 Pixmap Format",
760
+ ".xpm",
761
+ "i",
762
+ "FreeimageFormat",
763
+ "imageio.plugins.freeimage",
764
+ ),
765
+ ]
766
+ for name, i, des, ext, mode, class_name, module_name in FREEIMAGE_FORMATS:
767
+ config = PluginConfig(
768
+ name=name.upper() + "-FI",
769
+ class_name=class_name,
770
+ module_name=module_name,
771
+ is_legacy=True,
772
+ install_name="freeimage",
773
+ legacy_args={
774
+ "description": des,
775
+ "extensions": ext,
776
+ "modes": mode,
777
+ "fif": i,
778
+ },
779
+ )
780
+ known_plugins[config.name] = config
781
+
782
+ # exists for backwards compatibility with FormatManager
783
+ # delete in V3
784
+ _original_order = [x for x, config in known_plugins.items() if config.is_legacy]
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/core/__init__.py ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ # Distributed under the (new) BSD License. See LICENSE.txt for more info.
3
+
4
+ """ This subpackage provides the core functionality of imageio
5
+ (everything but the plugins).
6
+ """
7
+
8
+ # flake8: noqa
9
+
10
+ from .util import Image, Array, Dict, asarray, image_as_uint, urlopen
11
+ from .util import BaseProgressIndicator, StdoutProgressIndicator, IS_PYPY
12
+ from .util import get_platform, appdata_dir, resource_dirs, has_module
13
+ from .findlib import load_lib
14
+ from .fetching import get_remote_file, InternetNotAllowedError, NeedDownloadError
15
+ from .request import Request, read_n_bytes, RETURN_BYTES
16
+ from .format import Format, FormatManager
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/core/__pycache__/__init__.cpython-38.pyc ADDED
Binary file (890 Bytes). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/core/__pycache__/legacy_plugin_wrapper.cpython-38.pyc ADDED
Binary file (9.67 kB). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/core/__pycache__/request.cpython-38.pyc ADDED
Binary file (19.8 kB). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/core/findlib.py ADDED
@@ -0,0 +1,161 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright (c) 2015-1018, imageio contributors
3
+ # Copyright (C) 2013, Zach Pincus, Almar Klein and others
4
+
5
+ """ This module contains generic code to find and load a dynamic library.
6
+ """
7
+
8
+ import os
9
+ import sys
10
+ import ctypes
11
+
12
+
13
+ LOCALDIR = os.path.abspath(os.path.dirname(__file__))
14
+
15
+ # Flag that can be patched / set to True to disable loading non-system libs
16
+ SYSTEM_LIBS_ONLY = False
17
+
18
+
19
+ def looks_lib(fname):
20
+ """Returns True if the given filename looks like a dynamic library.
21
+ Based on extension, but cross-platform and more flexible.
22
+ """
23
+ fname = fname.lower()
24
+ if sys.platform.startswith("win"):
25
+ return fname.endswith(".dll")
26
+ elif sys.platform.startswith("darwin"):
27
+ return fname.endswith(".dylib")
28
+ else:
29
+ return fname.endswith(".so") or ".so." in fname
30
+
31
+
32
+ def generate_candidate_libs(lib_names, lib_dirs=None):
33
+ """Generate a list of candidate filenames of what might be the dynamic
34
+ library corresponding with the given list of names.
35
+ Returns (lib_dirs, lib_paths)
36
+ """
37
+ lib_dirs = lib_dirs or []
38
+
39
+ # Get system dirs to search
40
+ sys_lib_dirs = [
41
+ "/lib",
42
+ "/usr/lib",
43
+ "/usr/lib/x86_64-linux-gnu",
44
+ "/usr/lib/aarch64-linux-gnu",
45
+ "/usr/local/lib",
46
+ "/opt/local/lib",
47
+ ]
48
+
49
+ # Get Python dirs to search (shared if for Pyzo)
50
+ py_sub_dirs = ["bin", "lib", "DLLs", "Library/bin", "shared"]
51
+ py_lib_dirs = [os.path.join(sys.prefix, d) for d in py_sub_dirs]
52
+ if hasattr(sys, "base_prefix"):
53
+ py_lib_dirs += [os.path.join(sys.base_prefix, d) for d in py_sub_dirs]
54
+
55
+ # Get user dirs to search (i.e. HOME)
56
+ home_dir = os.path.expanduser("~")
57
+ user_lib_dirs = [os.path.join(home_dir, d) for d in ["lib"]]
58
+
59
+ # Select only the dirs for which a directory exists, and remove duplicates
60
+ potential_lib_dirs = lib_dirs + sys_lib_dirs + py_lib_dirs + user_lib_dirs
61
+ lib_dirs = []
62
+ for ld in potential_lib_dirs:
63
+ if os.path.isdir(ld) and ld not in lib_dirs:
64
+ lib_dirs.append(ld)
65
+
66
+ # Now attempt to find libraries of that name in the given directory
67
+ # (case-insensitive)
68
+ lib_paths = []
69
+ for lib_dir in lib_dirs:
70
+ # Get files, prefer short names, last version
71
+ files = os.listdir(lib_dir)
72
+ files = reversed(sorted(files))
73
+ files = sorted(files, key=len)
74
+ for lib_name in lib_names:
75
+ # Test all filenames for name and ext
76
+ for fname in files:
77
+ if fname.lower().startswith(lib_name) and looks_lib(fname):
78
+ lib_paths.append(os.path.join(lib_dir, fname))
79
+
80
+ # Return (only the items which are files)
81
+ lib_paths = [lp for lp in lib_paths if os.path.isfile(lp)]
82
+ return lib_dirs, lib_paths
83
+
84
+
85
+ def load_lib(exact_lib_names, lib_names, lib_dirs=None):
86
+ """load_lib(exact_lib_names, lib_names, lib_dirs=None)
87
+
88
+ Load a dynamic library.
89
+
90
+ This function first tries to load the library from the given exact
91
+ names. When that fails, it tries to find the library in common
92
+ locations. It searches for files that start with one of the names
93
+ given in lib_names (case insensitive). The search is performed in
94
+ the given lib_dirs and a set of common library dirs.
95
+
96
+ Returns ``(ctypes_library, library_path)``
97
+ """
98
+
99
+ # Checks
100
+ assert isinstance(exact_lib_names, list)
101
+ assert isinstance(lib_names, list)
102
+ if lib_dirs is not None:
103
+ assert isinstance(lib_dirs, list)
104
+ exact_lib_names = [n for n in exact_lib_names if n]
105
+ lib_names = [n for n in lib_names if n]
106
+
107
+ # Get reference name (for better messages)
108
+ if lib_names:
109
+ the_lib_name = lib_names[0]
110
+ elif exact_lib_names:
111
+ the_lib_name = exact_lib_names[0]
112
+ else:
113
+ raise ValueError("No library name given.")
114
+
115
+ # Collect filenames of potential libraries
116
+ # First try a few bare library names that ctypes might be able to find
117
+ # in the default locations for each platform.
118
+ if SYSTEM_LIBS_ONLY:
119
+ lib_dirs, lib_paths = [], []
120
+ else:
121
+ lib_dirs, lib_paths = generate_candidate_libs(lib_names, lib_dirs)
122
+ lib_paths = exact_lib_names + lib_paths
123
+
124
+ # Select loader
125
+ if sys.platform.startswith("win"):
126
+ loader = ctypes.windll
127
+ else:
128
+ loader = ctypes.cdll
129
+
130
+ # Try to load until success
131
+ the_lib = None
132
+ errors = []
133
+ for fname in lib_paths:
134
+ try:
135
+ the_lib = loader.LoadLibrary(fname)
136
+ break
137
+ except Exception as err:
138
+ # Don't record errors when it couldn't load the library from an
139
+ # exact name -- this fails often, and doesn't provide any useful
140
+ # debugging information anyway, beyond "couldn't find library..."
141
+ if fname not in exact_lib_names:
142
+ errors.append((fname, err))
143
+
144
+ # No success ...
145
+ if the_lib is None:
146
+ if errors:
147
+ # No library loaded, and load-errors reported for some
148
+ # candidate libs
149
+ err_txt = ["%s:\n%s" % (lib, str(e)) for lib, e in errors]
150
+ msg = (
151
+ "One or more %s libraries were found, but "
152
+ + "could not be loaded due to the following errors:\n%s"
153
+ )
154
+ raise OSError(msg % (the_lib_name, "\n\n".join(err_txt)))
155
+ else:
156
+ # No errors, because no potential libraries found at all!
157
+ msg = "Could not find a %s library in any of:\n%s"
158
+ raise OSError(msg % (the_lib_name, "\n".join(lib_dirs)))
159
+
160
+ # Done
161
+ return the_lib, fname
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/core/format.py ADDED
@@ -0,0 +1,856 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ # imageio is distributed under the terms of the (new) BSD License.
3
+
4
+ """
5
+
6
+ .. note::
7
+ imageio is under construction, some details with regard to the
8
+ Reader and Writer classes may change.
9
+
10
+ These are the main classes of imageio. They expose an interface for
11
+ advanced users and plugin developers. A brief overview:
12
+
13
+ * imageio.FormatManager - for keeping track of registered formats.
14
+ * imageio.Format - representation of a file format reader/writer
15
+ * imageio.Format.Reader - object used during the reading of a file.
16
+ * imageio.Format.Writer - object used during saving a file.
17
+ * imageio.Request - used to store the filename and other info.
18
+
19
+ Plugins need to implement a Format class and register
20
+ a format object using ``imageio.formats.add_format()``.
21
+
22
+ """
23
+
24
+ # todo: do we even use the known extensions?
25
+
26
+ # Some notes:
27
+ #
28
+ # The classes in this module use the Request object to pass filename and
29
+ # related info around. This request object is instantiated in
30
+ # imageio.get_reader and imageio.get_writer.
31
+
32
+ import sys
33
+ import warnings
34
+
35
+ import numpy as np
36
+ from pathlib import Path
37
+
38
+ from . import Array, asarray
39
+ from .request import ImageMode
40
+ from ..config import known_plugins, known_extensions, PluginConfig, FileExtension
41
+ from ..config.plugins import _original_order
42
+ from .imopen import imopen
43
+
44
+
45
+ # survived for backwards compatibility
46
+ # I don't know if external plugin code depends on it existing
47
+ # We no longer do
48
+ MODENAMES = ImageMode
49
+
50
+
51
+ def _get_config(plugin):
52
+ """Old Plugin resolution logic.
53
+
54
+ Remove once we remove the old format manager.
55
+ """
56
+
57
+ extension_name = None
58
+
59
+ if Path(plugin).suffix.lower() in known_extensions:
60
+ extension_name = Path(plugin).suffix.lower()
61
+ elif plugin in known_plugins:
62
+ pass
63
+ elif plugin.lower() in known_extensions:
64
+ extension_name = plugin.lower()
65
+ elif "." + plugin.lower() in known_extensions:
66
+ extension_name = "." + plugin.lower()
67
+ else:
68
+ raise IndexError(f"No format known by name `{plugin}`.")
69
+
70
+ if extension_name is not None:
71
+ for plugin_name in [
72
+ x
73
+ for file_extension in known_extensions[extension_name]
74
+ for x in file_extension.priority
75
+ ]:
76
+ if known_plugins[plugin_name].is_legacy:
77
+ plugin = plugin_name
78
+ break
79
+
80
+ return known_plugins[plugin]
81
+
82
+
83
+ class Format(object):
84
+ """Represents an implementation to read/write a particular file format
85
+
86
+ A format instance is responsible for 1) providing information about
87
+ a format; 2) determining whether a certain file can be read/written
88
+ with this format; 3) providing a reader/writer class.
89
+
90
+ Generally, imageio will select the right format and use that to
91
+ read/write an image. A format can also be explicitly chosen in all
92
+ read/write functions. Use ``print(format)``, or ``help(format_name)``
93
+ to see its documentation.
94
+
95
+ To implement a specific format, one should create a subclass of
96
+ Format and the Format.Reader and Format.Writer classes. See
97
+ :class:`imageio.plugins` for details.
98
+
99
+ Parameters
100
+ ----------
101
+ name : str
102
+ A short name of this format. Users can select a format using its name.
103
+ description : str
104
+ A one-line description of the format.
105
+ extensions : str | list | None
106
+ List of filename extensions that this format supports. If a
107
+ string is passed it should be space or comma separated. The
108
+ extensions are used in the documentation and to allow users to
109
+ select a format by file extension. It is not used to determine
110
+ what format to use for reading/saving a file.
111
+ modes : str
112
+ A string containing the modes that this format can handle ('iIvV'),
113
+ “i” for an image, “I” for multiple images, “v” for a volume,
114
+ “V” for multiple volumes.
115
+ This attribute is used in the documentation and to select the
116
+ formats when reading/saving a file.
117
+ """
118
+
119
+ def __init__(self, name, description, extensions=None, modes=None):
120
+ """Initialize the Plugin.
121
+
122
+ Parameters
123
+ ----------
124
+ name : str
125
+ A short name of this format. Users can select a format using its name.
126
+ description : str
127
+ A one-line description of the format.
128
+ extensions : str | list | None
129
+ List of filename extensions that this format supports. If a
130
+ string is passed it should be space or comma separated. The
131
+ extensions are used in the documentation and to allow users to
132
+ select a format by file extension. It is not used to determine
133
+ what format to use for reading/saving a file.
134
+ modes : str
135
+ A string containing the modes that this format can handle ('iIvV'),
136
+ “i” for an image, “I” for multiple images, “v” for a volume,
137
+ “V” for multiple volumes.
138
+ This attribute is used in the documentation and to select the
139
+ formats when reading/saving a file.
140
+ """
141
+
142
+ # Store name and description
143
+ self._name = name.upper()
144
+ self._description = description
145
+
146
+ # Store extensions, do some effort to normalize them.
147
+ # They are stored as a list of lowercase strings without leading dots.
148
+ if extensions is None:
149
+ extensions = []
150
+ elif isinstance(extensions, str):
151
+ extensions = extensions.replace(",", " ").split(" ")
152
+ #
153
+ if isinstance(extensions, (tuple, list)):
154
+ self._extensions = tuple(
155
+ ["." + e.strip(".").lower() for e in extensions if e]
156
+ )
157
+ else:
158
+ raise ValueError("Invalid value for extensions given.")
159
+
160
+ # Store mode
161
+ self._modes = modes or ""
162
+ if not isinstance(self._modes, str):
163
+ raise ValueError("Invalid value for modes given.")
164
+ for m in self._modes:
165
+ if m not in "iIvV?":
166
+ raise ValueError("Invalid value for mode given.")
167
+
168
+ def __repr__(self):
169
+ # Short description
170
+ return "<Format %s - %s>" % (self.name, self.description)
171
+
172
+ def __str__(self):
173
+ return self.doc
174
+
175
+ @property
176
+ def doc(self):
177
+ """The documentation for this format (name + description + docstring)."""
178
+ # Our docsring is assumed to be indented by four spaces. The
179
+ # first line needs special attention.
180
+ return "%s - %s\n\n %s\n" % (
181
+ self.name,
182
+ self.description,
183
+ self.__doc__.strip(),
184
+ )
185
+
186
+ @property
187
+ def name(self):
188
+ """The name of this format."""
189
+ return self._name
190
+
191
+ @property
192
+ def description(self):
193
+ """A short description of this format."""
194
+ return self._description
195
+
196
+ @property
197
+ def extensions(self):
198
+ """A list of file extensions supported by this plugin.
199
+ These are all lowercase with a leading dot.
200
+ """
201
+ return self._extensions
202
+
203
+ @property
204
+ def modes(self):
205
+ """A string specifying the modes that this format can handle."""
206
+ return self._modes
207
+
208
+ def get_reader(self, request):
209
+ """get_reader(request)
210
+
211
+ Return a reader object that can be used to read data and info
212
+ from the given file. Users are encouraged to use
213
+ imageio.get_reader() instead.
214
+ """
215
+ select_mode = request.mode[1] if request.mode[1] in "iIvV" else ""
216
+ if select_mode not in self.modes:
217
+ raise RuntimeError(
218
+ f"Format {self.name} cannot read in {request.mode.image_mode} mode"
219
+ )
220
+ return self.Reader(self, request)
221
+
222
+ def get_writer(self, request):
223
+ """get_writer(request)
224
+
225
+ Return a writer object that can be used to write data and info
226
+ to the given file. Users are encouraged to use
227
+ imageio.get_writer() instead.
228
+ """
229
+ select_mode = request.mode[1] if request.mode[1] in "iIvV" else ""
230
+ if select_mode not in self.modes:
231
+ raise RuntimeError(
232
+ f"Format {self.name} cannot write in {request.mode.image_mode} mode"
233
+ )
234
+ return self.Writer(self, request)
235
+
236
+ def can_read(self, request):
237
+ """can_read(request)
238
+
239
+ Get whether this format can read data from the specified uri.
240
+ """
241
+ return self._can_read(request)
242
+
243
+ def can_write(self, request):
244
+ """can_write(request)
245
+
246
+ Get whether this format can write data to the speciefed uri.
247
+ """
248
+ return self._can_write(request)
249
+
250
+ def _can_read(self, request): # pragma: no cover
251
+ """Check if Plugin can read from ImageResource.
252
+
253
+ This method is called when the format manager is searching for a format
254
+ to read a certain image. Return True if this format can do it.
255
+
256
+ The format manager is aware of the extensions and the modes that each
257
+ format can handle. It will first ask all formats that *seem* to be able
258
+ to read it whether they can. If none can, it will ask the remaining
259
+ formats if they can: the extension might be missing, and this allows
260
+ formats to provide functionality for certain extensions, while giving
261
+ preference to other plugins.
262
+
263
+ If a format says it can, it should live up to it. The format would
264
+ ideally check the request.firstbytes and look for a header of some kind.
265
+
266
+ Parameters
267
+ ----------
268
+ request : Request
269
+ A request that can be used to access the ImageResource and obtain
270
+ metadata about it.
271
+
272
+ Returns
273
+ -------
274
+ can_read : bool
275
+ True if the plugin can read from the ImageResource, False otherwise.
276
+
277
+ """
278
+ return None # Plugins must implement this
279
+
280
+ def _can_write(self, request): # pragma: no cover
281
+ """Check if Plugin can write to ImageResource.
282
+
283
+ Parameters
284
+ ----------
285
+ request : Request
286
+ A request that can be used to access the ImageResource and obtain
287
+ metadata about it.
288
+
289
+ Returns
290
+ -------
291
+ can_read : bool
292
+ True if the plugin can write to the ImageResource, False otherwise.
293
+
294
+ """
295
+ return None # Plugins must implement this
296
+
297
+ # -----
298
+
299
+ class _BaseReaderWriter(object):
300
+ """Base class for the Reader and Writer class to implement common
301
+ functionality. It implements a similar approach for opening/closing
302
+ and context management as Python's file objects.
303
+ """
304
+
305
+ def __init__(self, format, request):
306
+ self.__closed = False
307
+ self._BaseReaderWriter_last_index = -1
308
+ self._format = format
309
+ self._request = request
310
+ # Open the reader/writer
311
+ self._open(**self.request.kwargs.copy())
312
+
313
+ @property
314
+ def format(self):
315
+ """The :class:`.Format` object corresponding to the current
316
+ read/write operation.
317
+ """
318
+ return self._format
319
+
320
+ @property
321
+ def request(self):
322
+ """The :class:`.Request` object corresponding to the
323
+ current read/write operation.
324
+ """
325
+ return self._request
326
+
327
+ def __enter__(self):
328
+ self._checkClosed()
329
+ return self
330
+
331
+ def __exit__(self, type, value, traceback):
332
+ if value is None:
333
+ # Otherwise error in close hide the real error.
334
+ self.close()
335
+
336
+ def __del__(self):
337
+ try:
338
+ self.close()
339
+ except Exception: # pragma: no cover
340
+ pass # Supress noise when called during interpreter shutdown
341
+
342
+ def close(self):
343
+ """Flush and close the reader/writer.
344
+ This method has no effect if it is already closed.
345
+ """
346
+ if self.__closed:
347
+ return
348
+ self.__closed = True
349
+ self._close()
350
+ # Process results and clean request object
351
+ self.request.finish()
352
+
353
+ @property
354
+ def closed(self):
355
+ """Whether the reader/writer is closed."""
356
+ return self.__closed
357
+
358
+ def _checkClosed(self, msg=None):
359
+ """Internal: raise an ValueError if reader/writer is closed"""
360
+ if self.closed:
361
+ what = self.__class__.__name__
362
+ msg = msg or ("I/O operation on closed %s." % what)
363
+ raise RuntimeError(msg)
364
+
365
+ # To implement
366
+
367
+ def _open(self, **kwargs):
368
+ """_open(**kwargs)
369
+
370
+ Plugins should probably implement this.
371
+
372
+ It is called when reader/writer is created. Here the
373
+ plugin can do its initialization. The given keyword arguments
374
+ are those that were given by the user at imageio.read() or
375
+ imageio.write().
376
+ """
377
+ raise NotImplementedError()
378
+
379
+ def _close(self):
380
+ """_close()
381
+
382
+ Plugins should probably implement this.
383
+
384
+ It is called when the reader/writer is closed. Here the plugin
385
+ can do a cleanup, flush, etc.
386
+
387
+ """
388
+ raise NotImplementedError()
389
+
390
+ # -----
391
+
392
+ class Reader(_BaseReaderWriter):
393
+ """
394
+ The purpose of a reader object is to read data from an image
395
+ resource, and should be obtained by calling :func:`.get_reader`.
396
+
397
+ A reader can be used as an iterator to read multiple images,
398
+ and (if the format permits) only reads data from the file when
399
+ new data is requested (i.e. streaming). A reader can also be
400
+ used as a context manager so that it is automatically closed.
401
+
402
+ Plugins implement Reader's for different formats. Though rare,
403
+ plugins may provide additional functionality (beyond what is
404
+ provided by the base reader class).
405
+ """
406
+
407
+ def get_length(self):
408
+ """get_length()
409
+
410
+ Get the number of images in the file. (Note: you can also
411
+ use ``len(reader_object)``.)
412
+
413
+ The result can be:
414
+ * 0 for files that only have meta data
415
+ * 1 for singleton images (e.g. in PNG, JPEG, etc.)
416
+ * N for image series
417
+ * inf for streams (series of unknown length)
418
+ """
419
+ return self._get_length()
420
+
421
+ def get_data(self, index, **kwargs):
422
+ """get_data(index, **kwargs)
423
+
424
+ Read image data from the file, using the image index. The
425
+ returned image has a 'meta' attribute with the meta data.
426
+ Raises IndexError if the index is out of range.
427
+
428
+ Some formats may support additional keyword arguments. These are
429
+ listed in the documentation of those formats.
430
+ """
431
+ self._checkClosed()
432
+ self._BaseReaderWriter_last_index = index
433
+ try:
434
+ im, meta = self._get_data(index, **kwargs)
435
+ except StopIteration:
436
+ raise IndexError(index)
437
+ return Array(im, meta) # Array tests im and meta
438
+
439
+ def get_next_data(self, **kwargs):
440
+ """get_next_data(**kwargs)
441
+
442
+ Read the next image from the series.
443
+
444
+ Some formats may support additional keyword arguments. These are
445
+ listed in the documentation of those formats.
446
+ """
447
+ return self.get_data(self._BaseReaderWriter_last_index + 1, **kwargs)
448
+
449
+ def set_image_index(self, index, **kwargs):
450
+ """set_image_index(index)
451
+
452
+ Set the internal pointer such that the next call to
453
+ get_next_data() returns the image specified by the index
454
+ """
455
+ self._checkClosed()
456
+ n = self.get_length()
457
+ self._BaseReaderWriter_last_index = min(max(index - 1, -1), n)
458
+
459
+ def get_meta_data(self, index=None):
460
+ """get_meta_data(index=None)
461
+
462
+ Read meta data from the file. using the image index. If the
463
+ index is omitted or None, return the file's (global) meta data.
464
+
465
+ Note that ``get_data`` also provides the meta data for the returned
466
+ image as an atrribute of that image.
467
+
468
+ The meta data is a dict, which shape depends on the format.
469
+ E.g. for JPEG, the dict maps group names to subdicts and each
470
+ group is a dict with name-value pairs. The groups represent
471
+ the different metadata formats (EXIF, XMP, etc.).
472
+ """
473
+ self._checkClosed()
474
+ meta = self._get_meta_data(index)
475
+ if not isinstance(meta, dict):
476
+ raise ValueError(
477
+ "Meta data must be a dict, not %r" % meta.__class__.__name__
478
+ )
479
+ return meta
480
+
481
+ def iter_data(self):
482
+ """iter_data()
483
+
484
+ Iterate over all images in the series. (Note: you can also
485
+ iterate over the reader object.)
486
+
487
+ """
488
+ self._checkClosed()
489
+ n = self.get_length()
490
+ i = 0
491
+ while i < n:
492
+ try:
493
+ im, meta = self._get_data(i)
494
+ except StopIteration:
495
+ return
496
+ except IndexError:
497
+ if n == float("inf"):
498
+ return
499
+ raise
500
+ yield Array(im, meta)
501
+ i += 1
502
+
503
+ # Compatibility
504
+
505
+ def __iter__(self):
506
+ return self.iter_data()
507
+
508
+ def __len__(self):
509
+ n = self.get_length()
510
+ if n == float("inf"):
511
+ n = sys.maxsize
512
+ return n
513
+
514
+ # To implement
515
+
516
+ def _get_length(self):
517
+ """_get_length()
518
+
519
+ Plugins must implement this.
520
+
521
+ The retured scalar specifies the number of images in the series.
522
+ See Reader.get_length for more information.
523
+ """
524
+ raise NotImplementedError()
525
+
526
+ def _get_data(self, index):
527
+ """_get_data()
528
+
529
+ Plugins must implement this, but may raise an IndexError in
530
+ case the plugin does not support random access.
531
+
532
+ It should return the image and meta data: (ndarray, dict).
533
+ """
534
+ raise NotImplementedError()
535
+
536
+ def _get_meta_data(self, index):
537
+ """_get_meta_data(index)
538
+
539
+ Plugins must implement this.
540
+
541
+ It should return the meta data as a dict, corresponding to the
542
+ given index, or to the file's (global) meta data if index is
543
+ None.
544
+ """
545
+ raise NotImplementedError()
546
+
547
+ # -----
548
+
549
+ class Writer(_BaseReaderWriter):
550
+ """
551
+ The purpose of a writer object is to write data to an image
552
+ resource, and should be obtained by calling :func:`.get_writer`.
553
+
554
+ A writer will (if the format permits) write data to the file
555
+ as soon as new data is provided (i.e. streaming). A writer can
556
+ also be used as a context manager so that it is automatically
557
+ closed.
558
+
559
+ Plugins implement Writer's for different formats. Though rare,
560
+ plugins may provide additional functionality (beyond what is
561
+ provided by the base writer class).
562
+ """
563
+
564
+ def append_data(self, im, meta=None):
565
+ """append_data(im, meta={})
566
+
567
+ Append an image (and meta data) to the file. The final meta
568
+ data that is used consists of the meta data on the given
569
+ image (if applicable), updated with the given meta data.
570
+ """
571
+ self._checkClosed()
572
+ # Check image data
573
+ if not isinstance(im, np.ndarray):
574
+ raise ValueError("append_data requires ndarray as first arg")
575
+ # Get total meta dict
576
+ total_meta = {}
577
+ if hasattr(im, "meta") and isinstance(im.meta, dict):
578
+ total_meta.update(im.meta)
579
+ if meta is None:
580
+ pass
581
+ elif not isinstance(meta, dict):
582
+ raise ValueError("Meta must be a dict.")
583
+ else:
584
+ total_meta.update(meta)
585
+
586
+ # Decouple meta info
587
+ im = asarray(im)
588
+ # Call
589
+ return self._append_data(im, total_meta)
590
+
591
+ def set_meta_data(self, meta):
592
+ """set_meta_data(meta)
593
+
594
+ Sets the file's (global) meta data. The meta data is a dict which
595
+ shape depends on the format. E.g. for JPEG the dict maps
596
+ group names to subdicts, and each group is a dict with
597
+ name-value pairs. The groups represents the different
598
+ metadata formats (EXIF, XMP, etc.).
599
+
600
+ Note that some meta formats may not be supported for
601
+ writing, and individual fields may be ignored without
602
+ warning if they are invalid.
603
+ """
604
+ self._checkClosed()
605
+ if not isinstance(meta, dict):
606
+ raise ValueError("Meta must be a dict.")
607
+ else:
608
+ return self._set_meta_data(meta)
609
+
610
+ # To implement
611
+
612
+ def _append_data(self, im, meta):
613
+ # Plugins must implement this
614
+ raise NotImplementedError()
615
+
616
+ def _set_meta_data(self, meta):
617
+ # Plugins must implement this
618
+ raise NotImplementedError()
619
+
620
+
621
+ class FormatManager(object):
622
+ """
623
+ The FormatManager is a singleton plugin factory.
624
+
625
+ The format manager supports getting a format object using indexing (by
626
+ format name or extension). When used as an iterator, this object
627
+ yields all registered format objects.
628
+
629
+ See also :func:`.help`.
630
+ """
631
+
632
+ @property
633
+ def _formats(self):
634
+ return [x for x in known_plugins.values() if x.is_legacy]
635
+
636
+ def __repr__(self):
637
+ return f"<imageio.FormatManager with {len(self._formats)} registered formats>"
638
+
639
+ def __iter__(self):
640
+ return iter(x.format for x in self._formats)
641
+
642
+ def __len__(self):
643
+ return len(self._formats)
644
+
645
+ def __str__(self):
646
+ ss = []
647
+ for config in self._formats:
648
+ ext = config.legacy_args["extensions"]
649
+ desc = config.legacy_args["description"]
650
+ s = f"{config.name} - {desc} [{ext}]"
651
+ ss.append(s)
652
+ return "\n".join(ss)
653
+
654
+ def __getitem__(self, name):
655
+ warnings.warn(
656
+ "The usage of `FormatManager` is deprecated and it will be "
657
+ "removed in Imageio v3. Use `iio.imopen` instead.",
658
+ DeprecationWarning,
659
+ stacklevel=2,
660
+ )
661
+
662
+ if not isinstance(name, str):
663
+ raise ValueError(
664
+ "Looking up a format should be done by name or by extension."
665
+ )
666
+
667
+ if name == "":
668
+ raise ValueError("No format matches the empty string.")
669
+
670
+ # Test if name is existing file
671
+ if Path(name).is_file():
672
+ # legacy compatibility - why test reading here??
673
+ try:
674
+ return imopen(name, "r", legacy_mode=True)._format
675
+ except ValueError:
676
+ # no plugin can read the file
677
+ pass
678
+
679
+ config = _get_config(name.upper())
680
+
681
+ try:
682
+ return config.format
683
+ except ImportError:
684
+ raise ImportError(
685
+ f"The `{config.name}` format is not installed. "
686
+ f"Use `pip install imageio[{config.install_name}]` to install it."
687
+ )
688
+
689
+ def sort(self, *names):
690
+ """sort(name1, name2, name3, ...)
691
+
692
+ Sort the formats based on zero or more given names; a format with
693
+ a name that matches one of the given names will take precedence
694
+ over other formats. A match means an equal name, or ending with
695
+ that name (though the former counts higher). Case insensitive.
696
+
697
+ Format preference will match the order of the given names: using
698
+ ``sort('TIFF', '-FI', '-PIL')`` would prefer the FreeImage formats
699
+ over the Pillow formats, but prefer TIFF even more. Each time
700
+ this is called, the starting point is the default format order,
701
+ and calling ``sort()`` with no arguments will reset the order.
702
+
703
+ Be aware that using the function can affect the behavior of
704
+ other code that makes use of imageio.
705
+
706
+ Also see the ``IMAGEIO_FORMAT_ORDER`` environment variable.
707
+ """
708
+
709
+ warnings.warn(
710
+ "`FormatManager` is deprecated and it will be removed in ImageIO v3."
711
+ " Migrating `FormatManager.sort` depends on your use-case:\n"
712
+ "\t- modify `iio.config.known_plugins` to specify the search order for "
713
+ "unrecognized formats.\n"
714
+ "\t- modify `iio.config.known_extensions[<extension>].priority`"
715
+ " to control a specific extension.",
716
+ DeprecationWarning,
717
+ stacklevel=2,
718
+ )
719
+
720
+ # Check and sanitize imput
721
+ for name in names:
722
+ if not isinstance(name, str):
723
+ raise TypeError("formats.sort() accepts only string names.")
724
+ if any(c in name for c in ".,"):
725
+ raise ValueError(
726
+ "Names given to formats.sort() should not "
727
+ "contain dots `.` or commas `,`."
728
+ )
729
+
730
+ should_reset = len(names) == 0
731
+ if should_reset:
732
+ names = _original_order
733
+
734
+ sane_names = [name.strip().upper() for name in names if name != ""]
735
+
736
+ # enforce order for every extension that uses it
737
+ flat_extensions = [
738
+ ext for ext_list in known_extensions.values() for ext in ext_list
739
+ ]
740
+ for extension in flat_extensions:
741
+ if should_reset:
742
+ extension.reset()
743
+ continue
744
+
745
+ for name in reversed(sane_names):
746
+ for plugin in [x for x in extension.default_priority]:
747
+ if plugin.endswith(name):
748
+ extension.priority.remove(plugin)
749
+ extension.priority.insert(0, plugin)
750
+
751
+ old_order = known_plugins.copy()
752
+ known_plugins.clear()
753
+
754
+ for name in sane_names:
755
+ plugin = old_order.pop(name, None)
756
+ if plugin is not None:
757
+ known_plugins[name] = plugin
758
+
759
+ known_plugins.update(old_order)
760
+
761
+ def add_format(self, iio_format, overwrite=False):
762
+ """add_format(format, overwrite=False)
763
+
764
+ Register a format, so that imageio can use it. If a format with the
765
+ same name already exists, an error is raised, unless overwrite is True,
766
+ in which case the current format is replaced.
767
+ """
768
+
769
+ warnings.warn(
770
+ "`FormatManager` is deprecated and it will be removed in ImageIO v3."
771
+ "To migrate `FormatManager.add_format` add the plugin directly to "
772
+ "`iio.config.known_plugins`.",
773
+ DeprecationWarning,
774
+ stacklevel=2,
775
+ )
776
+
777
+ if not isinstance(iio_format, Format):
778
+ raise ValueError("add_format needs argument to be a Format object")
779
+ elif not overwrite and iio_format.name in self.get_format_names():
780
+ raise ValueError(
781
+ f"A Format named {iio_format.name} is already registered, use"
782
+ " `overwrite=True` to replace."
783
+ )
784
+
785
+ config = PluginConfig(
786
+ name=iio_format.name.upper(),
787
+ class_name=iio_format.__class__.__name__,
788
+ module_name=iio_format.__class__.__module__,
789
+ is_legacy=True,
790
+ install_name="unknown",
791
+ legacy_args={
792
+ "name": iio_format.name,
793
+ "description": iio_format.description,
794
+ "extensions": " ".join(iio_format.extensions),
795
+ "modes": iio_format.modes,
796
+ },
797
+ )
798
+
799
+ known_plugins[config.name] = config
800
+
801
+ for extension in iio_format.extensions:
802
+ # be conservative and always treat it as a unique file format
803
+ ext = FileExtension(
804
+ extension=extension,
805
+ priority=[config.name],
806
+ name="Unique Format",
807
+ description="A format inserted at runtime."
808
+ f" It is being read by the `{config.name}` plugin.",
809
+ )
810
+ known_extensions.setdefault(extension, list()).append(ext)
811
+
812
+ def search_read_format(self, request):
813
+ """search_read_format(request)
814
+
815
+ Search a format that can read a file according to the given request.
816
+ Returns None if no appropriate format was found. (used internally)
817
+ """
818
+
819
+ try:
820
+ # in legacy_mode imopen returns a LegacyPlugin
821
+ return imopen(request, request.mode.io_mode, legacy_mode=True)._format
822
+ except ValueError:
823
+ # no plugin can read this request
824
+ # but the legacy API doesn't raise
825
+ return None
826
+
827
+ def search_write_format(self, request):
828
+ """search_write_format(request)
829
+
830
+ Search a format that can write a file according to the given request.
831
+ Returns None if no appropriate format was found. (used internally)
832
+ """
833
+
834
+ try:
835
+ # in legacy_mode imopen returns a LegacyPlugin
836
+ return imopen(request, request.mode.io_mode, legacy_mode=True)._format
837
+ except ValueError:
838
+ # no plugin can write this request
839
+ # but the legacy API doesn't raise
840
+ return None
841
+
842
+ def get_format_names(self):
843
+ """Get the names of all registered formats."""
844
+
845
+ warnings.warn(
846
+ "`FormatManager` is deprecated and it will be removed in ImageIO v3."
847
+ "To migrate `FormatManager.get_format_names` use `iio.config.known_plugins.keys()` instead.",
848
+ DeprecationWarning,
849
+ stacklevel=2,
850
+ )
851
+
852
+ return [f.name for f in self._formats]
853
+
854
+ def show(self):
855
+ """Show a nicely formatted list of available formats"""
856
+ print(self)
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/core/imopen.py ADDED
@@ -0,0 +1,303 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pathlib import Path
2
+ import warnings
3
+
4
+ from ..config import known_plugins
5
+ from ..config.extensions import known_extensions
6
+ from .request import (
7
+ SPECIAL_READ_URIS,
8
+ URI_FILENAME,
9
+ InitializationError,
10
+ IOMode,
11
+ Request,
12
+ )
13
+
14
+
15
+ def imopen(
16
+ uri,
17
+ io_mode,
18
+ *,
19
+ plugin=None,
20
+ extension=None,
21
+ format_hint=None,
22
+ legacy_mode=False,
23
+ **kwargs,
24
+ ):
25
+ """Open an ImageResource.
26
+
27
+ .. warning::
28
+ This warning is for pypy users. If you are not using a context manager,
29
+ remember to deconstruct the returned plugin to avoid leaking the file
30
+ handle to an unclosed file.
31
+
32
+ Parameters
33
+ ----------
34
+ uri : str or pathlib.Path or bytes or file or Request
35
+ The :doc:`ImageResource <../../user_guide/requests>` to load the
36
+ image from.
37
+ io_mode : str
38
+ The mode in which the file is opened. Possible values are::
39
+
40
+ ``r`` - open the file for reading
41
+ ``w`` - open the file for writing
42
+
43
+ Depreciated since v2.9:
44
+ A second character can be added to give the reader a hint on what
45
+ the user expects. This will be ignored by new plugins and will
46
+ only have an effect on legacy plugins. Possible values are::
47
+
48
+ ``i`` for a single image,
49
+ ``I`` for multiple images,
50
+ ``v`` for a single volume,
51
+ ``V`` for multiple volumes,
52
+ ``?`` for don't care (default)
53
+
54
+ plugin : str, Plugin, or None
55
+ The plugin to use. If set to None (default) imopen will perform a
56
+ search for a matching plugin. If not None, this takes priority over
57
+ the provided format hint.
58
+ extension : str
59
+ If not None, treat the provided ImageResource as if it had the given
60
+ extension. This affects the order in which backends are considered, and
61
+ when writing this may also influence the format used when encoding.
62
+ format_hint : str
63
+ A format hint to help optimize plugin selection given as the format's
64
+ extension, e.g. ".png". This can speed up the selection process for
65
+ ImageResources that don't have an explicit extension, e.g. streams, or
66
+ for ImageResources where the extension does not match the resource's
67
+ content. If the ImageResource lacks an explicit extension, it will be
68
+ set to this format.
69
+ legacy_mode : bool
70
+ If true (default) use the v2 behavior when searching for a suitable
71
+ plugin. This will ignore v3 plugins and will check ``plugin``
72
+ against known extensions if no plugin with the given name can be found.
73
+ **kwargs : Any
74
+ Additional keyword arguments will be passed to the plugin upon
75
+ construction.
76
+
77
+ Notes
78
+ -----
79
+ Registered plugins are controlled via the ``known_plugins`` dict in
80
+ ``imageio.config``.
81
+
82
+ Passing a ``Request`` as the uri is only supported if ``legacy_mode``
83
+ is ``True``. In this case ``io_mode`` is ignored.
84
+
85
+ Using the kwarg ``format_hint`` does not enforce the given format. It merely
86
+ provides a `hint` to the selection process and plugin. The selection
87
+ processes uses this hint for optimization; however, a plugin's decision how
88
+ to read a ImageResource will - typically - still be based on the content of
89
+ the resource.
90
+
91
+
92
+ Examples
93
+ --------
94
+
95
+ >>> import imageio.v3 as iio
96
+ >>> with iio.imopen("/path/to/image.png", "r") as file:
97
+ >>> im = file.read()
98
+
99
+ >>> with iio.imopen("/path/to/output.jpg", "w") as file:
100
+ >>> file.write(im)
101
+
102
+ """
103
+
104
+ if isinstance(uri, Request) and legacy_mode:
105
+ warnings.warn(
106
+ "`iio.core.Request` is a low-level object and using it"
107
+ " directly as input to `imopen` is discouraged. This will raise"
108
+ " an exception in ImageIO v3.",
109
+ DeprecationWarning,
110
+ stacklevel=2,
111
+ )
112
+
113
+ request = uri
114
+ uri = request.raw_uri
115
+ io_mode = request.mode.io_mode
116
+ request.format_hint = format_hint
117
+ else:
118
+ request = Request(uri, io_mode, format_hint=format_hint, extension=extension)
119
+
120
+ source = "<bytes>" if isinstance(uri, bytes) else uri
121
+
122
+ # fast-path based on plugin
123
+ # (except in legacy mode)
124
+ if plugin is not None:
125
+ if isinstance(plugin, str):
126
+ try:
127
+ config = known_plugins[plugin]
128
+ except KeyError:
129
+ request.finish()
130
+ raise ValueError(
131
+ f"`{plugin}` is not a registered plugin name."
132
+ ) from None
133
+
134
+ def loader(request, **kwargs):
135
+ return config.plugin_class(request, **kwargs)
136
+
137
+ elif not legacy_mode:
138
+
139
+ def loader(request, **kwargs):
140
+ return plugin(request, **kwargs)
141
+
142
+ else:
143
+ request.finish()
144
+ raise ValueError("The `plugin` argument must be a string.")
145
+
146
+ try:
147
+ return loader(request, **kwargs)
148
+ except InitializationError as class_specific:
149
+ err_from = class_specific
150
+ err_type = RuntimeError if legacy_mode else IOError
151
+ err_msg = f"`{plugin}` can not handle the given uri."
152
+ except ImportError:
153
+ err_from = None
154
+ err_type = ImportError
155
+ err_msg = (
156
+ f"The `{config.name}` plugin is not installed. "
157
+ f"Use `pip install imageio[{config.install_name}]` to install it."
158
+ )
159
+ except Exception as generic_error:
160
+ err_from = generic_error
161
+ err_type = IOError
162
+ err_msg = f"An unknown error occured while initializing plugin `{plugin}`."
163
+
164
+ request.finish()
165
+ raise err_type(err_msg) from err_from
166
+
167
+ # fast-path based on format_hint
168
+ if request.format_hint is not None:
169
+ for candidate_format in known_extensions[format_hint]:
170
+ for plugin_name in candidate_format.priority:
171
+ config = known_plugins[plugin_name]
172
+
173
+ # v2 compatibility; delete in v3
174
+ if legacy_mode and not config.is_legacy:
175
+ continue
176
+
177
+ try:
178
+ candidate_plugin = config.plugin_class
179
+ except ImportError:
180
+ # not installed
181
+ continue
182
+
183
+ try:
184
+ plugin_instance = candidate_plugin(request, **kwargs)
185
+ except InitializationError:
186
+ # file extension doesn't match file type
187
+ continue
188
+
189
+ return plugin_instance
190
+ else:
191
+ resource = (
192
+ "<bytes>" if isinstance(request.raw_uri, bytes) else request.raw_uri
193
+ )
194
+ warnings.warn(f"`{resource}` can not be opened as a `{format_hint}` file.")
195
+
196
+ # fast-path based on file extension
197
+ if request.extension in known_extensions:
198
+ for candidate_format in known_extensions[request.extension]:
199
+ for plugin_name in candidate_format.priority:
200
+ config = known_plugins[plugin_name]
201
+
202
+ # v2 compatibility; delete in v3
203
+ if legacy_mode and not config.is_legacy:
204
+ continue
205
+
206
+ try:
207
+ candidate_plugin = config.plugin_class
208
+ except ImportError:
209
+ # not installed
210
+ continue
211
+
212
+ try:
213
+ plugin_instance = candidate_plugin(request, **kwargs)
214
+ except InitializationError:
215
+ # file extension doesn't match file type
216
+ continue
217
+
218
+ return plugin_instance
219
+
220
+ # error out for read-only special targets
221
+ # this is hacky; can we come up with a better solution for this?
222
+ if request.mode.io_mode == IOMode.write:
223
+ if isinstance(uri, str) and uri.startswith(SPECIAL_READ_URIS):
224
+ request.finish()
225
+ err_type = ValueError if legacy_mode else IOError
226
+ err_msg = f"`{source}` is read-only."
227
+ raise err_type(err_msg)
228
+
229
+ # error out for directories
230
+ # this is a bit hacky and should be cleaned once we decide
231
+ # how to gracefully handle DICOM
232
+ if request._uri_type == URI_FILENAME and Path(request.raw_uri).is_dir():
233
+ request.finish()
234
+ err_type = ValueError if legacy_mode else IOError
235
+ err_msg = (
236
+ "ImageIO does not generally support reading folders. "
237
+ "Limited support may be available via specific plugins. "
238
+ "Specify the plugin explicitly using the `plugin` kwarg, e.g. `plugin='DICOM'`"
239
+ )
240
+ raise err_type(err_msg)
241
+
242
+ # close the current request here and use fresh/new ones while trying each
243
+ # plugin This is slow (means potentially reopening a resource several
244
+ # times), but should only happen rarely because this is the fallback if all
245
+ # else fails.
246
+ request.finish()
247
+
248
+ # fallback option: try all plugins
249
+ for config in known_plugins.values():
250
+ # Note: for v2 compatibility
251
+ # this branch can be removed in ImageIO v3.0
252
+ if legacy_mode and not config.is_legacy:
253
+ continue
254
+
255
+ # each plugin gets its own request
256
+ request = Request(uri, io_mode, format_hint=format_hint)
257
+
258
+ try:
259
+ plugin_instance = config.plugin_class(request, **kwargs)
260
+ except InitializationError:
261
+ continue
262
+ except ImportError:
263
+ continue
264
+ else:
265
+ return plugin_instance
266
+
267
+ err_type = ValueError if legacy_mode else IOError
268
+ err_msg = f"Could not find a backend to open `{source}`` with iomode `{io_mode}`."
269
+
270
+ # check if a missing plugin could help
271
+ if request.extension in known_extensions:
272
+ missing_plugins = list()
273
+
274
+ formats = known_extensions[request.extension]
275
+ plugin_names = [
276
+ plugin for file_format in formats for plugin in file_format.priority
277
+ ]
278
+ for name in plugin_names:
279
+ config = known_plugins[name]
280
+
281
+ try:
282
+ config.plugin_class
283
+ continue
284
+ except ImportError:
285
+ missing_plugins.append(config)
286
+
287
+ if len(missing_plugins) > 0:
288
+ install_candidates = "\n".join(
289
+ [
290
+ (
291
+ f" {config.name}: "
292
+ f"pip install imageio[{config.install_name}]"
293
+ )
294
+ for config in missing_plugins
295
+ ]
296
+ )
297
+ err_msg += (
298
+ "\nBased on the extension, the following plugins might add capable backends:\n"
299
+ f"{install_candidates}"
300
+ )
301
+
302
+ request.finish()
303
+ raise err_type(err_msg)
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/core/legacy_plugin_wrapper.py ADDED
@@ -0,0 +1,322 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ from pathlib import Path
3
+
4
+ from .request import IOMode, InitializationError
5
+ from .v3_plugin_api import PluginV3, ImageProperties
6
+
7
+
8
+ def _legacy_default_index(format):
9
+ if format._name == "FFMPEG":
10
+ index = Ellipsis
11
+ elif format._name == "GIF-PIL":
12
+ index = Ellipsis
13
+ else:
14
+ index = 0
15
+
16
+ return index
17
+
18
+
19
+ class LegacyPlugin(PluginV3):
20
+ """A plugin to make old (v2.9) plugins compatible with v3.0
21
+
22
+ .. depreciated:: 2.9
23
+ `legacy_get_reader` will be removed in a future version of imageio.
24
+ `legacy_get_writer` will be removed in a future version of imageio.
25
+
26
+ This plugin is a wrapper around the old FormatManager class and exposes
27
+ all the old plugins via the new API. On top of this it has
28
+ ``legacy_get_reader`` and ``legacy_get_writer`` methods to allow using
29
+ it with the v2.9 API.
30
+
31
+ Methods
32
+ -------
33
+ read(index=None, **kwargs)
34
+ Read the image at position ``index``.
35
+ write(image, **kwargs)
36
+ Write image to the URI.
37
+ iter(**kwargs)
38
+ Iteratively yield images from the given URI.
39
+ get_meta(index=None)
40
+ Return the metadata for the image at position ``index``.
41
+ legacy_get_reader(**kwargs)
42
+ Returns the v2.9 image reader. (depreciated)
43
+ legacy_get_writer(**kwargs)
44
+ Returns the v2.9 image writer. (depreciated)
45
+
46
+ Examples
47
+ --------
48
+
49
+ >>> import imageio.v3 as iio
50
+ >>> with iio.imopen("/path/to/image.tiff", "r", legacy_mode=True) as file:
51
+ >>> reader = file.legacy_get_reader() # depreciated
52
+ >>> for im in file.iter():
53
+ >>> print(im.shape)
54
+
55
+ """
56
+
57
+ def __init__(self, request, legacy_plugin):
58
+ """Instantiate a new Legacy Plugin
59
+
60
+ Parameters
61
+ ----------
62
+ uri : {str, pathlib.Path, bytes, file}
63
+ The resource to load the image from, e.g. a filename, pathlib.Path,
64
+ http address or file object, see the docs for more info.
65
+ legacy_plugin : Format
66
+ The (legacy) format to use to interface with the URI.
67
+
68
+ """
69
+ self._request = request
70
+ self._format = legacy_plugin
71
+
72
+ source = (
73
+ "<bytes>"
74
+ if isinstance(self._request.raw_uri, bytes)
75
+ else self._request.raw_uri
76
+ )
77
+ if self._request.mode.io_mode == IOMode.read:
78
+ if not self._format.can_read(request):
79
+ raise InitializationError(
80
+ f"`{self._format.name}`" f" can not read `{source}`."
81
+ )
82
+ else:
83
+ if not self._format.can_write(request):
84
+ raise InitializationError(
85
+ f"`{self._format.name}`" f" can not write to `{source}`."
86
+ )
87
+
88
+ def legacy_get_reader(self, **kwargs):
89
+ """legacy_get_reader(**kwargs)
90
+
91
+ a utility method to provide support vor the V2.9 API
92
+
93
+ Parameters
94
+ ----------
95
+ kwargs : ...
96
+ Further keyword arguments are passed to the reader. See :func:`.help`
97
+ to see what arguments are available for a particular format.
98
+ """
99
+
100
+ # Note: this will break thread-safety
101
+ self._request._kwargs = kwargs
102
+
103
+ # safeguard for DICOM plugin reading from folders
104
+ try:
105
+ assert Path(self._request.filename).is_dir()
106
+ except OSError:
107
+ pass # not a valid path on this OS
108
+ except AssertionError:
109
+ pass # not a folder
110
+ else:
111
+ return self._format.get_reader(self._request)
112
+
113
+ self._request.get_file().seek(0)
114
+ return self._format.get_reader(self._request)
115
+
116
+ def read(self, *, index=None, **kwargs):
117
+ """
118
+ Parses the given URI and creates a ndarray from it.
119
+
120
+ Parameters
121
+ ----------
122
+ index : {integer, None}
123
+ If the URI contains a list of ndimages return the index-th
124
+ image. If None, stack all images into an ndimage along the
125
+ 0-th dimension (equivalent to np.stack(imgs, axis=0)).
126
+ kwargs : ...
127
+ Further keyword arguments are passed to the reader. See
128
+ :func:`.help` to see what arguments are available for a particular
129
+ format.
130
+
131
+ Returns
132
+ -------
133
+ ndimage : np.ndarray
134
+ A numpy array containing the decoded image data.
135
+
136
+ """
137
+
138
+ if index is None:
139
+ index = _legacy_default_index(self._format)
140
+
141
+ if index is Ellipsis:
142
+ img = np.stack([im for im in self.iter(**kwargs)])
143
+ return img
144
+
145
+ reader = self.legacy_get_reader(**kwargs)
146
+ return reader.get_data(index)
147
+
148
+ def legacy_get_writer(self, **kwargs):
149
+ """legacy_get_writer(**kwargs)
150
+
151
+ Returns a :class:`.Writer` object which can be used to write data
152
+ and meta data to the specified file.
153
+
154
+ Parameters
155
+ ----------
156
+ kwargs : ...
157
+ Further keyword arguments are passed to the writer. See :func:`.help`
158
+ to see what arguments are available for a particular format.
159
+ """
160
+
161
+ # Note: this will break thread-safety
162
+ self._request._kwargs = kwargs
163
+ return self._format.get_writer(self._request)
164
+
165
+ def write(self, ndimage, **kwargs):
166
+ """
167
+ Write an ndimage to the URI specified in path.
168
+
169
+ If the URI points to a file on the current host and the file does not
170
+ yet exist it will be created. If the file exists already, it will be
171
+ appended if possible; otherwise, it will be replaced.
172
+
173
+ Parameters
174
+ ----------
175
+ image : numpy.ndarray
176
+ The ndimage or list of ndimages to write.
177
+ kwargs : ...
178
+ Further keyword arguments are passed to the writer. See
179
+ :func:`.help` to see what arguments are available for a
180
+ particular format.
181
+ """
182
+ with self.legacy_get_writer(**kwargs) as writer:
183
+ if self._request.mode.image_mode in "iv":
184
+ writer.append_data(ndimage)
185
+ else:
186
+ if len(ndimage) == 0:
187
+ raise RuntimeError("Zero images were written.")
188
+ for written, ndimage in enumerate(ndimage):
189
+ # Test image
190
+ imt = type(ndimage)
191
+ ndimage = np.asanyarray(ndimage)
192
+ if not np.issubdtype(ndimage.dtype, np.number):
193
+ raise ValueError(
194
+ "Image is not numeric, but {}.".format(imt.__name__)
195
+ )
196
+ elif self._request.mode.image_mode == "I":
197
+ if ndimage.ndim == 2:
198
+ pass
199
+ elif ndimage.ndim == 3 and ndimage.shape[2] in [1, 3, 4]:
200
+ pass
201
+ else:
202
+ raise ValueError(
203
+ "Image must be 2D " "(grayscale, RGB, or RGBA)."
204
+ )
205
+ elif self._request.mode.image_mode == "V":
206
+ if ndimage.ndim == 3:
207
+ pass
208
+ elif ndimage.ndim == 4 and ndimage.shape[3] < 32:
209
+ pass
210
+ else:
211
+ raise ValueError(
212
+ "Image must be 3D," " or 4D if each voxel is a tuple."
213
+ )
214
+
215
+ # Add image
216
+ writer.append_data(ndimage)
217
+
218
+ return writer.request.get_result()
219
+
220
+ def iter(self, **kwargs):
221
+ """Iterate over a list of ndimages given by the URI
222
+
223
+ Parameters
224
+ ----------
225
+ kwargs : ...
226
+ Further keyword arguments are passed to the reader. See
227
+ :func:`.help` to see what arguments are available for a particular
228
+ format.
229
+ """
230
+
231
+ reader = self.legacy_get_reader(**kwargs)
232
+ for image in reader:
233
+ yield image
234
+
235
+ def properties(self, index=None):
236
+ """Standardized ndimage metadata.
237
+
238
+ Parameters
239
+ ----------
240
+ index : int
241
+ The index of the ndimage for which to return properties. If the
242
+ index is out of bounds a ``ValueError`` is raised. If ``None``,
243
+ return the properties for the ndimage stack. If this is impossible,
244
+ e.g., due to shape missmatch, an exception will be raised.
245
+
246
+ Returns
247
+ -------
248
+ properties : ImageProperties
249
+ A dataclass filled with standardized image metadata.
250
+
251
+ """
252
+
253
+ if index is None:
254
+ index = _legacy_default_index(self._format)
255
+
256
+ # for backwards compatibility ... actually reads pixel data :(
257
+ image = self.read(index=index)
258
+
259
+ return ImageProperties(
260
+ shape=image.shape,
261
+ dtype=image.dtype,
262
+ is_batch=True if index is None else False,
263
+ )
264
+
265
+ def get_meta(self, *, index=None):
266
+ """Read ndimage metadata from the URI
267
+
268
+ Parameters
269
+ ----------
270
+ index : {integer, None}
271
+ If the URI contains a list of ndimages return the metadata
272
+ corresponding to the index-th image. If None, behavior depends on
273
+ the used api
274
+
275
+ Legacy-style API: return metadata of the first element (index=0)
276
+ New-style API: Behavior depends on the used Plugin.
277
+
278
+ Returns
279
+ -------
280
+ metadata : dict
281
+ A dictionary of metadata.
282
+
283
+ """
284
+
285
+ return self.metadata(index=index, exclude_applied=False)
286
+
287
+ def metadata(self, index=None, exclude_applied: bool = True):
288
+ """Format-Specific ndimage metadata.
289
+
290
+ Parameters
291
+ ----------
292
+ index : int
293
+ The index of the ndimage to read. If the index is out of bounds a
294
+ ``ValueError`` is raised. If ``None``, global metadata is returned.
295
+ exclude_applied : bool
296
+ If True (default), do not report metadata fields that the plugin
297
+ would apply/consume while reading the image.
298
+
299
+ Returns
300
+ -------
301
+ metadata : dict
302
+ A dictionary filled with format-specific metadata fields and their
303
+ values.
304
+
305
+ """
306
+
307
+ if exclude_applied:
308
+ raise ValueError(
309
+ "Legacy plugins don't support excluding applied metadata fields."
310
+ )
311
+
312
+ if index is None:
313
+ index = _legacy_default_index(self._format)
314
+
315
+ return self.legacy_get_reader().get_meta_data(index=index)
316
+
317
+ def __del__(self) -> None:
318
+ pass
319
+ # turns out we can't close the file here for LegacyPlugin
320
+ # because it would break backwards compatibility
321
+ # with legacy_get_writer and legacy_get_reader
322
+ # self._request.finish()
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/core/request.py ADDED
@@ -0,0 +1,752 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ # imageio is distributed under the terms of the (new) BSD License.
3
+
4
+ """
5
+ Definition of the Request object, which acts as a kind of bridge between
6
+ what the user wants and what the plugins can.
7
+ """
8
+
9
+ import os
10
+ from io import BytesIO
11
+ import zipfile
12
+ import tempfile
13
+ import shutil
14
+ import enum
15
+ import warnings
16
+
17
+ from ..core import urlopen, get_remote_file
18
+
19
+ from pathlib import Path
20
+ from urllib.parse import urlparse
21
+ from typing import Optional
22
+
23
+ # URI types
24
+ URI_BYTES = 1
25
+ URI_FILE = 2
26
+ URI_FILENAME = 3
27
+ URI_ZIPPED = 4
28
+ URI_HTTP = 5
29
+ URI_FTP = 6
30
+
31
+
32
+ class IOMode(str, enum.Enum):
33
+ """Available Image modes
34
+
35
+ This is a helper enum for ``Request.Mode`` which is a composite of a
36
+ ``Request.ImageMode`` and ``Request.IOMode``. The IOMode that tells the
37
+ plugin if the resource should be read from or written to. Available values are
38
+
39
+ - read ("r"): Read from the specified resource
40
+ - write ("w"): Write to the specified resource
41
+
42
+ """
43
+
44
+ read = "r"
45
+ write = "w"
46
+
47
+
48
+ class ImageMode(str, enum.Enum):
49
+ """Available Image modes
50
+
51
+ This is a helper enum for ``Request.Mode`` which is a composite of a
52
+ ``Request.ImageMode`` and ``Request.IOMode``. The image mode that tells the
53
+ plugin the desired (and expected) image shape. Available values are
54
+
55
+ - single_image ("i"): Return a single image extending in two spacial
56
+ dimensions
57
+ - multi_image ("I"): Return a list of images extending in two spacial
58
+ dimensions
59
+ - single_volume ("v"): Return an image extending into multiple dimensions.
60
+ E.g. three spacial dimensions for image stacks, or two spatial and one
61
+ time dimension for videos
62
+ - multi_volume ("V"): Return a list of images extending into multiple
63
+ dimensions.
64
+ - any_mode ("?"): Return an image in any format (the plugin decides the
65
+ appropriate action).
66
+
67
+ """
68
+
69
+ single_image = "i"
70
+ multi_image = "I"
71
+ single_volume = "v"
72
+ multi_volume = "V"
73
+ any_mode = "?"
74
+
75
+
76
+ @enum.unique
77
+ class Mode(str, enum.Enum):
78
+ """The mode to use when interacting with the resource
79
+
80
+ ``Request.Mode`` is a composite of ``Request.ImageMode`` and
81
+ ``Request.IOMode``. The image mode that tells the plugin the desired (and
82
+ expected) image shape and the ``Request.IOMode`` tells the plugin the way
83
+ the resource should be interacted with. For a detailed description of the
84
+ available modes, see the documentation for ``Request.ImageMode`` and
85
+ ``Request.IOMode`` respectively.
86
+
87
+ Available modes are all combinations of ``Request.IOMode`` and ``Request.ImageMode``:
88
+
89
+ - read_single_image ("ri")
90
+ - read_multi_image ("rI")
91
+ - read_single_volume ("rv")
92
+ - read_multi_volume ("rV")
93
+ - read_any ("r?")
94
+ - write_single_image ("wi")
95
+ - write_multi_image ("wI")
96
+ - write_single_volume ("wv")
97
+ - write_multi_volume ("wV")
98
+ - write_any ("w?")
99
+
100
+ Examples
101
+ --------
102
+ >>> Request.Mode("rI") # a list of simple images should be read from the resource
103
+ >>> Request.Mode("wv") # a single volume should be written to the resource
104
+
105
+ """
106
+
107
+ read_single_image = "ri"
108
+ read_multi_image = "rI"
109
+ read_single_volume = "rv"
110
+ read_multi_volume = "rV"
111
+ read_any = "r?"
112
+ write_single_image = "wi"
113
+ write_multi_image = "wI"
114
+ write_single_volume = "wv"
115
+ write_multi_volume = "wV"
116
+ write_any = "w?"
117
+
118
+ @classmethod
119
+ def _missing_(cls, value):
120
+ """Enable Mode("r") and Mode("w")
121
+
122
+ The sunder method ``_missing_`` is called whenever the constructor fails
123
+ to directly look up the corresponding enum value from the given input.
124
+ In our case, we use it to convert the modes "r" and "w" (from the v3
125
+ API) into their legacy versions "r?" and "w?".
126
+
127
+ More info on _missing_:
128
+ https://docs.python.org/3/library/enum.html#supported-sunder-names
129
+ """
130
+
131
+ if value == "r":
132
+ return cls("r?")
133
+ elif value == "w":
134
+ return cls("w?")
135
+ else:
136
+ raise ValueError(f"{value} is no valid Mode.")
137
+
138
+ @property
139
+ def io_mode(self) -> IOMode:
140
+ return IOMode(self.value[0])
141
+
142
+ @property
143
+ def image_mode(self) -> ImageMode:
144
+ return ImageMode(self.value[1])
145
+
146
+ def __getitem__(self, key):
147
+ """For backwards compatibility with the old non-enum modes"""
148
+ if key == 0:
149
+ return self.io_mode
150
+ elif key == 1:
151
+ return self.image_mode
152
+ else:
153
+ raise IndexError(f"Mode has no item {key}")
154
+
155
+
156
+ SPECIAL_READ_URIS = "<video", "<screen>", "<clipboard>"
157
+
158
+ # The user can use this string in a write call to get the data back as bytes.
159
+ RETURN_BYTES = "<bytes>"
160
+
161
+ # Example images that will be auto-downloaded
162
+ EXAMPLE_IMAGES = {
163
+ "astronaut.png": "Image of the astronaut Eileen Collins",
164
+ "camera.png": "A grayscale image of a photographer",
165
+ "checkerboard.png": "Black and white image of a chekerboard",
166
+ "wood.jpg": "A (repeatable) texture of wooden planks",
167
+ "bricks.jpg": "A (repeatable) texture of stone bricks",
168
+ "clock.png": "Photo of a clock with motion blur (Stefan van der Walt)",
169
+ "coffee.png": "Image of a cup of coffee (Rachel Michetti)",
170
+ "chelsea.png": "Image of Stefan's cat",
171
+ "wikkie.png": "Image of Almar's cat",
172
+ "coins.png": "Image showing greek coins from Pompeii",
173
+ "horse.png": "Image showing the silhouette of a horse (Andreas Preuss)",
174
+ "hubble_deep_field.png": "Photograph taken by Hubble telescope (NASA)",
175
+ "immunohistochemistry.png": "Immunohistochemical (IHC) staining",
176
+ "moon.png": "Image showing a portion of the surface of the moon",
177
+ "page.png": "A scanned page of text",
178
+ "text.png": "A photograph of handdrawn text",
179
+ "chelsea.zip": "The chelsea.png in a zipfile (for testing)",
180
+ "chelsea.bsdf": "The chelsea.png in a BSDF file(for testing)",
181
+ "newtonscradle.gif": "Animated GIF of a newton's cradle",
182
+ "cockatoo.mp4": "Video file of a cockatoo",
183
+ "stent.npz": "Volumetric image showing a stented abdominal aorta",
184
+ "meadow_cube.jpg": "A cubemap image of a meadow, e.g. to render a skybox.",
185
+ }
186
+
187
+
188
+ class Request(object):
189
+ """ImageResource handling utility.
190
+
191
+ Represents a request for reading or saving an image resource. This
192
+ object wraps information to that request and acts as an interface
193
+ for the plugins to several resources; it allows the user to read
194
+ from filenames, files, http, zipfiles, raw bytes, etc., but offer
195
+ a simple interface to the plugins via ``get_file()`` and
196
+ ``get_local_filename()``.
197
+
198
+ For each read/write operation a single Request instance is used and passed
199
+ to the can_read/can_write method of a format, and subsequently to
200
+ the Reader/Writer class. This allows rudimentary passing of
201
+ information between different formats and between a format and
202
+ associated reader/writer.
203
+
204
+ Parameters
205
+ ----------
206
+ uri : {str, bytes, file}
207
+ The resource to load the image from.
208
+ mode : str
209
+ The first character is "r" or "w", indicating a read or write
210
+ request. The second character is used to indicate the kind of data:
211
+ "i" for an image, "I" for multiple images, "v" for a volume,
212
+ "V" for multiple volumes, "?" for don't care.
213
+
214
+ """
215
+
216
+ def __init__(self, uri, mode, *, extension=None, format_hint: str = None, **kwargs):
217
+
218
+ # General
219
+ self.raw_uri = uri
220
+ self._uri_type = None
221
+ self._filename = None
222
+ self._extension = None
223
+ self._format_hint = None
224
+ self._kwargs = kwargs
225
+ self._result = None # Some write actions may have a result
226
+
227
+ # To handle the user-side
228
+ self._filename_zip = None # not None if a zipfile is used
229
+ self._bytes = None # Incoming bytes
230
+ self._zipfile = None # To store a zipfile instance (if used)
231
+
232
+ # To handle the plugin side
233
+ self._file = None # To store the file instance
234
+ self._file_is_local = False # whether the data needs to be copied at end
235
+ self._filename_local = None # not None if using tempfile on this FS
236
+ self._firstbytes = None # For easy header parsing
237
+
238
+ # To store formats that may be able to fulfil this request
239
+ # self._potential_formats = []
240
+
241
+ # Check mode
242
+ try:
243
+ self._mode = Mode(mode)
244
+ except ValueError:
245
+ raise ValueError(f"Invalid Request.Mode: {mode}")
246
+
247
+ # Parse what was given
248
+ self._parse_uri(uri)
249
+
250
+ # Set extension
251
+ if extension is not None:
252
+ if extension[0] != ".":
253
+ raise ValueError(
254
+ "`extension` should be a file extension starting with a `.`,"
255
+ f" but is `{extension}`."
256
+ )
257
+ self._extension = extension
258
+ elif self._filename is not None:
259
+ if self._uri_type in (URI_FILENAME, URI_ZIPPED):
260
+ path = self._filename
261
+ else:
262
+ path = urlparse(self._filename).path
263
+ ext = Path(path).suffix.lower()
264
+ self._extension = ext if ext != "" else None
265
+
266
+ if format_hint is not None:
267
+ warnings.warn(
268
+ "The usage of `format_hint` is deprecated and will be removed in ImageIO v3."
269
+ " Use `extension` instead."
270
+ )
271
+
272
+ if format_hint is not None and format_hint[0] != ".":
273
+ raise ValueError(
274
+ "`format_hint` should be a file extension starting with a `.`,"
275
+ f" but is `{format_hint}`."
276
+ )
277
+
278
+ self.format_hint = format_hint
279
+
280
+ def _parse_uri(self, uri):
281
+ """Try to figure our what we were given"""
282
+ is_read_request = self.mode.io_mode is IOMode.read
283
+ is_write_request = self.mode.io_mode is IOMode.write
284
+
285
+ if isinstance(uri, str):
286
+ # Explicit
287
+ if uri.startswith("imageio:"):
288
+ if is_write_request:
289
+ raise RuntimeError("Cannot write to the standard images.")
290
+ fn = uri.split(":", 1)[-1].lower()
291
+ fn, _, zip_part = fn.partition(".zip/")
292
+ if zip_part:
293
+ fn += ".zip"
294
+ if fn not in EXAMPLE_IMAGES:
295
+ raise ValueError("Unknown standard image %r." % fn)
296
+ self._uri_type = URI_FILENAME
297
+ self._filename = get_remote_file("images/" + fn, auto=True)
298
+ if zip_part:
299
+ self._filename += "/" + zip_part
300
+ elif uri.startswith("http://") or uri.startswith("https://"):
301
+ self._uri_type = URI_HTTP
302
+ self._filename = uri
303
+ elif uri.startswith("ftp://") or uri.startswith("ftps://"):
304
+ self._uri_type = URI_FTP
305
+ self._filename = uri
306
+ elif uri.startswith("file://"):
307
+ self._uri_type = URI_FILENAME
308
+ self._filename = uri[7:]
309
+ elif uri.startswith(SPECIAL_READ_URIS) and is_read_request:
310
+ self._uri_type = URI_BYTES
311
+ self._filename = uri
312
+ elif uri.startswith(RETURN_BYTES) and is_write_request:
313
+ self._uri_type = URI_BYTES
314
+ self._filename = uri
315
+ else:
316
+ self._uri_type = URI_FILENAME
317
+ self._filename = uri
318
+
319
+ elif isinstance(uri, memoryview) and is_read_request:
320
+ self._uri_type = URI_BYTES
321
+ self._filename = "<bytes>"
322
+ self._bytes = uri.tobytes()
323
+ elif isinstance(uri, bytes) and is_read_request:
324
+ self._uri_type = URI_BYTES
325
+ self._filename = "<bytes>"
326
+ self._bytes = uri
327
+ elif isinstance(uri, Path):
328
+ self._uri_type = URI_FILENAME
329
+ self._filename = str(uri)
330
+ # Files
331
+ elif is_read_request:
332
+ if hasattr(uri, "read") and hasattr(uri, "close"):
333
+ self._uri_type = URI_FILE
334
+ self._filename = "<file>"
335
+ self._file = uri # Data must be read from here
336
+ elif is_write_request:
337
+ if hasattr(uri, "write") and hasattr(uri, "close"):
338
+ self._uri_type = URI_FILE
339
+ self._filename = "<file>"
340
+ self._file = uri # Data must be written here
341
+
342
+ # Expand user dir
343
+ if self._uri_type == URI_FILENAME and self._filename.startswith("~"):
344
+ self._filename = os.path.expanduser(self._filename)
345
+
346
+ # Check if a zipfile
347
+ if self._uri_type == URI_FILENAME:
348
+ # Search for zip extension followed by a path separater
349
+ for needle in [".zip/", ".zip\\"]:
350
+ zip_i = self._filename.lower().find(needle)
351
+ if zip_i > 0:
352
+ zip_i += 4
353
+ zip_path = self._filename[:zip_i]
354
+ if os.path.isdir(zip_path):
355
+ pass # is an existing dir (see #548)
356
+ elif is_write_request or os.path.isfile(zip_path):
357
+ self._uri_type = URI_ZIPPED
358
+ self._filename_zip = (
359
+ zip_path,
360
+ self._filename[zip_i:].lstrip("/\\"),
361
+ )
362
+ break
363
+
364
+ # Check if we could read it
365
+ if self._uri_type is None:
366
+ uri_r = repr(uri)
367
+ if len(uri_r) > 60:
368
+ uri_r = uri_r[:57] + "..."
369
+ raise IOError("Cannot understand given URI: %s." % uri_r)
370
+
371
+ # Check if this is supported
372
+ noWriting = [URI_HTTP, URI_FTP]
373
+ if is_write_request and self._uri_type in noWriting:
374
+ raise IOError("imageio does not support writing to http/ftp.")
375
+
376
+ # Deprecated way to load standard images, give a sensible error message
377
+ if is_read_request and self._uri_type in [URI_FILENAME, URI_ZIPPED]:
378
+ fn = self._filename
379
+ if self._filename_zip:
380
+ fn = self._filename_zip[0]
381
+ if (not os.path.exists(fn)) and (fn in EXAMPLE_IMAGES):
382
+ raise IOError(
383
+ "No such file: %r. This file looks like one of "
384
+ "the standard images, but from imageio 2.1, "
385
+ "standard images have to be specified using "
386
+ '"imageio:%s".' % (fn, fn)
387
+ )
388
+
389
+ # Make filename absolute
390
+ if self._uri_type in [URI_FILENAME, URI_ZIPPED]:
391
+ if self._filename_zip:
392
+ self._filename_zip = (
393
+ os.path.abspath(self._filename_zip[0]),
394
+ self._filename_zip[1],
395
+ )
396
+ else:
397
+ self._filename = os.path.abspath(self._filename)
398
+
399
+ # Check whether file name is valid
400
+ if self._uri_type in [URI_FILENAME, URI_ZIPPED]:
401
+ fn = self._filename
402
+ if self._filename_zip:
403
+ fn = self._filename_zip[0]
404
+ if is_read_request:
405
+ # Reading: check that the file exists (but is allowed a dir)
406
+ if not os.path.exists(fn):
407
+ raise FileNotFoundError("No such file: '%s'" % fn)
408
+ else:
409
+ # Writing: check that the directory to write to does exist
410
+ dn = os.path.dirname(fn)
411
+ if not os.path.exists(dn):
412
+ raise FileNotFoundError("The directory %r does not exist" % dn)
413
+
414
+ @property
415
+ def filename(self):
416
+ """Name of the ImageResource.
417
+
418
+
419
+ The uri for which reading/saving was requested. This
420
+ can be a filename, an http address, or other resource
421
+ identifier. Do not rely on the filename to obtain the data,
422
+ but use ``get_file()`` or ``get_local_filename()`` instead.
423
+ """
424
+ return self._filename
425
+
426
+ @property
427
+ def extension(self) -> str:
428
+ """The (lowercase) extension of the requested filename.
429
+ Suffixes in url's are stripped. Can be None if the request is
430
+ not based on a filename.
431
+ """
432
+ return self._extension
433
+
434
+ @property
435
+ def format_hint(self) -> Optional[str]:
436
+ return self._format_hint
437
+
438
+ @format_hint.setter
439
+ def format_hint(self, format: str) -> None:
440
+ self._format_hint = format
441
+ if self._extension is None:
442
+ self._extension = format
443
+
444
+ @property
445
+ def mode(self):
446
+ """The mode of the request. The first character is "r" or "w",
447
+ indicating a read or write request. The second character is
448
+ used to indicate the kind of data:
449
+ "i" for an image, "I" for multiple images, "v" for a volume,
450
+ "V" for multiple volumes, "?" for don't care.
451
+ """
452
+ return self._mode
453
+
454
+ @property
455
+ def kwargs(self):
456
+ """The dict of keyword arguments supplied by the user."""
457
+ return self._kwargs
458
+
459
+ # For obtaining data
460
+
461
+ def get_file(self):
462
+ """get_file()
463
+ Get a file object for the resource associated with this request.
464
+ If this is a reading request, the file is in read mode,
465
+ otherwise in write mode. This method is not thread safe. Plugins
466
+ should not close the file when done.
467
+
468
+ This is the preferred way to read/write the data. But if a
469
+ format cannot handle file-like objects, they should use
470
+ ``get_local_filename()``.
471
+ """
472
+ want_to_write = self.mode.io_mode is IOMode.write
473
+
474
+ # Is there already a file?
475
+ # Either _uri_type == URI_FILE, or we already opened the file,
476
+ # e.g. by using firstbytes
477
+ if self._file is not None:
478
+ return self._file
479
+
480
+ if self._uri_type == URI_BYTES:
481
+ if want_to_write:
482
+ # Create new file object, we catch the bytes in finish()
483
+ self._file = BytesIO()
484
+ self._file_is_local = True
485
+ else:
486
+ self._file = BytesIO(self._bytes)
487
+
488
+ elif self._uri_type == URI_FILENAME:
489
+ if want_to_write:
490
+ self._file = open(self.filename, "wb")
491
+ else:
492
+ self._file = open(self.filename, "rb")
493
+
494
+ elif self._uri_type == URI_ZIPPED:
495
+ # Get the correct filename
496
+ filename, name = self._filename_zip
497
+ if want_to_write:
498
+ # Create new file object, we catch the bytes in finish()
499
+ self._file = BytesIO()
500
+ self._file_is_local = True
501
+ else:
502
+ # Open zipfile and open new file object for specific file
503
+ self._zipfile = zipfile.ZipFile(filename, "r")
504
+ self._file = self._zipfile.open(name, "r")
505
+ self._file = SeekableFileObject(self._file)
506
+
507
+ elif self._uri_type in [URI_HTTP or URI_FTP]:
508
+ assert not want_to_write # This should have been tested in init
509
+ timeout = os.getenv("IMAGEIO_REQUEST_TIMEOUT")
510
+ if timeout is None or not timeout.isdigit():
511
+ timeout = 5
512
+ self._file = urlopen(self.filename, timeout=float(timeout))
513
+ self._file = SeekableFileObject(self._file)
514
+
515
+ return self._file
516
+
517
+ def get_local_filename(self):
518
+ """get_local_filename()
519
+ If the filename is an existing file on this filesystem, return
520
+ that. Otherwise a temporary file is created on the local file
521
+ system which can be used by the format to read from or write to.
522
+ """
523
+
524
+ if self._uri_type == URI_FILENAME:
525
+ return self._filename
526
+ else:
527
+ # Get filename
528
+ if self.extension is not None:
529
+ ext = self.extension
530
+ else:
531
+ ext = os.path.splitext(self._filename)[1]
532
+ self._filename_local = tempfile.mktemp(ext, "imageio_")
533
+ # Write stuff to it?
534
+ if self.mode.io_mode == IOMode.read:
535
+ with open(self._filename_local, "wb") as file:
536
+ shutil.copyfileobj(self.get_file(), file)
537
+ return self._filename_local
538
+
539
+ def finish(self) -> None:
540
+ """Wrap up this request.
541
+
542
+ Finishes any pending reads or writes, closes any open files and frees
543
+ any resources allocated by this request.
544
+ """
545
+
546
+ if self.mode.io_mode == IOMode.write:
547
+
548
+ # See if we "own" the data and must put it somewhere
549
+ bytes = None
550
+ if self._filename_local:
551
+ bytes = Path(self._filename_local).read_bytes()
552
+ elif self._file_is_local:
553
+ self._file_is_local = False
554
+ bytes = self._file.getvalue()
555
+
556
+ # Put the data in the right place
557
+ if bytes is not None:
558
+ if self._uri_type == URI_BYTES:
559
+ self._result = bytes # Picked up by imread function
560
+ elif self._uri_type == URI_FILE:
561
+ self._file.write(bytes)
562
+ elif self._uri_type == URI_ZIPPED:
563
+ zf = zipfile.ZipFile(self._filename_zip[0], "a")
564
+ zf.writestr(self._filename_zip[1], bytes)
565
+ zf.close()
566
+ # elif self._uri_type == URI_FILENAME: -> is always direct
567
+ # elif self._uri_type == URI_FTP/HTTP: -> write not supported
568
+
569
+ # Close open files that we know of (and are responsible for)
570
+ if self._file and self._uri_type != URI_FILE:
571
+ self._file.close()
572
+ self._file = None
573
+ if self._zipfile:
574
+ self._zipfile.close()
575
+ self._zipfile = None
576
+
577
+ # Remove temp file
578
+ if self._filename_local:
579
+ try:
580
+ os.remove(self._filename_local)
581
+ except Exception: # pragma: no cover
582
+ warnings.warn(
583
+ "Failed to delete the temporary file at "
584
+ f"`{self._filename_local}`. Please report this issue."
585
+ )
586
+ self._filename_local = None
587
+
588
+ # Detach so gc can clean even if a reference of self lingers
589
+ self._bytes = None
590
+
591
+ def get_result(self):
592
+ """For internal use. In some situations a write action can have
593
+ a result (bytes data). That is obtained with this function.
594
+ """
595
+ # Is there a reason to disallow reading multiple times?
596
+ self._result, res = None, self._result
597
+ return res
598
+
599
+ @property
600
+ def firstbytes(self):
601
+ """The first 256 bytes of the file. These can be used to
602
+ parse the header to determine the file-format.
603
+ """
604
+ if self._firstbytes is None:
605
+ self._read_first_bytes()
606
+ return self._firstbytes
607
+
608
+ def _read_first_bytes(self, N=256):
609
+ if self._bytes is not None:
610
+ self._firstbytes = self._bytes[:N]
611
+ else:
612
+ # Prepare
613
+ try:
614
+ f = self.get_file()
615
+ except IOError:
616
+ if os.path.isdir(self.filename): # A directory, e.g. for DICOM
617
+ self._firstbytes = bytes()
618
+ return
619
+ raise
620
+ try:
621
+ i = f.tell()
622
+ except Exception:
623
+ i = None
624
+ # Read
625
+ self._firstbytes = read_n_bytes(f, N)
626
+ # Set back
627
+ try:
628
+ if i is None:
629
+ raise Exception("cannot seek with None")
630
+ f.seek(i)
631
+ except Exception:
632
+ # Prevent get_file() from reusing the file
633
+ self._file = None
634
+ # If the given URI was a file object, we have a problem,
635
+ if self._uri_type == URI_FILE:
636
+ raise IOError("Cannot seek back after getting firstbytes!")
637
+
638
+
639
+ def read_n_bytes(f, N):
640
+ """read_n_bytes(file, n)
641
+
642
+ Read n bytes from the given file, or less if the file has less
643
+ bytes. Returns zero bytes if the file is closed.
644
+ """
645
+ bb = bytes()
646
+ while len(bb) < N:
647
+ extra_bytes = f.read(N - len(bb))
648
+ if not extra_bytes:
649
+ break
650
+ bb += extra_bytes
651
+ return bb
652
+
653
+
654
+ class SeekableFileObject:
655
+ """A readonly wrapper file object that add support for seeking, even if
656
+ the wrapped file object does not. The allows us to stream from http and
657
+ still use Pillow.
658
+ """
659
+
660
+ def __init__(self, f):
661
+ self.f = f
662
+ self._i = 0 # >=0 but can exceed buffer
663
+ self._buffer = b""
664
+ self._have_all = False
665
+ self.closed = False
666
+
667
+ def read(self, n=None):
668
+
669
+ # Fix up n
670
+ if n is None:
671
+ pass
672
+ else:
673
+ n = int(n)
674
+ if n < 0:
675
+ n = None
676
+
677
+ # Can and must we read more?
678
+ if not self._have_all:
679
+ more = b""
680
+ if n is None:
681
+ more = self.f.read()
682
+ self._have_all = True
683
+ else:
684
+ want_i = self._i + n
685
+ want_more = want_i - len(self._buffer)
686
+ if want_more > 0:
687
+ more = self.f.read(want_more)
688
+ if len(more) < want_more:
689
+ self._have_all = True
690
+ self._buffer += more
691
+
692
+ # Read data from buffer and update pointer
693
+ if n is None:
694
+ res = self._buffer[self._i :]
695
+ else:
696
+ res = self._buffer[self._i : self._i + n]
697
+ self._i += len(res)
698
+
699
+ return res
700
+
701
+ def tell(self):
702
+ return self._i
703
+
704
+ def seek(self, i, mode=0):
705
+ # Mimic BytesIO behavior
706
+
707
+ # Get the absolute new position
708
+ i = int(i)
709
+ if mode == 0:
710
+ if i < 0:
711
+ raise ValueError("negative seek value " + str(i))
712
+ real_i = i
713
+ elif mode == 1:
714
+ real_i = max(0, self._i + i) # negative ok here
715
+ elif mode == 2:
716
+ if not self._have_all:
717
+ self.read()
718
+ real_i = max(0, len(self._buffer) + i)
719
+ else:
720
+ raise ValueError("invalid whence (%s, should be 0, 1 or 2)" % i)
721
+
722
+ # Read some?
723
+ if real_i <= len(self._buffer):
724
+ pass # no need to read
725
+ elif not self._have_all:
726
+ assert real_i > self._i # if we don't have all, _i cannot be > _buffer
727
+ self.read(real_i - self._i) # sets self._i
728
+
729
+ self._i = real_i
730
+ return self._i
731
+
732
+ def close(self):
733
+ self.closed = True
734
+ self.f.close()
735
+
736
+ def isatty(self):
737
+ return False
738
+
739
+ def seekable(self):
740
+ return True
741
+
742
+
743
+ class InitializationError(Exception):
744
+ """The plugin could not initialize from the given request.
745
+
746
+ This is a _internal_ error that is raised by plugins that fail to handle
747
+ a given request. We use this to differentiate incompatibility between
748
+ a plugin and a request from an actual error/bug inside a plugin.
749
+
750
+ """
751
+
752
+ pass
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/core/v3_plugin_api.py ADDED
@@ -0,0 +1,367 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from . import Request
2
+ from ..typing import ArrayLike
3
+ import numpy as np
4
+ from typing import Optional, Dict, Any, Tuple, Union, List, Iterator
5
+ from dataclasses import dataclass
6
+
7
+
8
+ @dataclass
9
+ class ImageProperties:
10
+ """Standardized Metadata
11
+
12
+ ImageProperties represent a set of standardized metadata that is available
13
+ under the same name for every supported format. If the ImageResource (or
14
+ format) does not specify the value, a sensible default value is chosen
15
+ instead.
16
+
17
+ Attributes
18
+ ----------
19
+ shape : Tuple[int, ...]
20
+ The shape of the loaded ndimage.
21
+ dtype : np.dtype
22
+ The dtype of the loaded ndimage.
23
+ is_batch : bool
24
+ If True, the first dimension of the ndimage represents a batch dimension
25
+ along which several images are stacked.
26
+ spacing : Tuple
27
+ A tuple describing the spacing between pixels along each axis of the
28
+ ndimage. If the spacing is uniform along an axis the value corresponding
29
+ to that axis is a single float. If the spacing is non-uniform, the value
30
+ corresponding to that axis is a tuple in which the i-th element
31
+ indicates the spacing between the i-th and (i+1)-th pixel along that
32
+ axis.
33
+
34
+ """
35
+
36
+ shape: Tuple[int, ...]
37
+ dtype: np.dtype
38
+ is_batch: bool = False
39
+ spacing: Optional[tuple] = None
40
+
41
+
42
+ class PluginV3:
43
+ """A ImageIO Plugin.
44
+
45
+ This is an abstract plugin that documents the v3 plugin API interface. A
46
+ plugin is an adapter/wrapper around a backend that converts a request from
47
+ iio.core (e.g., read an image from file) into a sequence of instructions for
48
+ the backend that fullfill the request.
49
+
50
+ Plugin authors may choose to subclass this class when implementing a new
51
+ plugin, but aren't obliged to do so. As long as the plugin class implements
52
+ the interface (methods) described below the ImageIO core will treat it just
53
+ like any other plugin.
54
+
55
+
56
+ Parameters
57
+ ----------
58
+ request : iio.Request
59
+ A request object that represents the users intent. It provides a
60
+ standard interface to access the various ImageResources and serves them
61
+ to the plugin as a file object (or file). Check the docs for details.
62
+ **kwargs : Any
63
+ Additional configuration arguments for the plugin or backend. Usually
64
+ these match the configuration arguments available on the backend and
65
+ are forwarded to it.
66
+
67
+
68
+ Raises
69
+ ------
70
+ InitializationError
71
+ During ``__init__`` the plugin tests if it can fulfill the request. If
72
+ it can't, e.g., because the request points to a file in the wrong
73
+ format, then it should raise an ``InitializationError`` and provide a
74
+ reason for failure. This reason may be reported to the user.
75
+ ImportError
76
+ Plugins will be imported dynamically when listed in
77
+ ``iio.config.known_plugins`` to fullfill requests. This way, users only
78
+ have to load plugins/backends they actually use. If this plugin's backend
79
+ is not installed, it should raise an ``ImportError`` either during
80
+ module import or during class construction.
81
+
82
+ Notes
83
+ -----
84
+ Upon successful construction the plugin takes ownership of the provided
85
+ request. This means that it is the plugin's responsibility to call
86
+ request.finish() to close the resource when it is no longer needed.
87
+
88
+ Plugins _must_ implement a context manager that closes and cleans any
89
+ resources held by the plugin upon exit.
90
+
91
+ """
92
+
93
+ def __init__(self, request: Request) -> None:
94
+ """Initialize a new Plugin Instance.
95
+
96
+ See Plugin's docstring for detailed documentation.
97
+
98
+ Notes
99
+ -----
100
+ The implementation here stores the request as a local variable that is
101
+ exposed using a @property below. If you inherit from PluginV3, remember
102
+ to call ``super().__init__(request)``.
103
+
104
+ """
105
+
106
+ self._request = request
107
+
108
+ def read(self, *, index: int = 0) -> np.ndarray:
109
+ """Read a ndimage.
110
+
111
+ The ``read`` method loads a (single) ndimage, located at ``index`` from
112
+ the requested ImageResource.
113
+
114
+ It is at the plugin's descretion to decide (and document) what
115
+ constitutes a single ndimage. A sensible way to make this decision is to
116
+ choose based on the ImageResource's format and on what users will expect
117
+ from such a format. For example, a sensible choice for a TIFF file
118
+ produced by an ImageJ hyperstack is to read it as a volumetric ndimage
119
+ (1 color dimension followed by 3 spatial dimensions). On the other hand,
120
+ a sensible choice for a MP4 file produced by Davinci Resolve is to treat
121
+ each frame as a ndimage (2 spatial dimensions followed by 1 color
122
+ dimension).
123
+
124
+ The value ``index=None`` is special. It requests the plugin to load all
125
+ ndimages in the file and stack them along a new first axis. For example,
126
+ if a MP4 file is read with ``index=None`` and the plugin identifies
127
+ single frames as ndimages, then the plugin should read all frames and
128
+ stack them into a new ndimage which now contains a time axis as its
129
+ first axis. If a PNG file (single image format) is read with
130
+ ``index=None`` the plugin does a very similar thing: It loads all
131
+ ndimages in the file (here it's just one) and stacks them along a new
132
+ first axis, effectively prepending an axis with size 1 to the image. If
133
+ a plugin does not wish to support ``index=None`` it should set a more
134
+ sensible default and raise a ``ValueError`` when requested to read using
135
+ ``index=None``.
136
+
137
+ Parameters
138
+ ----------
139
+ index : int
140
+ If the ImageResource contains multiple ndimages, and index is an
141
+ integer, select the index-th ndimage from among them and return it.
142
+ If index is an ellipsis (...), read all ndimages in the file and
143
+ stack them along a new batch dimension. If index is None, let the
144
+ plugin decide. If the index is out of bounds a ``ValueError`` is
145
+ raised.
146
+ **kwargs : Any
147
+ The read method may accept any number of plugin-specific keyword
148
+ arguments to further customize the read behavior. Usually these
149
+ match the arguments available on the backend and are forwarded to
150
+ it.
151
+
152
+ Returns
153
+ -------
154
+ ndimage : np.ndarray
155
+ A ndimage containing decoded pixel data (sometimes called bitmap).
156
+
157
+ Notes
158
+ -----
159
+ The ImageResource from which the plugin should read is managed by the
160
+ provided request object. Directly accessing the managed ImageResource is
161
+ _not_ permitted. Instead, you can get FileLike access to the
162
+ ImageResource via request.get_file().
163
+
164
+ If the backend doesn't support reading from FileLike objects, you can
165
+ request a temporary file to pass to the backend via
166
+ ``request.get_local_filename()``. This is, however, not very performant
167
+ (involves copying the Request's content into a temporary file), so you
168
+ should avoid doing this whenever possible. Consider it a fallback method
169
+ in case all else fails.
170
+
171
+ """
172
+ raise NotImplementedError()
173
+
174
+ def write(self, ndimage: Union[ArrayLike, List[ArrayLike]]) -> Optional[bytes]:
175
+ """Write a ndimage to a ImageResource.
176
+
177
+ The ``write`` method encodes the given ndimage into the format handled
178
+ by the backend and writes it to the ImageResource. It overwrites
179
+ any content that may have been previously stored in the file.
180
+
181
+ If the backend supports only a single format then it must check if
182
+ the ImageResource matches that format and raise an exception if not.
183
+ Typically, this should be done during initialization in the form of a
184
+ ``InitializationError``.
185
+
186
+ If the backend supports more than one format it must determine the
187
+ requested/desired format. Usually this can be done by inspecting the
188
+ ImageResource (e.g., by checking ``request.extension``), or by providing
189
+ a mechanism to explicitly set the format (perhaps with a - sensible -
190
+ default value). If the plugin can not determine the desired format, it
191
+ **must not** write to the ImageResource, but raise an exception instead.
192
+
193
+ If the backend supports at least one format that can hold multiple
194
+ ndimages it should be capable of handling ndimage batches and lists of
195
+ ndimages. If the ``ndimage`` input is a list of ndimages, the plugin
196
+ should not assume that the ndimages are not stackable, i.e., ndimages
197
+ may have different shapes. Otherwise, the ``ndimage`` may be a batch of
198
+ multiple ndimages stacked along the first axis of the array. The plugin
199
+ must be able to discover this, either automatically or via additional
200
+ `kwargs`. If there is ambiguity in the process, the plugin must clearly
201
+ document what happens in such cases and, if possible, describe how to
202
+ resolve this ambiguity.
203
+
204
+ Parameters
205
+ ----------
206
+ ndimage : ArrayLike
207
+ The ndimage to encode and write to the current ImageResource.
208
+ **kwargs : Any
209
+ The write method may accept any number of plugin-specific keyword
210
+ arguments to customize the writing behavior. Usually these match the
211
+ arguments available on the backend and are forwarded to it.
212
+
213
+ Returns
214
+ -------
215
+ encoded_image : bytes or None
216
+ If the chosen ImageResource is the special target ``"<bytes>"`` then
217
+ write should return a byte string containing the encoded image data.
218
+ Otherwise, it returns None.
219
+
220
+ Notes
221
+ -----
222
+ The ImageResource to which the plugin should write to is managed by the
223
+ provided request object. Directly accessing the managed ImageResource is
224
+ _not_ permitted. Instead, you can get FileLike access to the
225
+ ImageResource via request.get_file().
226
+
227
+ If the backend doesn't support writing to FileLike objects, you can
228
+ request a temporary file to pass to the backend via
229
+ ``request.get_local_filename()``. This is, however, not very performant
230
+ (involves copying the Request's content from a temporary file), so you
231
+ should avoid doing this whenever possible. Consider it a fallback method
232
+ in case all else fails.
233
+
234
+ """
235
+ raise NotImplementedError()
236
+
237
+ def iter(self) -> Iterator[np.ndarray]:
238
+ """Iterate the ImageResource.
239
+
240
+ This method returns a generator that yields ndimages in the order in which
241
+ they appear in the file. This is roughly equivalent to::
242
+
243
+ idx = 0
244
+ while True:
245
+ try:
246
+ yield self.read(index=idx)
247
+ except ValueError:
248
+ break
249
+
250
+ It works very similar to ``read``, and you can consult the documentation
251
+ of that method for additional information on desired behavior.
252
+
253
+ Parameters
254
+ ----------
255
+ **kwargs : Any
256
+ The iter method may accept any number of plugin-specific keyword
257
+ arguments to further customize the reading/iteration behavior.
258
+ Usually these match the arguments available on the backend and are
259
+ forwarded to it.
260
+
261
+ Yields
262
+ ------
263
+ ndimage : np.ndarray
264
+ A ndimage containing decoded pixel data (sometimes called bitmap).
265
+
266
+ See Also
267
+ --------
268
+ PluginV3.read
269
+
270
+ """
271
+ raise NotImplementedError()
272
+
273
+ def properties(self, index: int = 0) -> ImageProperties:
274
+ """Standardized ndimage metadata.
275
+
276
+ Parameters
277
+ ----------
278
+ index : int
279
+ If the ImageResource contains multiple ndimages, and index is an
280
+ integer, select the index-th ndimage from among them and return its
281
+ properties. If index is an ellipsis (...), read all ndimages in the file
282
+ and stack them along a new batch dimension and return their properties.
283
+ If index is None, the plugin decides the default.
284
+
285
+ Returns
286
+ -------
287
+ properties : ImageProperties
288
+ A dataclass filled with standardized image metadata.
289
+
290
+ """
291
+ raise NotImplementedError()
292
+
293
+ def metadata(self, index: int = 0, exclude_applied: bool = True) -> Dict[str, Any]:
294
+ """Format-Specific ndimage metadata.
295
+
296
+ The method reads metadata stored in the ImageResource and returns it as
297
+ a python dict. The plugin is free to choose which name to give a piece
298
+ of metadata; however, if possible, it should match the name given by the
299
+ format. There is no requirement regarding the fields a plugin must
300
+ expose; however, if a plugin does expose any,``exclude_applied`` applies
301
+ to these fields.
302
+
303
+ If the plugin does return metadata items, it must check the value of
304
+ ``exclude_applied`` before returning them. If ``exclude applied`` is
305
+ True, then any metadata item that would be applied to an ndimage
306
+ returned by ``read`` (or ``iter``) must not be returned. This is done to
307
+ avoid confusion; for example, if an ImageResource defines the ExIF
308
+ rotation tag, and the plugin applies the rotation to the data before
309
+ returning it, then ``exclude_applied`` prevents confusion on whether the
310
+ tag was already applied or not.
311
+
312
+ The `kwarg` ``index`` behaves similar to its counterpart in ``read``
313
+ with one exception: If the ``index`` is None, then global metadata is
314
+ returned instead of returning a combination of all metadata items. If
315
+ there is no global metadata, the Plugin should return an empty dict or
316
+ raise an exception.
317
+
318
+ Parameters
319
+ ----------
320
+ index : int
321
+ If the ImageResource contains multiple ndimages, and index is an
322
+ integer, select the index-th ndimage from among them and return its
323
+ metadata. If index is an ellipsis (...), return global metadata. If
324
+ index is None, the plugin decides the default.
325
+ exclude_applied : bool
326
+ If True (default), do not report metadata fields that the plugin
327
+ would apply/consume while reading the image.
328
+
329
+ Returns
330
+ -------
331
+ metadata : dict
332
+ A dictionary filled with format-specific metadata fields and their
333
+ values.
334
+
335
+ """
336
+ raise NotImplementedError()
337
+
338
+ def close(self) -> None:
339
+ """Close the ImageResource.
340
+
341
+ This method allows a plugin to behave similar to the python build-in ``open``::
342
+
343
+ image_file = my_plugin(Request, "r")
344
+ ...
345
+ image_file.close()
346
+
347
+ It is used by the context manager and deconstructor below to avoid leaking
348
+ ImageResources. If the plugin has no other cleanup to do it doesn't have
349
+ to overwrite this method itself and can rely on the implementation
350
+ below.
351
+
352
+ """
353
+
354
+ self.request.finish()
355
+
356
+ @property
357
+ def request(self) -> Request:
358
+ return self._request
359
+
360
+ def __enter__(self) -> "PluginV3":
361
+ return self
362
+
363
+ def __exit__(self, type, value, traceback) -> None:
364
+ self.close()
365
+
366
+ def __del__(self) -> None:
367
+ self.close()
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/plugins/__pycache__/__init__.cpython-38.pyc ADDED
Binary file (3.85 kB). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/plugins/__pycache__/_bsdf.cpython-38.pyc ADDED
Binary file (25.3 kB). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/plugins/__pycache__/_dicom.cpython-38.pyc ADDED
Binary file (22.9 kB). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/plugins/__pycache__/_freeimage.cpython-38.pyc ADDED
Binary file (28.4 kB). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/plugins/__pycache__/_swf.cpython-38.pyc ADDED
Binary file (20.6 kB). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/plugins/__pycache__/feisem.cpython-38.pyc ADDED
Binary file (3.01 kB). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/plugins/__pycache__/fits.cpython-38.pyc ADDED
Binary file (4.72 kB). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/plugins/__pycache__/freeimage.cpython-38.pyc ADDED
Binary file (14.1 kB). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/plugins/__pycache__/gdal.cpython-38.pyc ADDED
Binary file (2.37 kB). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/plugins/__pycache__/lytro.cpython-38.pyc ADDED
Binary file (16.7 kB). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/plugins/__pycache__/npz.cpython-38.pyc ADDED
Binary file (3.44 kB). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/plugins/__pycache__/opencv.cpython-38.pyc ADDED
Binary file (10.9 kB). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/plugins/__pycache__/pillow.cpython-38.pyc ADDED
Binary file (14.1 kB). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/plugins/__pycache__/pillow_info.cpython-38.pyc ADDED
Binary file (35.5 kB). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/plugins/__pycache__/pillow_legacy.cpython-38.pyc ADDED
Binary file (24 kB). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/plugins/__pycache__/pillowmulti.cpython-38.pyc ADDED
Binary file (8.76 kB). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/plugins/__pycache__/simpleitk.cpython-38.pyc ADDED
Binary file (3.96 kB). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/plugins/__pycache__/swf.cpython-38.pyc ADDED
Binary file (8.73 kB). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/plugins/__pycache__/tifffile.cpython-38.pyc ADDED
Binary file (17.7 kB). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/plugins/_dicom.py ADDED
@@ -0,0 +1,925 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ # imageio is distributed under the terms of the (new) BSD License.
3
+
4
+ """ Plugin for reading DICOM files.
5
+ """
6
+
7
+ # todo: Use pydicom:
8
+ # * Note: is not py3k ready yet
9
+ # * Allow reading the full meta info
10
+ # I think we can more or less replace the SimpleDicomReader with a
11
+ # pydicom.Dataset For series, only ned to read the full info from one
12
+ # file: speed still high
13
+ # * Perhaps allow writing?
14
+
15
+ import sys
16
+ import os
17
+ import struct
18
+ import logging
19
+
20
+ import numpy as np
21
+
22
+
23
+ logger = logging.getLogger(__name__)
24
+
25
+ # Determine endianity of system
26
+ sys_is_little_endian = sys.byteorder == "little"
27
+
28
+ # Define a dictionary that contains the tags that we would like to know
29
+ MINIDICT = {
30
+ (0x7FE0, 0x0010): ("PixelData", "OB"),
31
+ # Date and time
32
+ (0x0008, 0x0020): ("StudyDate", "DA"),
33
+ (0x0008, 0x0021): ("SeriesDate", "DA"),
34
+ (0x0008, 0x0022): ("AcquisitionDate", "DA"),
35
+ (0x0008, 0x0023): ("ContentDate", "DA"),
36
+ (0x0008, 0x0030): ("StudyTime", "TM"),
37
+ (0x0008, 0x0031): ("SeriesTime", "TM"),
38
+ (0x0008, 0x0032): ("AcquisitionTime", "TM"),
39
+ (0x0008, 0x0033): ("ContentTime", "TM"),
40
+ # With what, where, by whom?
41
+ (0x0008, 0x0060): ("Modality", "CS"),
42
+ (0x0008, 0x0070): ("Manufacturer", "LO"),
43
+ (0x0008, 0x0080): ("InstitutionName", "LO"),
44
+ # Descriptions
45
+ (0x0008, 0x1030): ("StudyDescription", "LO"),
46
+ (0x0008, 0x103E): ("SeriesDescription", "LO"),
47
+ # UID's
48
+ (0x0008, 0x0016): ("SOPClassUID", "UI"),
49
+ (0x0008, 0x0018): ("SOPInstanceUID", "UI"),
50
+ (0x0020, 0x000D): ("StudyInstanceUID", "UI"),
51
+ (0x0020, 0x000E): ("SeriesInstanceUID", "UI"),
52
+ (0x0008, 0x0117): ("ContextUID", "UI"),
53
+ # Numbers
54
+ (0x0020, 0x0011): ("SeriesNumber", "IS"),
55
+ (0x0020, 0x0012): ("AcquisitionNumber", "IS"),
56
+ (0x0020, 0x0013): ("InstanceNumber", "IS"),
57
+ (0x0020, 0x0014): ("IsotopeNumber", "IS"),
58
+ (0x0020, 0x0015): ("PhaseNumber", "IS"),
59
+ (0x0020, 0x0016): ("IntervalNumber", "IS"),
60
+ (0x0020, 0x0017): ("TimeSlotNumber", "IS"),
61
+ (0x0020, 0x0018): ("AngleNumber", "IS"),
62
+ (0x0020, 0x0019): ("ItemNumber", "IS"),
63
+ (0x0020, 0x0020): ("PatientOrientation", "CS"),
64
+ (0x0020, 0x0030): ("ImagePosition", "CS"),
65
+ (0x0020, 0x0032): ("ImagePositionPatient", "CS"),
66
+ (0x0020, 0x0035): ("ImageOrientation", "CS"),
67
+ (0x0020, 0x0037): ("ImageOrientationPatient", "CS"),
68
+ # Patient information
69
+ (0x0010, 0x0010): ("PatientName", "PN"),
70
+ (0x0010, 0x0020): ("PatientID", "LO"),
71
+ (0x0010, 0x0030): ("PatientBirthDate", "DA"),
72
+ (0x0010, 0x0040): ("PatientSex", "CS"),
73
+ (0x0010, 0x1010): ("PatientAge", "AS"),
74
+ (0x0010, 0x1020): ("PatientSize", "DS"),
75
+ (0x0010, 0x1030): ("PatientWeight", "DS"),
76
+ # Image specific (required to construct numpy array)
77
+ (0x0028, 0x0002): ("SamplesPerPixel", "US"),
78
+ (0x0028, 0x0008): ("NumberOfFrames", "IS"),
79
+ (0x0028, 0x0100): ("BitsAllocated", "US"),
80
+ (0x0028, 0x0101): ("BitsStored", "US"),
81
+ (0x0028, 0x0102): ("HighBit", "US"),
82
+ (0x0028, 0x0103): ("PixelRepresentation", "US"),
83
+ (0x0028, 0x0010): ("Rows", "US"),
84
+ (0x0028, 0x0011): ("Columns", "US"),
85
+ (0x0028, 0x1052): ("RescaleIntercept", "DS"),
86
+ (0x0028, 0x1053): ("RescaleSlope", "DS"),
87
+ # Image specific (for the user)
88
+ (0x0028, 0x0030): ("PixelSpacing", "DS"),
89
+ (0x0018, 0x0088): ("SliceSpacing", "DS"),
90
+ }
91
+
92
+ # Define some special tags:
93
+ # See PS 3.5-2008 section 7.5 (p.40)
94
+ ItemTag = (0xFFFE, 0xE000) # start of Sequence Item
95
+ ItemDelimiterTag = (0xFFFE, 0xE00D) # end of Sequence Item
96
+ SequenceDelimiterTag = (0xFFFE, 0xE0DD) # end of Sequence of undefined length
97
+
98
+ # Define set of groups that we're interested in (so we can quickly skip others)
99
+ GROUPS = set([key[0] for key in MINIDICT.keys()])
100
+ VRS = set([val[1] for val in MINIDICT.values()])
101
+
102
+
103
+ class NotADicomFile(Exception):
104
+ pass
105
+
106
+
107
+ class CompressedDicom(RuntimeError):
108
+ pass
109
+
110
+
111
+ class SimpleDicomReader(object):
112
+ """
113
+ This class provides reading of pixel data from DICOM files. It is
114
+ focussed on getting the pixel data, not the meta info.
115
+
116
+ To use, first create an instance of this class (giving it
117
+ a file object or filename). Next use the info attribute to
118
+ get a dict of the meta data. The loading of pixel data is
119
+ deferred until get_numpy_array() is called.
120
+
121
+ Comparison with Pydicom
122
+ -----------------------
123
+
124
+ This code focusses on getting the pixel data out, which allows some
125
+ shortcuts, resulting in the code being much smaller.
126
+
127
+ Since the processing of data elements is much cheaper (it skips a lot
128
+ of tags), this code is about 3x faster than pydicom (except for the
129
+ deflated DICOM files).
130
+
131
+ This class does borrow some code (and ideas) from the pydicom
132
+ project, and (to the best of our knowledge) has the same limitations
133
+ as pydicom with regard to the type of files that it can handle.
134
+
135
+ Limitations
136
+ -----------
137
+
138
+ For more advanced DICOM processing, please check out pydicom.
139
+
140
+ * Only a predefined subset of data elements (meta information) is read.
141
+ * This is a reader; it can not write DICOM files.
142
+ * (just like pydicom) it can handle none of the compressed DICOM
143
+ formats except for "Deflated Explicit VR Little Endian"
144
+ (1.2.840.10008.1.2.1.99).
145
+
146
+ """
147
+
148
+ def __init__(self, file):
149
+ # Open file if filename given
150
+ if isinstance(file, str):
151
+ self._filename = file
152
+ self._file = open(file, "rb")
153
+ else:
154
+ self._filename = "<unknown file>"
155
+ self._file = file
156
+ # Init variable to store position and size of pixel data
157
+ self._pixel_data_loc = None
158
+ # The meta header is always explicit and little endian
159
+ self.is_implicit_VR = False
160
+ self.is_little_endian = True
161
+ self._unpackPrefix = "<"
162
+ # Dict to store data elements of interest in
163
+ self._info = {}
164
+ # VR Conversion
165
+ self._converters = {
166
+ # Numbers
167
+ "US": lambda x: self._unpack("H", x),
168
+ "UL": lambda x: self._unpack("L", x),
169
+ # Numbers encoded as strings
170
+ "DS": lambda x: self._splitValues(x, float, "\\"),
171
+ "IS": lambda x: self._splitValues(x, int, "\\"),
172
+ # strings
173
+ "AS": lambda x: x.decode("ascii", "ignore").strip("\x00"),
174
+ "DA": lambda x: x.decode("ascii", "ignore").strip("\x00"),
175
+ "TM": lambda x: x.decode("ascii", "ignore").strip("\x00"),
176
+ "UI": lambda x: x.decode("ascii", "ignore").strip("\x00"),
177
+ "LO": lambda x: x.decode("utf-8", "ignore").strip("\x00").rstrip(),
178
+ "CS": lambda x: self._splitValues(x, float, "\\"),
179
+ "PN": lambda x: x.decode("utf-8", "ignore").strip("\x00").rstrip(),
180
+ }
181
+
182
+ # Initiate reading
183
+ self._read()
184
+
185
+ @property
186
+ def info(self):
187
+ return self._info
188
+
189
+ def _splitValues(self, x, type, splitter):
190
+ s = x.decode("ascii").strip("\x00")
191
+ try:
192
+ if splitter in s:
193
+ return tuple([type(v) for v in s.split(splitter) if v.strip()])
194
+ else:
195
+ return type(s)
196
+ except ValueError:
197
+ return s
198
+
199
+ def _unpack(self, fmt, value):
200
+ return struct.unpack(self._unpackPrefix + fmt, value)[0]
201
+
202
+ # Really only so we need minimal changes to _pixel_data_numpy
203
+ def __iter__(self):
204
+ return iter(self._info.keys())
205
+
206
+ def __getattr__(self, key):
207
+ info = object.__getattribute__(self, "_info")
208
+ if key in info:
209
+ return info[key]
210
+ return object.__getattribute__(self, key) # pragma: no cover
211
+
212
+ def _read(self):
213
+ f = self._file
214
+ # Check prefix after peamble
215
+ f.seek(128)
216
+ if f.read(4) != b"DICM":
217
+ raise NotADicomFile("Not a valid DICOM file.")
218
+ # Read
219
+ self._read_header()
220
+ self._read_data_elements()
221
+ self._get_shape_and_sampling()
222
+ # Close if done, reopen if necessary to read pixel data
223
+ if os.path.isfile(self._filename):
224
+ self._file.close()
225
+ self._file = None
226
+
227
+ def _readDataElement(self):
228
+ f = self._file
229
+ # Get group and element
230
+ group = self._unpack("H", f.read(2))
231
+ element = self._unpack("H", f.read(2))
232
+ # Get value length
233
+ if self.is_implicit_VR:
234
+ vl = self._unpack("I", f.read(4))
235
+ else:
236
+ vr = f.read(2)
237
+ if vr in (b"OB", b"OW", b"SQ", b"UN"):
238
+ reserved = f.read(2) # noqa
239
+ vl = self._unpack("I", f.read(4))
240
+ else:
241
+ vl = self._unpack("H", f.read(2))
242
+ # Get value
243
+ if group == 0x7FE0 and element == 0x0010:
244
+ here = f.tell()
245
+ self._pixel_data_loc = here, vl
246
+ f.seek(here + vl)
247
+ return group, element, b"Deferred loading of pixel data"
248
+ else:
249
+ if vl == 0xFFFFFFFF:
250
+ value = self._read_undefined_length_value()
251
+ else:
252
+ value = f.read(vl)
253
+ return group, element, value
254
+
255
+ def _read_undefined_length_value(self, read_size=128):
256
+ """Copied (in compacted form) from PyDicom
257
+ Copyright Darcy Mason.
258
+ """
259
+ fp = self._file
260
+ # data_start = fp.tell()
261
+ search_rewind = 3
262
+ bytes_to_find = struct.pack(
263
+ self._unpackPrefix + "HH", SequenceDelimiterTag[0], SequenceDelimiterTag[1]
264
+ )
265
+
266
+ found = False
267
+ value_chunks = []
268
+ while not found:
269
+ chunk_start = fp.tell()
270
+ bytes_read = fp.read(read_size)
271
+ if len(bytes_read) < read_size:
272
+ # try again,
273
+ # if still don't get required amount, this is last block
274
+ new_bytes = fp.read(read_size - len(bytes_read))
275
+ bytes_read += new_bytes
276
+ if len(bytes_read) < read_size:
277
+ raise EOFError(
278
+ "End of file reached before sequence " "delimiter found."
279
+ )
280
+ index = bytes_read.find(bytes_to_find)
281
+ if index != -1:
282
+ found = True
283
+ value_chunks.append(bytes_read[:index])
284
+ fp.seek(chunk_start + index + 4) # rewind to end of delimiter
285
+ length = fp.read(4)
286
+ if length != b"\0\0\0\0":
287
+ logger.warning(
288
+ "Expected 4 zero bytes after undefined length " "delimiter"
289
+ )
290
+ else:
291
+ fp.seek(fp.tell() - search_rewind) # rewind a bit
292
+ # accumulate the bytes read (not including the rewind)
293
+ value_chunks.append(bytes_read[:-search_rewind])
294
+
295
+ # if get here then have found the byte string
296
+ return b"".join(value_chunks)
297
+
298
+ def _read_header(self):
299
+ f = self._file
300
+ TransferSyntaxUID = None
301
+
302
+ # Read all elements, store transferSyntax when we encounter it
303
+ try:
304
+ while True:
305
+ fp_save = f.tell()
306
+ # Get element
307
+ group, element, value = self._readDataElement()
308
+ if group == 0x02:
309
+ if group == 0x02 and element == 0x10:
310
+ TransferSyntaxUID = value.decode("ascii").strip("\x00")
311
+ else:
312
+ # No more group 2: rewind and break
313
+ # (don't trust group length)
314
+ f.seek(fp_save)
315
+ break
316
+ except (EOFError, struct.error): # pragma: no cover
317
+ raise RuntimeError("End of file reached while still in header.")
318
+
319
+ # Handle transfer syntax
320
+ self._info["TransferSyntaxUID"] = TransferSyntaxUID
321
+ #
322
+ if TransferSyntaxUID is None:
323
+ # Assume ExplicitVRLittleEndian
324
+ is_implicit_VR, is_little_endian = False, True
325
+ elif TransferSyntaxUID == "1.2.840.10008.1.2.1":
326
+ # ExplicitVRLittleEndian
327
+ is_implicit_VR, is_little_endian = False, True
328
+ elif TransferSyntaxUID == "1.2.840.10008.1.2.2":
329
+ # ExplicitVRBigEndian
330
+ is_implicit_VR, is_little_endian = False, False
331
+ elif TransferSyntaxUID == "1.2.840.10008.1.2":
332
+ # implicit VR little endian
333
+ is_implicit_VR, is_little_endian = True, True
334
+ elif TransferSyntaxUID == "1.2.840.10008.1.2.1.99":
335
+ # DeflatedExplicitVRLittleEndian:
336
+ is_implicit_VR, is_little_endian = False, True
337
+ self._inflate()
338
+ else:
339
+ # http://www.dicomlibrary.com/dicom/transfer-syntax/
340
+ t, extra_info = TransferSyntaxUID, ""
341
+ if "1.2.840.10008.1.2.4.50" <= t < "1.2.840.10008.1.2.4.99":
342
+ extra_info = " (JPEG)"
343
+ if "1.2.840.10008.1.2.4.90" <= t < "1.2.840.10008.1.2.4.99":
344
+ extra_info = " (JPEG 2000)"
345
+ if t == "1.2.840.10008.1.2.5":
346
+ extra_info = " (RLE)"
347
+ if t == "1.2.840.10008.1.2.6.1":
348
+ extra_info = " (RFC 2557)"
349
+ raise CompressedDicom(
350
+ "The dicom reader can only read files with "
351
+ "uncompressed image data - not %r%s. You "
352
+ "can try using dcmtk or gdcm to convert the "
353
+ "image." % (t, extra_info)
354
+ )
355
+
356
+ # From hereon, use implicit/explicit big/little endian
357
+ self.is_implicit_VR = is_implicit_VR
358
+ self.is_little_endian = is_little_endian
359
+ self._unpackPrefix = "><"[is_little_endian]
360
+
361
+ def _read_data_elements(self):
362
+ info = self._info
363
+ try:
364
+ while True:
365
+ # Get element
366
+ group, element, value = self._readDataElement()
367
+ # Is it a group we are interested in?
368
+ if group in GROUPS:
369
+ key = (group, element)
370
+ name, vr = MINIDICT.get(key, (None, None))
371
+ # Is it an element we are interested in?
372
+ if name:
373
+ # Store value
374
+ converter = self._converters.get(vr, lambda x: x)
375
+ info[name] = converter(value)
376
+ except (EOFError, struct.error):
377
+ pass # end of file ...
378
+
379
+ def get_numpy_array(self):
380
+ """Get numpy arra for this DICOM file, with the correct shape,
381
+ and pixel values scaled appropriately.
382
+ """
383
+ # Is there pixel data at all?
384
+ if "PixelData" not in self:
385
+ raise TypeError("No pixel data found in this dataset.")
386
+
387
+ # Load it now if it was not already loaded
388
+ if self._pixel_data_loc and len(self.PixelData) < 100:
389
+ # Reopen file?
390
+ close_file = False
391
+ if self._file is None:
392
+ close_file = True
393
+ self._file = open(self._filename, "rb")
394
+ # Read data
395
+ self._file.seek(self._pixel_data_loc[0])
396
+ if self._pixel_data_loc[1] == 0xFFFFFFFF:
397
+ value = self._read_undefined_length_value()
398
+ else:
399
+ value = self._file.read(self._pixel_data_loc[1])
400
+ # Close file
401
+ if close_file:
402
+ self._file.close()
403
+ self._file = None
404
+ # Overwrite
405
+ self._info["PixelData"] = value
406
+
407
+ # Get data
408
+ data = self._pixel_data_numpy()
409
+ data = self._apply_slope_and_offset(data)
410
+
411
+ # Remove data again to preserve memory
412
+ # Note that the data for the original file is loaded twice ...
413
+ self._info["PixelData"] = (
414
+ b"Data converted to numpy array, " + b"raw data removed to preserve memory"
415
+ )
416
+ return data
417
+
418
+ def _get_shape_and_sampling(self):
419
+ """Get shape and sampling without actuall using the pixel data.
420
+ In this way, the user can get an idea what's inside without having
421
+ to load it.
422
+ """
423
+ # Get shape (in the same way that pydicom does)
424
+ if "NumberOfFrames" in self and self.NumberOfFrames > 1:
425
+ if self.SamplesPerPixel > 1:
426
+ shape = (
427
+ self.SamplesPerPixel,
428
+ self.NumberOfFrames,
429
+ self.Rows,
430
+ self.Columns,
431
+ )
432
+ else:
433
+ shape = self.NumberOfFrames, self.Rows, self.Columns
434
+ elif "SamplesPerPixel" in self:
435
+ if self.SamplesPerPixel > 1:
436
+ if self.BitsAllocated == 8:
437
+ shape = self.SamplesPerPixel, self.Rows, self.Columns
438
+ else:
439
+ raise NotImplementedError(
440
+ "DICOM plugin only handles "
441
+ "SamplesPerPixel > 1 if Bits "
442
+ "Allocated = 8"
443
+ )
444
+ else:
445
+ shape = self.Rows, self.Columns
446
+ else:
447
+ raise RuntimeError(
448
+ "DICOM file has no SamplesPerPixel " "(perhaps this is a report?)"
449
+ )
450
+
451
+ # Try getting sampling between pixels
452
+ if "PixelSpacing" in self:
453
+ sampling = float(self.PixelSpacing[0]), float(self.PixelSpacing[1])
454
+ else:
455
+ sampling = 1.0, 1.0
456
+ if "SliceSpacing" in self:
457
+ sampling = (abs(self.SliceSpacing),) + sampling
458
+
459
+ # Ensure that sampling has as many elements as shape
460
+ sampling = (1.0,) * (len(shape) - len(sampling)) + sampling[-len(shape) :]
461
+
462
+ # Set shape and sampling
463
+ self._info["shape"] = shape
464
+ self._info["sampling"] = sampling
465
+
466
+ def _pixel_data_numpy(self):
467
+ """Return a NumPy array of the pixel data."""
468
+ # Taken from pydicom
469
+ # Copyright (c) 2008-2012 Darcy Mason
470
+
471
+ if "PixelData" not in self:
472
+ raise TypeError("No pixel data found in this dataset.")
473
+
474
+ # determine the type used for the array
475
+ need_byteswap = self.is_little_endian != sys_is_little_endian
476
+
477
+ # Make NumPy format code, e.g. "uint16", "int32" etc
478
+ # from two pieces of info:
479
+ # self.PixelRepresentation -- 0 for unsigned, 1 for signed;
480
+ # self.BitsAllocated -- 8, 16, or 32
481
+ format_str = "%sint%d" % (
482
+ ("u", "")[self.PixelRepresentation],
483
+ self.BitsAllocated,
484
+ )
485
+ try:
486
+ numpy_format = np.dtype(format_str)
487
+ except TypeError: # pragma: no cover
488
+ raise TypeError(
489
+ "Data type not understood by NumPy: format='%s', "
490
+ " PixelRepresentation=%d, BitsAllocated=%d"
491
+ % (numpy_format, self.PixelRepresentation, self.BitsAllocated)
492
+ )
493
+
494
+ # Have correct Numpy format, so create the NumPy array
495
+ arr = np.frombuffer(self.PixelData, numpy_format).copy()
496
+
497
+ # XXX byte swap - may later handle this in read_file!!?
498
+ if need_byteswap:
499
+ arr.byteswap(True) # True means swap in-place, don't make new copy
500
+
501
+ # Note the following reshape operations return a new *view* onto arr,
502
+ # but don't copy the data
503
+ arr = arr.reshape(*self._info["shape"])
504
+ return arr
505
+
506
+ def _apply_slope_and_offset(self, data):
507
+ """
508
+ If RescaleSlope and RescaleIntercept are present in the data,
509
+ apply them. The data type of the data is changed if necessary.
510
+ """
511
+ # Obtain slope and offset
512
+ slope, offset = 1, 0
513
+ needFloats, needApplySlopeOffset = False, False
514
+ if "RescaleSlope" in self:
515
+ needApplySlopeOffset = True
516
+ slope = self.RescaleSlope
517
+ if "RescaleIntercept" in self:
518
+ needApplySlopeOffset = True
519
+ offset = self.RescaleIntercept
520
+ if int(slope) != slope or int(offset) != offset:
521
+ needFloats = True
522
+ if not needFloats:
523
+ slope, offset = int(slope), int(offset)
524
+
525
+ # Apply slope and offset
526
+ if needApplySlopeOffset:
527
+ # Maybe we need to change the datatype?
528
+ if data.dtype in [np.float32, np.float64]:
529
+ pass
530
+ elif needFloats:
531
+ data = data.astype(np.float32)
532
+ else:
533
+ # Determine required range
534
+ minReq, maxReq = data.min(), data.max()
535
+ minReq = min([minReq, minReq * slope + offset, maxReq * slope + offset])
536
+ maxReq = max([maxReq, minReq * slope + offset, maxReq * slope + offset])
537
+
538
+ # Determine required datatype from that
539
+ dtype = None
540
+ if minReq < 0:
541
+ # Signed integer type
542
+ maxReq = max([-minReq, maxReq])
543
+ if maxReq < 2**7:
544
+ dtype = np.int8
545
+ elif maxReq < 2**15:
546
+ dtype = np.int16
547
+ elif maxReq < 2**31:
548
+ dtype = np.int32
549
+ else:
550
+ dtype = np.float32
551
+ else:
552
+ # Unsigned integer type
553
+ if maxReq < 2**8:
554
+ dtype = np.int8
555
+ elif maxReq < 2**16:
556
+ dtype = np.int16
557
+ elif maxReq < 2**32:
558
+ dtype = np.int32
559
+ else:
560
+ dtype = np.float32
561
+ # Change datatype
562
+ if dtype != data.dtype:
563
+ data = data.astype(dtype)
564
+
565
+ # Apply slope and offset
566
+ data *= slope
567
+ data += offset
568
+
569
+ # Done
570
+ return data
571
+
572
+ def _inflate(self):
573
+ # Taken from pydicom
574
+ # Copyright (c) 2008-2012 Darcy Mason
575
+ import zlib
576
+ from io import BytesIO
577
+
578
+ # See PS3.6-2008 A.5 (p 71) -- when written, the entire dataset
579
+ # following the file metadata was prepared the normal way,
580
+ # then "deflate" compression applied.
581
+ # All that is needed here is to decompress and then
582
+ # use as normal in a file-like object
583
+ zipped = self._file.read()
584
+ # -MAX_WBITS part is from comp.lang.python answer:
585
+ # groups.google.com/group/comp.lang.python/msg/e95b3b38a71e6799
586
+ unzipped = zlib.decompress(zipped, -zlib.MAX_WBITS)
587
+ self._file = BytesIO(unzipped) # a file-like object
588
+
589
+
590
+ class DicomSeries(object):
591
+ """DicomSeries
592
+ This class represents a serie of dicom files (SimpleDicomReader
593
+ objects) that belong together. If these are multiple files, they
594
+ represent the slices of a volume (like for CT or MRI).
595
+ """
596
+
597
+ def __init__(self, suid, progressIndicator):
598
+ # Init dataset list and the callback
599
+ self._entries = []
600
+
601
+ # Init props
602
+ self._suid = suid
603
+ self._info = {}
604
+ self._progressIndicator = progressIndicator
605
+
606
+ def __len__(self):
607
+ return len(self._entries)
608
+
609
+ def __iter__(self):
610
+ return iter(self._entries)
611
+
612
+ def __getitem__(self, index):
613
+ return self._entries[index]
614
+
615
+ @property
616
+ def suid(self):
617
+ return self._suid
618
+
619
+ @property
620
+ def shape(self):
621
+ """The shape of the data (nz, ny, nx)."""
622
+ return self._info["shape"]
623
+
624
+ @property
625
+ def sampling(self):
626
+ """The sampling (voxel distances) of the data (dz, dy, dx)."""
627
+ return self._info["sampling"]
628
+
629
+ @property
630
+ def info(self):
631
+ """A dictionary containing the information as present in the
632
+ first dicomfile of this serie. None if there are no entries."""
633
+ return self._info
634
+
635
+ @property
636
+ def description(self):
637
+ """A description of the dicom series. Used fields are
638
+ PatientName, shape of the data, SeriesDescription, and
639
+ ImageComments.
640
+ """
641
+ info = self.info
642
+
643
+ # If no info available, return simple description
644
+ if not info: # pragma: no cover
645
+ return "DicomSeries containing %i images" % len(self)
646
+
647
+ fields = []
648
+ # Give patient name
649
+ if "PatientName" in info:
650
+ fields.append("" + info["PatientName"])
651
+ # Also add dimensions
652
+ if self.shape:
653
+ tmp = [str(d) for d in self.shape]
654
+ fields.append("x".join(tmp))
655
+ # Try adding more fields
656
+ if "SeriesDescription" in info:
657
+ fields.append("'" + info["SeriesDescription"] + "'")
658
+ if "ImageComments" in info:
659
+ fields.append("'" + info["ImageComments"] + "'")
660
+
661
+ # Combine
662
+ return " ".join(fields)
663
+
664
+ def __repr__(self):
665
+ adr = hex(id(self)).upper()
666
+ return "<DicomSeries with %i images at %s>" % (len(self), adr)
667
+
668
+ def get_numpy_array(self):
669
+ """Get (load) the data that this DicomSeries represents, and return
670
+ it as a numpy array. If this serie contains multiple images, the
671
+ resulting array is 3D, otherwise it's 2D.
672
+ """
673
+
674
+ # It's easy if no file or if just a single file
675
+ if len(self) == 0:
676
+ raise ValueError("Serie does not contain any files.")
677
+ elif len(self) == 1:
678
+ return self[0].get_numpy_array()
679
+
680
+ # Check info
681
+ if self.info is None:
682
+ raise RuntimeError("Cannot return volume if series not finished.")
683
+
684
+ # Init data (using what the dicom packaged produces as a reference)
685
+ slice = self[0].get_numpy_array()
686
+ vol = np.zeros(self.shape, dtype=slice.dtype)
687
+ vol[0] = slice
688
+
689
+ # Fill volume
690
+ self._progressIndicator.start("loading data", "", len(self))
691
+ for z in range(1, len(self)):
692
+ vol[z] = self[z].get_numpy_array()
693
+ self._progressIndicator.set_progress(z + 1)
694
+ self._progressIndicator.finish()
695
+
696
+ # Done
697
+ import gc
698
+
699
+ gc.collect()
700
+ return vol
701
+
702
+ def _append(self, dcm):
703
+ self._entries.append(dcm)
704
+
705
+ def _sort(self):
706
+ self._entries.sort(key=lambda k: k.InstanceNumber)
707
+
708
+ def _finish(self):
709
+ """
710
+ Evaluate the series of dicom files. Together they should make up
711
+ a volumetric dataset. This means the files should meet certain
712
+ conditions. Also some additional information has to be calculated,
713
+ such as the distance between the slices. This method sets the
714
+ attributes for "shape", "sampling" and "info".
715
+
716
+ This method checks:
717
+ * that there are no missing files
718
+ * that the dimensions of all images match
719
+ * that the pixel spacing of all images match
720
+ """
721
+
722
+ # The datasets list should be sorted by instance number
723
+ L = self._entries
724
+ if len(L) == 0:
725
+ return
726
+ elif len(L) == 1:
727
+ self._info = L[0].info
728
+ return
729
+
730
+ # Get previous
731
+ ds1 = L[0]
732
+ # Init measures to calculate average of
733
+ distance_sum = 0.0
734
+ # Init measures to check (these are in 2D)
735
+ dimensions = ds1.Rows, ds1.Columns
736
+ # sampling = float(ds1.PixelSpacing[0]), float(ds1.PixelSpacing[1])
737
+ sampling = ds1.info["sampling"][:2] # row, column
738
+
739
+ for index in range(len(L)):
740
+ # The first round ds1 and ds2 will be the same, for the
741
+ # distance calculation this does not matter
742
+ # Get current
743
+ ds2 = L[index]
744
+ # Get positions
745
+ pos1 = float(ds1.ImagePositionPatient[2])
746
+ pos2 = float(ds2.ImagePositionPatient[2])
747
+ # Update distance_sum to calculate distance later
748
+ distance_sum += abs(pos1 - pos2)
749
+ # Test measures
750
+ dimensions2 = ds2.Rows, ds2.Columns
751
+ # sampling2 = float(ds2.PixelSpacing[0]), float(ds2.PixelSpacing[1])
752
+ sampling2 = ds2.info["sampling"][:2] # row, column
753
+ if dimensions != dimensions2:
754
+ # We cannot produce a volume if the dimensions match
755
+ raise ValueError("Dimensions of slices does not match.")
756
+ if sampling != sampling2:
757
+ # We can still produce a volume, but we should notify the user
758
+ self._progressIndicator.write("Warn: sampling does not match.")
759
+ # Store previous
760
+ ds1 = ds2
761
+
762
+ # Finish calculating average distance
763
+ # (Note that there are len(L)-1 distances)
764
+ distance_mean = distance_sum / (len(L) - 1)
765
+
766
+ # Set info dict
767
+ self._info = L[0].info.copy()
768
+
769
+ # Store information that is specific for the serie
770
+ self._info["shape"] = (len(L),) + ds2.info["shape"]
771
+ self._info["sampling"] = (distance_mean,) + ds2.info["sampling"]
772
+
773
+
774
+ def list_files(files, path):
775
+ """List all files in the directory, recursively."""
776
+ for item in os.listdir(path):
777
+ item = os.path.join(path, item)
778
+ if os.path.isdir(item):
779
+ list_files(files, item)
780
+ elif os.path.isfile(item):
781
+ files.append(item)
782
+
783
+
784
+ def process_directory(request, progressIndicator, readPixelData=False):
785
+ """
786
+ Reads dicom files and returns a list of DicomSeries objects, which
787
+ contain information about the data, and can be used to load the
788
+ image or volume data.
789
+
790
+ if readPixelData is True, the pixel data of all series is read. By
791
+ default the loading of pixeldata is deferred until it is requested
792
+ using the DicomSeries.get_pixel_array() method. In general, both
793
+ methods should be equally fast.
794
+ """
795
+ # Get directory to examine
796
+ if os.path.isdir(request.filename):
797
+ path = request.filename
798
+ elif os.path.isfile(request.filename):
799
+ path = os.path.dirname(request.filename)
800
+ else: # pragma: no cover - tested earlier
801
+ raise ValueError(
802
+ "Dicom plugin needs a valid filename to examine " "the directory"
803
+ )
804
+
805
+ # Check files
806
+ files = []
807
+ list_files(files, path) # Find files recursively
808
+
809
+ # Gather file data and put in DicomSeries
810
+ series = {}
811
+ count = 0
812
+ progressIndicator.start("examining files", "files", len(files))
813
+ for filename in files:
814
+ # Show progress (note that we always start with a 0.0)
815
+ count += 1
816
+ progressIndicator.set_progress(count)
817
+ # Skip DICOMDIR files
818
+ if filename.count("DICOMDIR"): # pragma: no cover
819
+ continue
820
+ # Try loading dicom ...
821
+ try:
822
+ dcm = SimpleDicomReader(filename)
823
+ except NotADicomFile:
824
+ continue # skip non-dicom file
825
+ except Exception as why: # pragma: no cover
826
+ progressIndicator.write(str(why))
827
+ continue
828
+ # Get SUID and register the file with an existing or new series object
829
+ try:
830
+ suid = dcm.SeriesInstanceUID
831
+ except AttributeError: # pragma: no cover
832
+ continue # some other kind of dicom file
833
+ if suid not in series:
834
+ series[suid] = DicomSeries(suid, progressIndicator)
835
+ series[suid]._append(dcm)
836
+
837
+ # Finish progress
838
+ # progressIndicator.finish('Found %i series.' % len(series))
839
+
840
+ # Make a list and sort, so that the order is deterministic
841
+ series = list(series.values())
842
+ series.sort(key=lambda x: x.suid)
843
+
844
+ # Split series if necessary
845
+ for serie in reversed([serie for serie in series]):
846
+ splitSerieIfRequired(serie, series, progressIndicator)
847
+
848
+ # Finish all series
849
+ # progressIndicator.start('analyse series', '', len(series))
850
+ series_ = []
851
+ for i in range(len(series)):
852
+ try:
853
+ series[i]._finish()
854
+ series_.append(series[i])
855
+ except Exception as err: # pragma: no cover
856
+ progressIndicator.write(str(err))
857
+ pass # Skip serie (probably report-like file without pixels)
858
+ # progressIndicator.set_progress(i+1)
859
+ progressIndicator.finish("Found %i correct series." % len(series_))
860
+
861
+ # Done
862
+ return series_
863
+
864
+
865
+ def splitSerieIfRequired(serie, series, progressIndicator):
866
+ """
867
+ Split the serie in multiple series if this is required. The choice
868
+ is based on examing the image position relative to the previous
869
+ image. If it differs too much, it is assumed that there is a new
870
+ dataset. This can happen for example in unspitted gated CT data.
871
+ """
872
+
873
+ # Sort the original list and get local name
874
+ serie._sort()
875
+ L = serie._entries
876
+ # Init previous slice
877
+ ds1 = L[0]
878
+ # Check whether we can do this
879
+ if "ImagePositionPatient" not in ds1:
880
+ return
881
+ # Initialize a list of new lists
882
+ L2 = [[ds1]]
883
+ # Init slice distance estimate
884
+ distance = 0
885
+
886
+ for index in range(1, len(L)):
887
+ # Get current slice
888
+ ds2 = L[index]
889
+ # Get positions
890
+ pos1 = float(ds1.ImagePositionPatient[2])
891
+ pos2 = float(ds2.ImagePositionPatient[2])
892
+ # Get distances
893
+ newDist = abs(pos1 - pos2)
894
+ # deltaDist = abs(firstPos-pos2)
895
+ # If the distance deviates more than 2x from what we've seen,
896
+ # we can agree it's a new dataset.
897
+ if distance and newDist > 2.1 * distance:
898
+ L2.append([])
899
+ distance = 0
900
+ else:
901
+ # Test missing file
902
+ if distance and newDist > 1.5 * distance:
903
+ progressIndicator.write(
904
+ "Warning: missing file after %r" % ds1._filename
905
+ )
906
+ distance = newDist
907
+ # Add to last list
908
+ L2[-1].append(ds2)
909
+ # Store previous
910
+ ds1 = ds2
911
+
912
+ # Split if we should
913
+ if len(L2) > 1:
914
+ # At what position are we now?
915
+ i = series.index(serie)
916
+ # Create new series
917
+ series2insert = []
918
+ for L in L2:
919
+ newSerie = DicomSeries(serie.suid, progressIndicator)
920
+ newSerie._entries = L
921
+ series2insert.append(newSerie)
922
+ # Insert series and remove self
923
+ for newSerie in reversed(series2insert):
924
+ series.insert(i, newSerie)
925
+ series.remove(serie)
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/plugins/_tifffile.py ADDED
The diff for this file is too large to render. See raw diff
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/plugins/example.py ADDED
@@ -0,0 +1,148 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ # imageio is distributed under the terms of the (new) BSD License.
3
+
4
+ """ Example plugin. You can use this as a template for your own plugin.
5
+ """
6
+
7
+ import numpy as np
8
+
9
+ from .. import formats
10
+ from ..core import Format
11
+
12
+
13
+ class DummyFormat(Format):
14
+ """The dummy format is an example format that does nothing.
15
+ It will never indicate that it can read or write a file. When
16
+ explicitly asked to read, it will simply read the bytes. When
17
+ explicitly asked to write, it will raise an error.
18
+
19
+ This documentation is shown when the user does ``help('thisformat')``.
20
+
21
+ Parameters for reading
22
+ ----------------------
23
+ Specify arguments in numpy doc style here.
24
+
25
+ Parameters for saving
26
+ ---------------------
27
+ Specify arguments in numpy doc style here.
28
+
29
+ """
30
+
31
+ def _can_read(self, request):
32
+ # This method is called when the format manager is searching
33
+ # for a format to read a certain image. Return True if this format
34
+ # can do it.
35
+ #
36
+ # The format manager is aware of the extensions and the modes
37
+ # that each format can handle. It will first ask all formats
38
+ # that *seem* to be able to read it whether they can. If none
39
+ # can, it will ask the remaining formats if they can: the
40
+ # extension might be missing, and this allows formats to provide
41
+ # functionality for certain extensions, while giving preference
42
+ # to other plugins.
43
+ #
44
+ # If a format says it can, it should live up to it. The format
45
+ # would ideally check the request.firstbytes and look for a
46
+ # header of some kind.
47
+ #
48
+ # The request object has:
49
+ # request.filename: a representation of the source (only for reporting)
50
+ # request.firstbytes: the first 256 bytes of the file.
51
+ # request.mode[0]: read or write mode
52
+ # request.mode[1]: what kind of data the user expects: one of 'iIvV?'
53
+
54
+ if request.mode[1] in (self.modes + "?"):
55
+ if request.extension in self.extensions:
56
+ return True
57
+
58
+ def _can_write(self, request):
59
+ # This method is called when the format manager is searching
60
+ # for a format to write a certain image. It will first ask all
61
+ # formats that *seem* to be able to write it whether they can.
62
+ # If none can, it will ask the remaining formats if they can.
63
+ #
64
+ # Return True if the format can do it.
65
+
66
+ # In most cases, this code does suffice:
67
+ if request.mode[1] in (self.modes + "?"):
68
+ if request.extension in self.extensions:
69
+ return True
70
+
71
+ # -- reader
72
+
73
+ class Reader(Format.Reader):
74
+ def _open(self, some_option=False, length=1):
75
+ # Specify kwargs here. Optionally, the user-specified kwargs
76
+ # can also be accessed via the request.kwargs object.
77
+ #
78
+ # The request object provides two ways to get access to the
79
+ # data. Use just one:
80
+ # - Use request.get_file() for a file object (preferred)
81
+ # - Use request.get_local_filename() for a file on the system
82
+ self._fp = self.request.get_file()
83
+ self._length = length # passed as an arg in this case for testing
84
+ self._data = None
85
+
86
+ def _close(self):
87
+ # Close the reader.
88
+ # Note that the request object will close self._fp
89
+ pass
90
+
91
+ def _get_length(self):
92
+ # Return the number of images. Can be np.inf
93
+ return self._length
94
+
95
+ def _get_data(self, index):
96
+ # Return the data and meta data for the given index
97
+ if index >= self._length:
98
+ raise IndexError("Image index %i > %i" % (index, self._length))
99
+ # Read all bytes
100
+ if self._data is None:
101
+ self._data = self._fp.read()
102
+ # Put in a numpy array
103
+ im = np.frombuffer(self._data, "uint8")
104
+ im.shape = len(im), 1
105
+ # Return array and dummy meta data
106
+ return im, {}
107
+
108
+ def _get_meta_data(self, index):
109
+ # Get the meta data for the given index. If index is None, it
110
+ # should return the global meta data.
111
+ return {} # This format does not support meta data
112
+
113
+ # -- writer
114
+
115
+ class Writer(Format.Writer):
116
+ def _open(self, flags=0):
117
+ # Specify kwargs here. Optionally, the user-specified kwargs
118
+ # can also be accessed via the request.kwargs object.
119
+ #
120
+ # The request object provides two ways to write the data.
121
+ # Use just one:
122
+ # - Use request.get_file() for a file object (preferred)
123
+ # - Use request.get_local_filename() for a file on the system
124
+ self._fp = self.request.get_file()
125
+
126
+ def _close(self):
127
+ # Close the reader.
128
+ # Note that the request object will close self._fp
129
+ pass
130
+
131
+ def _append_data(self, im, meta):
132
+ # Process the given data and meta data.
133
+ raise RuntimeError("The dummy format cannot write image data.")
134
+
135
+ def set_meta_data(self, meta):
136
+ # Process the given meta data (global for all images)
137
+ # It is not mandatory to support this.
138
+ raise RuntimeError("The dummy format cannot write meta data.")
139
+
140
+
141
+ # Register. You register an *instance* of a Format class. Here specify:
142
+ format = DummyFormat(
143
+ "dummy", # short name
144
+ "An example format that does nothing.", # one line descr.
145
+ ".foobar .nonexistentext", # list of extensions
146
+ "iI", # modes, characters in iIvV
147
+ )
148
+ formats.add_format(format)
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/plugins/gdal.py ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ # imageio is distributed under the terms of the (new) BSD License.
3
+
4
+ """ Read GDAL files.
5
+
6
+ Backend: `GDAL <https://gdal.org/>`_
7
+
8
+ .. note::
9
+ To use this plugin you have to install its backend::
10
+
11
+ pip install imageio[gdal]
12
+
13
+ Parameters
14
+ ----------
15
+ none
16
+ """
17
+
18
+ from ..core import Format, has_module
19
+
20
+ _gdal = None # lazily loaded in load_lib()
21
+
22
+
23
+ def load_lib():
24
+ global _gdal
25
+ try:
26
+ import osgeo.gdal as _gdal
27
+ except ImportError:
28
+ raise ImportError(
29
+ "The GDAL format relies on the GDAL package."
30
+ "Please refer to http://www.gdal.org/"
31
+ "for further instructions."
32
+ )
33
+ return _gdal
34
+
35
+
36
+ GDAL_FORMATS = (".tiff", " .tif", ".img", ".ecw", ".jpg", ".jpeg")
37
+
38
+
39
+ class GdalFormat(Format):
40
+ """See :mod:`imageio.plugins.gdal`"""
41
+
42
+ def _can_read(self, request):
43
+ if request.extension in (".ecw",):
44
+ return True
45
+ if has_module("osgeo.gdal"):
46
+ return request.extension in self.extensions
47
+
48
+ def _can_write(self, request):
49
+ return False
50
+
51
+ # --
52
+
53
+ class Reader(Format.Reader):
54
+ def _open(self):
55
+ if not _gdal:
56
+ load_lib()
57
+ self._ds = _gdal.Open(self.request.get_local_filename())
58
+
59
+ def _close(self):
60
+ del self._ds
61
+
62
+ def _get_length(self):
63
+ return 1
64
+
65
+ def _get_data(self, index):
66
+ if index != 0:
67
+ raise IndexError("Gdal file contains only one dataset")
68
+ return self._ds.ReadAsArray(), self._get_meta_data(index)
69
+
70
+ def _get_meta_data(self, index):
71
+ return self._ds.GetMetadata()
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/plugins/npz.py ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ # imageio is distributed under the terms of the (new) BSD License.
3
+
4
+ """Read/Write NPZ files.
5
+
6
+ Backend: `Numpy <https://numpy.org/doc/stable/reference/generated/numpy.savez.html>`_
7
+
8
+ NPZ is a file format by numpy that provides storage of array data using gzip
9
+ compression. This imageio plugin supports data of any shape, and also supports
10
+ multiple images per file. However, the npz format does not provide streaming;
11
+ all data is read/written at once. Further, there is no support for meta data.
12
+
13
+ See the BSDF format for a similar (but more fully featured) format.
14
+
15
+ Parameters
16
+ ----------
17
+ None
18
+
19
+ Notes
20
+ -----
21
+ This format is not available on Pypy.
22
+
23
+ """
24
+
25
+ import numpy as np
26
+
27
+ from ..core import Format
28
+
29
+
30
+ class NpzFormat(Format):
31
+ """See :mod:`imageio.plugins.npz`"""
32
+
33
+ def _can_read(self, request):
34
+ # We support any kind of image data
35
+ return request.extension in self.extensions
36
+
37
+ def _can_write(self, request):
38
+ # We support any kind of image data
39
+ return request.extension in self.extensions
40
+
41
+ # -- reader
42
+
43
+ class Reader(Format.Reader):
44
+ def _open(self):
45
+ # Load npz file, which provides another file like object
46
+ self._npz = np.load(self.request.get_file())
47
+ assert isinstance(self._npz, np.lib.npyio.NpzFile)
48
+ # Get list of names, ordered by name, but smarter
49
+ self._names = sorted(self._npz.files, key=lambda x: x.split("_")[-1])
50
+
51
+ def _close(self):
52
+ self._npz.close()
53
+
54
+ def _get_length(self):
55
+ return len(self._names)
56
+
57
+ def _get_data(self, index):
58
+ # Get data
59
+ if index < 0 or index >= len(self._names):
60
+ raise IndexError("Index out of range while reading from nzp")
61
+ im = self._npz[self._names[index]]
62
+ # Return array and empty meta data
63
+ return im, {}
64
+
65
+ def _get_meta_data(self, index):
66
+ # Get the meta data for the given index
67
+ raise RuntimeError("The npz format does not support meta data.")
68
+
69
+ # -- writer
70
+
71
+ class Writer(Format.Writer):
72
+ def _open(self):
73
+ # Npz is not such a great format. We cannot stream to the file.
74
+ # So we remember all images and write them to file at the end.
75
+ self._images = []
76
+
77
+ def _close(self):
78
+ # Write everything
79
+ np.savez_compressed(self.request.get_file(), *self._images)
80
+
81
+ def _append_data(self, im, meta):
82
+ self._images.append(im) # discart meta data
83
+
84
+ def set_meta_data(self, meta):
85
+ raise RuntimeError("The npz format does not support meta data.")
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/imageio/resources/images/realshort.mp4 ADDED
Binary file (96.8 kB). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/matplotlib/__pycache__/patches.cpython-38.pyc ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:83e824a4d7719ede1c578409a91dc776783b1aec961dde5b7f5028cec27601bc
3
+ size 139669
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/matplotlib/mpl-data/fonts/ttf/DejaVuSerif-Bold.ttf ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:c3753f2ed6bc673f15846dc45addbeb3b9c872f32fb18fd53a21f1bef1ed7676
3
+ size 355692
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/matplotlib/mpl-data/fonts/ttf/STIXGeneralBolIta.ttf ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:98788fd4ba48dfbb2bd026c0e20a247a8b06c7372879628b7a6bb0d5bb09736c
3
+ size 181152
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/matplotlib/mpl-data/fonts/ttf/STIXGeneralItalic.ttf ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:6cfcb333d22b7c3c623bdfd40174f14c85c3d6731ca6166c1edc80140eae8527
3
+ size 175040