Merge pull request #5349 from latosha-maltba/master

This commit is contained in:
Hugo van Kemenade 2021-04-01 11:55:37 +03:00 committed by GitHub
commit 8c852e44f0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 56 additions and 20 deletions

View File

@ -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():
@ -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

View File

@ -5,9 +5,7 @@ import pytest
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):
@ -23,13 +21,10 @@ 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
@ -37,14 +32,15 @@ def open_with_imagemagick(tmp_path, f):
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)

View File

@ -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

View File

@ -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
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -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/

View File

@ -194,6 +194,15 @@ class DisplayViewer(UnixViewer):
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."""
@ -220,6 +229,8 @@ class XVViewer(UnixViewer):
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"):