Skip to content

Commit

Permalink
Merge pull request #5349 from latosha-maltba/master
Browse files Browse the repository at this point in the history
  • Loading branch information
hugovk committed Apr 1, 2021
2 parents 682e3e2 + 0f8fffb commit 8c852e4
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 20 deletions.
27 changes: 17 additions & 10 deletions Tests/helper.py
Expand Up @@ -257,8 +257,23 @@ def netpbm_available():
return bool(shutil.which("ppmquant") and shutil.which("ppmtogif"))


def imagemagick_available():
return bool(IMCONVERT and shutil.which(IMCONVERT))
def magick_command():
if sys.platform == "win32":
magickhome = os.environ.get("MAGICK_HOME", "")
if magickhome:
imagemagick = [os.path.join(magickhome, "convert.exe")]
graphicsmagick = [os.path.join(magickhome, "gm.exe"), "convert"]
else:
imagemagick = None
graphicsmagick = None
else:
imagemagick = ["convert"]
graphicsmagick = ["gm", "convert"]

if imagemagick and shutil.which(imagemagick[0]):
return imagemagick
elif graphicsmagick and shutil.which(graphicsmagick[0]):
return graphicsmagick


def on_appveyor():
Expand Down Expand Up @@ -296,14 +311,6 @@ def is_mingw():
return sysconfig.get_platform() == "mingw"


if sys.platform == "win32":
IMCONVERT = os.environ.get("MAGICK_HOME", "")
if IMCONVERT:
IMCONVERT = os.path.join(IMCONVERT, "convert.exe")
else:
IMCONVERT = "convert"


class cached_property:
def __init__(self, func):
self.func = func
Expand Down
16 changes: 6 additions & 10 deletions Tests/test_file_palm.py
Expand Up @@ -5,9 +5,7 @@

from PIL import Image

from .helper import IMCONVERT, assert_image_equal, hopper, imagemagick_available

_roundtrip = imagemagick_available()
from .helper import assert_image_equal, hopper, magick_command


def helper_save_as_palm(tmp_path, mode):
Expand All @@ -23,28 +21,26 @@ def helper_save_as_palm(tmp_path, mode):
assert os.path.getsize(outfile) > 0


def open_with_imagemagick(tmp_path, f):
if not imagemagick_available():
raise OSError()

def open_with_magick(magick, tmp_path, f):
outfile = str(tmp_path / "temp.png")
rc = subprocess.call(
[IMCONVERT, f, outfile], stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT
magick + [f, outfile], stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT
)
if rc:
raise OSError
return Image.open(outfile)


def roundtrip(tmp_path, mode):
if not _roundtrip:
magick = magick_command()
if not magick:
return

im = hopper(mode)
outfile = str(tmp_path / "temp.palm")

im.save(outfile)
converted = open_with_imagemagick(tmp_path, outfile)
converted = open_with_magick(magick, tmp_path, outfile)
assert_image_equal(converted, im)


Expand Down
1 change: 1 addition & 0 deletions docs/reference/ImageShow.rst
Expand Up @@ -18,6 +18,7 @@ All default viewers convert the image to be shown to PNG format.
The following viewers may be registered on Unix-based systems, if the given command is found:

.. autoclass:: PIL.ImageShow.DisplayViewer
.. autoclass:: PIL.ImageShow.GmDisplayViewer
.. autoclass:: PIL.ImageShow.EogViewer
.. autoclass:: PIL.ImageShow.XVViewer

Expand Down
21 changes: 21 additions & 0 deletions docs/releasenotes/8.2.0.rst
Expand Up @@ -83,6 +83,18 @@ instances, so it will only be used by ``im.show()`` or :py:func:`.ImageShow.show
if none of the other viewers are available. This means that the behaviour of
:py:class:`PIL.ImageShow` will stay the same for most Pillow users.

ImageShow.GmDisplayViewer
^^^^^^^^^^^^^^^^^^^^^^^^^

If GraphicsMagick is present, this new :py:class:`PIL.ImageShow.Viewer` subclass will
be registered. It uses GraphicsMagick_, an ImageMagick_ fork, to display images.

The GraphicsMagick based viewer has a lower priority than its ImageMagick
counterpart. Thus, if both ImageMagick and GraphicsMagick are installed,
``im.show()`` and :py:func:`.ImageShow.show()` prefer the viewer based on
ImageMagick, i.e the behaviour stays the same for Pillow users having
ImageMagick installed.

Saving TIFF with ICC profile
^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Expand Down Expand Up @@ -143,3 +155,12 @@ PyQt6

Support has been added for PyQt6. If it is installed, it will be used instead of
PySide6, PyQt5 or PySide2.

GraphicsMagick
^^^^^^^^^^^^^^

The test suite can now be run on systems which have GraphicsMagick_ but not
ImageMagick_ installed. If both are installed, the tests prefer ImageMagick.

.. _GraphicsMagick: http://www.graphicsmagick.org/
.. _ImageMagick: https://imagemagick.org/
11 changes: 11 additions & 0 deletions src/PIL/ImageShow.py
Expand Up @@ -194,6 +194,15 @@ def get_command_ex(self, file, **options):
return command, executable


class GmDisplayViewer(UnixViewer):
"""The GraphicsMagick ``gm display`` command."""

def get_command_ex(self, file, **options):
executable = "gm"
command = "gm display"
return command, executable


class EogViewer(UnixViewer):
"""The GNOME Image Viewer ``eog`` command."""

Expand All @@ -220,6 +229,8 @@ def get_command_ex(self, file, title=None, **options):
if sys.platform not in ("win32", "darwin"): # unixoids
if shutil.which("display"):
register(DisplayViewer)
if shutil.which("gm"):
register(GmDisplayViewer)
if shutil.which("eog"):
register(EogViewer)
if shutil.which("xv"):
Expand Down

0 comments on commit 8c852e4

Please sign in to comment.