Skip to content

Commit cfcae2b

Browse files
authored
Merge pull request #9032 from anntzer/image-cleanup
Cleanup to image.py.
2 parents b884161 + 6ee70cb commit cfcae2b

File tree

2 files changed

+64
-99
lines changed

2 files changed

+64
-99
lines changed

INSTALL.rst

+8-9
Original file line numberDiff line numberDiff line change
@@ -206,15 +206,14 @@ optional Matplotlib backends and the capabilities they provide.
206206
For better support of animation output format and image file formats, LaTeX,
207207
etc., you can install the following:
208208

209-
* `ffmpeg <https://www.ffmpeg.org/>`__/`avconv
210-
<https://libav.org/avconv.html>`__ or `mencoder
211-
<https://mplayerhq.hu/design7/news.html>`__ (for saving movies);
212-
* `ImageMagick <https://www.imagemagick.org/script/index.php>`__ (for saving
213-
animated gifs);
214-
* `Pillow <https://python-pillow.org/>`__ (for a larger selection of image
215-
file formats: JPEG, BMP, and TIFF image files);
216-
* `LaTeX <https://miktex.org/>`_ and `GhostScript <https://ghostscript.com/download/>`_
217-
(for rendering text with LaTeX);
209+
* `ffmpeg <https://www.ffmpeg.org/>`_/`avconv
210+
<https://libav.org/avconv.html>`_: for saving movies;
211+
* `ImageMagick <https://www.imagemagick.org/script/index.php>`_: for saving
212+
animated gifs;
213+
* `Pillow <https://python-pillow.org/>`_ (>=2.0): for a larger selection of
214+
image file formats: JPEG, BMP, and TIFF image files;
215+
* `LaTeX <https://miktex.org/>`_ and `GhostScript
216+
<https://ghostscript.com/download/>`_ (for rendering text with LaTeX).
218217

219218
.. note::
220219

lib/matplotlib/image.py

+56-90
Original file line numberDiff line numberDiff line change
@@ -130,9 +130,8 @@ def _draw_list_compositing_images(
130130
has_images = any(isinstance(x, _ImageBase) for x in artists)
131131

132132
# override the renderer default if suppressComposite is not None
133-
not_composite = renderer.option_image_nocomposite()
134-
if suppress_composite is not None:
135-
not_composite = suppress_composite
133+
not_composite = (suppress_composite if suppress_composite is not None
134+
else renderer.option_image_nocomposite())
136135

137136
if not_composite or not has_images:
138137
for a in artists:
@@ -146,8 +145,7 @@ def flush_images():
146145
if len(image_group) == 1:
147146
image_group[0].draw(renderer)
148147
elif len(image_group) > 1:
149-
data, l, b = composite_images(
150-
image_group, renderer, mag)
148+
data, l, b = composite_images(image_group, renderer, mag)
151149
if data.size != 0:
152150
gc = renderer.new_gc()
153151
gc.set_clip_rectangle(parent.bbox)
@@ -182,13 +180,17 @@ def _rgb_to_rgba(A):
182180
class _ImageBase(martist.Artist, cm.ScalarMappable):
183181
zorder = 0
184182

185-
# the 3 following keys seem to be unused now, keep it for
186-
# backward compatibility just in case.
187-
_interpd = _interpd_
188-
# reverse interp dict
189-
_interpdr = {v: k for k, v in six.iteritems(_interpd_)}
190-
iterpnames = interpolations_names
191-
# <end unused keys>
183+
@cbook.deprecated("2.1")
184+
def _interpd(self):
185+
return _interpd_
186+
187+
@cbook.deprecated("2.1")
188+
def _interpdr(self):
189+
return {v: k for k, v in six.iteritems(_interpd_)}
190+
191+
@cbook.deprecated("2.1")
192+
def iterpnames(self):
193+
return interpolations_names
192194

193195
def set_cmap(self, cmap):
194196
super(_ImageBase, self).set_cmap(cmap)
@@ -349,8 +351,7 @@ def _make_image(self, A, in_bbox, out_bbox, clip_bbox, magnification=1.0,
349351
out_height = int(ceil(out_height_base))
350352
extra_width = (out_width - out_width_base) / out_width_base
351353
extra_height = (out_height - out_height_base) / out_height_base
352-
t += Affine2D().scale(
353-
1.0 + extra_width, 1.0 + extra_height)
354+
t += Affine2D().scale(1.0 + extra_width, 1.0 + extra_height)
354355
else:
355356
out_width = int(out_width_base)
356357
out_height = int(out_height_base)
@@ -659,7 +660,7 @@ def can_composite(self):
659660

660661
def set_resample(self, v):
661662
"""
662-
Set whether or not image resampling is used
663+
Set whether or not image resampling is used.
663664
664665
ACCEPTS: True|False
665666
"""
@@ -669,7 +670,7 @@ def set_resample(self, v):
669670
self.stale = True
670671

671672
def get_resample(self):
672-
"""Return the image resample boolean"""
673+
"""Return the image resample boolean."""
673674
return self._resample
674675

675676
def set_filternorm(self, filternorm):
@@ -687,7 +688,7 @@ def set_filternorm(self, filternorm):
687688
self.stale = True
688689

689690
def get_filternorm(self):
690-
"""Return the filternorm setting"""
691+
"""Return the filternorm setting."""
691692
return self._filternorm
692693

693694
def set_filterrad(self, filterrad):
@@ -704,7 +705,7 @@ def set_filterrad(self, filterrad):
704705
self.stale = True
705706

706707
def get_filterrad(self):
707-
"""return the filterrad setting"""
708+
"""Return the filterrad setting."""
708709
return self._filterrad
709710

710711

@@ -770,13 +771,10 @@ def make_image(self, renderer, magnification=1.0, unsampled=False):
770771

771772
def _check_unsampled_image(self, renderer):
772773
"""
773-
return True if the image is better to be drawn unsampled.
774+
Return whether the image would be better drawn unsampled.
774775
"""
775-
if (self.get_interpolation() == "none" and
776-
renderer.option_scale_image()):
777-
return True
778-
779-
return False
776+
return (self.get_interpolation() == "none"
777+
and renderer.option_scale_image())
780778

781779
def set_extent(self, extent):
782780
"""
@@ -786,11 +784,8 @@ def set_extent(self, extent):
786784
to tightly fit the image, regardless of dataLim. Autoscaling
787785
state is not changed, so following this with ax.autoscale_view
788786
will redo the autoscaling in accord with dataLim.
789-
790787
"""
791-
self._extent = extent
792-
793-
xmin, xmax, ymin, ymax = extent
788+
self._extent = xmin, xmax, ymin, ymax = extent
794789
corners = (xmin, ymin), (xmax, ymax)
795790
self.axes.update_datalim(corners)
796791
self.sticky_edges.x[:] = [xmin, xmax]
@@ -821,8 +816,7 @@ def get_cursor_data(self, event):
821816
arr = self.get_array()
822817
data_extent = Bbox([[ymin, xmin], [ymax, xmax]])
823818
array_extent = Bbox([[0, 0], arr.shape[:2]])
824-
trans = BboxTransform(boxin=data_extent,
825-
boxout=array_extent)
819+
trans = BboxTransform(boxin=data_extent, boxout=array_extent)
826820
y, x = event.ydata, event.xdata
827821
i, j = trans.transform_point([y, x]).astype(int)
828822
# Clip the coordinates at array bounds
@@ -971,7 +965,6 @@ def __init__(self, ax,
971965
norm is a colors.Normalize instance to map luminance to 0-1
972966
973967
Additional kwargs are matplotlib.artist properties
974-
975968
"""
976969
super(PcolorImage, self).__init__(ax, norm=norm, cmap=cmap)
977970
self.update(kwargs)
@@ -1095,7 +1088,6 @@ def __init__(self, fig,
10951088
origin=None,
10961089
**kwargs
10971090
):
1098-
10991091
"""
11001092
cmap is a colors.Colormap instance
11011093
norm is a colors.Normalize instance to map luminance to 0-1
@@ -1148,7 +1140,6 @@ def __init__(self, bbox,
11481140
interp_at_native=True,
11491141
**kwargs
11501142
):
1151-
11521143
"""
11531144
cmap is a colors.Colormap instance
11541145
norm is a colors.Normalize instance to map luminance to 0-1
@@ -1305,30 +1296,30 @@ def imsave(fname, arr, vmin=None, vmax=None, cmap=None, format=None,
13051296
13061297
The output formats available depend on the backend being used.
13071298
1308-
Arguments:
1309-
*fname*:
1310-
A string containing a path to a filename, or a Python file-like object.
1299+
Parameters
1300+
----------
1301+
fname : str or file-like
1302+
Path string to a filename, or a Python file-like object.
13111303
If *format* is *None* and *fname* is a string, the output
13121304
format is deduced from the extension of the filename.
1313-
*arr*:
1305+
arr : array-like
13141306
An MxN (luminance), MxNx3 (RGB) or MxNx4 (RGBA) array.
1315-
Keyword arguments:
1316-
*vmin*/*vmax*: [ None | scalar ]
1307+
vmin, vmax: [ None | scalar ]
13171308
*vmin* and *vmax* set the color scaling for the image by fixing the
13181309
values that map to the colormap color limits. If either *vmin*
13191310
or *vmax* is None, that limit is determined from the *arr*
13201311
min/max value.
1321-
*cmap*:
1322-
cmap is a colors.Colormap instance, e.g., cm.jet.
1323-
If None, default to the rc image.cmap value.
1324-
*format*:
1325-
One of the file extensions supported by the active
1326-
backend. Most backends support png, pdf, ps, eps and svg.
1327-
*origin*
1328-
[ 'upper' | 'lower' ] Indicates where the [0,0] index of
1329-
the array is in the upper left or lower left corner of
1330-
the axes. Defaults to the rc image.origin value.
1331-
*dpi*
1312+
cmap : matplotlib.colors.Colormap, optional
1313+
For example, ``cm.viridis``. If ``None``, defaults to the
1314+
``image.cmap`` rcParam.
1315+
format : str
1316+
One of the file extensions supported by the active backend. Most
1317+
backends support png, pdf, ps, eps and svg.
1318+
origin : [ 'upper' | 'lower' ]
1319+
Indicates whether the ``(0, 0)`` index of the array is in the
1320+
upper left or lower left corner of the axes. Defaults to the
1321+
``image.origin`` rcParam.
1322+
dpi : int
13321323
The DPI to store in the metadata of the file. This does not affect the
13331324
resolution of the output image.
13341325
"""
@@ -1352,54 +1343,29 @@ def imsave(fname, arr, vmin=None, vmax=None, cmap=None, format=None,
13521343

13531344

13541345
def pil_to_array(pilImage):
1346+
"""Load a PIL image and return it as a numpy array.
1347+
1348+
Grayscale images are returned as ``(M, N)`` arrays. RGB images are
1349+
returned as ``(M, N, 3)`` arrays. RGBA images are returned as ``(M, N,
1350+
4)`` arrays.
13551351
"""
1356-
Load a PIL image and return it as a numpy array. For grayscale
1357-
images, the return array is MxN. For RGB images, the return value
1358-
is MxNx3. For RGBA images the return value is MxNx4
1359-
"""
1360-
def toarray(im, dtype=np.uint8):
1361-
"""Return a 1D array of dtype."""
1362-
# Pillow wants us to use "tobytes"
1363-
if hasattr(im, 'tobytes'):
1364-
x_str = im.tobytes('raw', im.mode)
1365-
else:
1366-
x_str = im.tostring('raw', im.mode)
1367-
x = np.fromstring(x_str, dtype)
1368-
return x
1369-
1370-
if pilImage.mode in ('RGBA', 'RGBX'):
1371-
im = pilImage # no need to convert images
1372-
elif pilImage.mode == 'L':
1373-
im = pilImage # no need to luminance images
1374-
# return MxN luminance array
1375-
x = toarray(im)
1376-
x.shape = im.size[1], im.size[0]
1377-
return x
1378-
elif pilImage.mode == 'RGB':
1379-
# return MxNx3 RGB array
1380-
im = pilImage # no need to RGB images
1381-
x = toarray(im)
1382-
x.shape = im.size[1], im.size[0], 3
1383-
return x
1352+
if pilImage.mode in ['RGBA', 'RGBX', 'RGB', 'L']:
1353+
# return MxNx4 RGBA, MxNx3 RBA, or MxN luminance array
1354+
return np.asarray(pilImage)
13841355
elif pilImage.mode.startswith('I;16'):
13851356
# return MxN luminance array of uint16
1386-
im = pilImage
1387-
if im.mode.endswith('B'):
1388-
x = toarray(im, '>u2')
1357+
raw = pilImage.tobytes('raw', pilImage.mode)
1358+
if pilImage.mode.endswith('B'):
1359+
x = np.fromstring(raw, '>u2')
13891360
else:
1390-
x = toarray(im, '<u2')
1391-
x.shape = im.size[1], im.size[0]
1392-
return x.astype('=u2')
1361+
x = np.fromstring(raw, '<u2')
1362+
return x.reshape(pilImage.size[::-1]).astype('=u2')
13931363
else: # try to convert to an rgba image
13941364
try:
1395-
im = pilImage.convert('RGBA')
1365+
pilImage = pilImage.convert('RGBA')
13961366
except ValueError:
13971367
raise RuntimeError('Unknown image mode')
1398-
1399-
# return MxNx4 RGBA array
1400-
x = toarray(im)
1401-
x.shape = im.size[1], im.size[0], 4
1402-
return x
1368+
return np.asarray(pilImage) # return MxNx4 RGBA array
14031369

14041370

14051371
def thumbnail(infile, thumbfile, scale=0.1, interpolation='bilinear',

0 commit comments

Comments
 (0)