The ImageIO Plugin API#
Here you can find documentation on how to write your own plugin to allow ImageIO to access a new backend. Plugins are quite object oriented, and the relevant classes and their interaction are documented here:
|
Represents an implementation to read/write a particular file format |
|
ImageResource handling utility. |
Note
You can always check existing plugins if you want to see examples.
What methods to implement#
To implement a new plugin, create a new class that inherits from
imageio.core.Format
. and implement the following functions:
|
Initialize the Plugin. |
|
Check if Plugin can read from ImageResource. |
|
Check if Plugin can write to ImageResource. |
Further, each format contains up to two nested classes; one for reading and one for writing. To support reading and/or writing, the respective classes need to be defined.
For reading, create a nested class that inherits from
imageio.core.Format.Reader
and that implements the following functions:
- Implement
_open(**kwargs)
to initialize the reader. Deal with theuser-provided keyword arguments here.
Implement
_close()
to clean up.
- Implement
_get_length()
to provide a suitable length based on whatthe user expects. Can be
inf
for streaming data.Implement
_get_data(index)
to return an array and a meta-data dict.
- Implement
_get_meta_data(index)
to return a meta-data dict. If indexis None, it should return the ‘global’ meta-data.
For writing, create a nested class that inherits from
imageio.core.Format.Writer
and implement the following functions:
- Implement
_open(**kwargs)
to initialize the writer. Deal with theuser-provided keyword arguments here.
Implement
_close()
to clean up.Implement
_append_data(im, meta)
to add data (and meta-data).Implement
_set_meta_data(meta)
to set the global meta-data.
Example / template plugin#
1# -*- coding: utf-8 -*-
2
3# imageio is distributed under the terms of the (new) BSD License.
4
5
6
7""" Example plugin. You can use this as a template for your own plugin.
8
9"""
10
11
12
13import numpy as np
14
15
16
17from .. import formats
18
19from ..core import Format
20
21
22
23
24
25class DummyFormat(Format):
26
27 """The dummy format is an example format that does nothing.
28
29 It will never indicate that it can read or write a file. When
30
31 explicitly asked to read, it will simply read the bytes. When
32
33 explicitly asked to write, it will raise an error.
34
35
36
37 This documentation is shown when the user does ``help('thisformat')``.
38
39
40
41 Parameters for reading
42
43 ----------------------
44
45 Specify arguments in numpy doc style here.
46
47
48
49 Parameters for saving
50
51 ---------------------
52
53 Specify arguments in numpy doc style here.
54
55
56
57 """
58
59
60
61 def _can_read(self, request):
62
63 # This method is called when the format manager is searching
64
65 # for a format to read a certain image. Return True if this format
66
67 # can do it.
68
69 #
70
71 # The format manager is aware of the extensions and the modes
72
73 # that each format can handle. It will first ask all formats
74
75 # that *seem* to be able to read it whether they can. If none
76
77 # can, it will ask the remaining formats if they can: the
78
79 # extension might be missing, and this allows formats to provide
80
81 # functionality for certain extensions, while giving preference
82
83 # to other plugins.
84
85 #
86
87 # If a format says it can, it should live up to it. The format
88
89 # would ideally check the request.firstbytes and look for a
90
91 # header of some kind.
92
93 #
94
95 # The request object has:
96
97 # request.filename: a representation of the source (only for reporting)
98
99 # request.firstbytes: the first 256 bytes of the file.
100
101 # request.mode[0]: read or write mode
102
103
104
105 if request.extension in self.extensions:
106
107 return True
108
109
110
111 def _can_write(self, request):
112
113 # This method is called when the format manager is searching
114
115 # for a format to write a certain image. It will first ask all
116
117 # formats that *seem* to be able to write it whether they can.
118
119 # If none can, it will ask the remaining formats if they can.
120
121 #
122
123 # Return True if the format can do it.
124
125
126
127 # In most cases, this code does suffice:
128
129 if request.extension in self.extensions:
130
131 return True
132
133
134
135 # -- reader
136
137
138
139 class Reader(Format.Reader):
140
141 def _open(self, some_option=False, length=1):
142
143 # Specify kwargs here. Optionally, the user-specified kwargs
144
145 # can also be accessed via the request.kwargs object.
146
147 #
148
149 # The request object provides two ways to get access to the
150
151 # data. Use just one:
152
153 # - Use request.get_file() for a file object (preferred)
154
155 # - Use request.get_local_filename() for a file on the system
156
157 self._fp = self.request.get_file()
158
159 self._length = length # passed as an arg in this case for testing
160
161 self._data = None
162
163
164
165 def _close(self):
166
167 # Close the reader.
168
169 # Note that the request object will close self._fp
170
171 pass
172
173
174
175 def _get_length(self):
176
177 # Return the number of images. Can be np.inf
178
179 return self._length
180
181
182
183 def _get_data(self, index):
184
185 # Return the data and meta data for the given index
186
187 if index >= self._length:
188
189 raise IndexError("Image index %i > %i" % (index, self._length))
190
191 # Read all bytes
192
193 if self._data is None:
194
195 self._data = self._fp.read()
196
197 # Put in a numpy array
198
199 im = np.frombuffer(self._data, "uint8")
200
201 im.shape = len(im), 1
202
203 # Return array and dummy meta data
204
205 return im, {}
206
207
208
209 def _get_meta_data(self, index):
210
211 # Get the meta data for the given index. If index is None, it
212
213 # should return the global meta data.
214
215 return {} # This format does not support meta data
216
217
218
219 # -- writer
220
221
222
223 class Writer(Format.Writer):
224
225 def _open(self, flags=0):
226
227 # Specify kwargs here. Optionally, the user-specified kwargs
228
229 # can also be accessed via the request.kwargs object.
230
231 #
232
233 # The request object provides two ways to write the data.
234
235 # Use just one:
236
237 # - Use request.get_file() for a file object (preferred)
238
239 # - Use request.get_local_filename() for a file on the system
240
241 self._fp = self.request.get_file()
242
243
244
245 def _close(self):
246
247 # Close the reader.
248
249 # Note that the request object will close self._fp
250
251 pass
252
253
254
255 def _append_data(self, im, meta):
256
257 # Process the given data and meta data.
258
259 raise RuntimeError("The dummy format cannot write image data.")
260
261
262
263 def set_meta_data(self, meta):
264
265 # Process the given meta data (global for all images)
266
267 # It is not mandatory to support this.
268
269 raise RuntimeError("The dummy format cannot write meta data.")
270
271
272
273
274
275# Register. You register an *instance* of a Format class. Here specify:
276
277format = DummyFormat(
278
279 "dummy", # short name
280
281 "An example format that does nothing.", # one line descr.
282
283 ".foobar .nonexistentext", # list of extensions
284
285 "iI", # modes, characters in iIvV
286
287)
288
289formats.add_format(format)