diff --git a/Tests/test_file_eps.py b/Tests/test_file_eps.py index 26adfff8786..4e3954ecb63 100644 --- a/Tests/test_file_eps.py +++ b/Tests/test_file_eps.py @@ -8,6 +8,7 @@ assert_image_similar, assert_image_similar_tofile, hopper, + is_win32, mark_if_feature_version, skip_unless_feature, ) @@ -98,6 +99,20 @@ def test_load(): assert im.load()[0, 0] == (255, 255, 255) +def test_binary(): + if HAS_GHOSTSCRIPT: + assert EpsImagePlugin.gs_binary is not None + else: + assert EpsImagePlugin.gs_binary is False + + if not is_win32(): + assert EpsImagePlugin.gs_windows_binary is None + elif not HAS_GHOSTSCRIPT: + assert EpsImagePlugin.gs_windows_binary is False + else: + assert EpsImagePlugin.gs_windows_binary is not None + + def test_invalid_file(): invalid_file = "Tests/images/flower.jpg" with pytest.raises(SyntaxError): diff --git a/docs/handbook/image-file-formats.rst b/docs/handbook/image-file-formats.rst index 2a42bdacba7..f13475a898a 100644 --- a/docs/handbook/image-file-formats.rst +++ b/docs/handbook/image-file-formats.rst @@ -88,8 +88,13 @@ in ``L``, ``RGB`` and ``CMYK`` modes. Loading ~~~~~~~ +To use Ghostscript, Pillow searches for the "gs" executable. On Windows, it +also searches for "gswin32c" and "gswin64c". To customise this behaviour, +``EpsImagePlugin.gs_binary = "gswin64"`` will set the name of the executable to +use. ``EpsImagePlugin.gs_binary = False`` will prevent Ghostscript use. + If Ghostscript is available, you can call the :py:meth:`~PIL.Image.Image.load` -method with the following parameters to affect how Ghostscript renders the EPS +method with the following parameters to affect how Ghostscript renders the EPS. **scale** Affects the scale of the resultant rasterized image. If the EPS suggests diff --git a/src/PIL/EpsImagePlugin.py b/src/PIL/EpsImagePlugin.py index b96ce9603a3..ec4e822d109 100644 --- a/src/PIL/EpsImagePlugin.py +++ b/src/PIL/EpsImagePlugin.py @@ -37,33 +37,39 @@ split = re.compile(r"^%%([^:]*):[ \t]*(.*)[ \t]*$") field = re.compile(r"^%[%!\w]([^:]*)[ \t]*$") +gs_binary = None gs_windows_binary = None -if sys.platform.startswith("win"): - import shutil - - for binary in ("gswin32c", "gswin64c", "gs"): - if shutil.which(binary) is not None: - gs_windows_binary = binary - break - else: - gs_windows_binary = False def has_ghostscript(): - if gs_windows_binary: - return True - if not sys.platform.startswith("win"): - try: - subprocess.check_call(["gs", "--version"], stdout=subprocess.DEVNULL) - return True - except OSError: - # No Ghostscript - pass - return False + global gs_binary, gs_windows_binary + if gs_binary is None: + if sys.platform.startswith("win"): + if gs_windows_binary is None: + import shutil + + for binary in ("gswin32c", "gswin64c", "gs"): + if shutil.which(binary) is not None: + gs_windows_binary = binary + break + else: + gs_windows_binary = False + gs_binary = gs_windows_binary + else: + try: + subprocess.check_call(["gs", "--version"], stdout=subprocess.DEVNULL) + gs_binary = "gs" + except OSError: + gs_binary = False + return gs_binary is not False def Ghostscript(tile, size, fp, scale=1, transparency=False): """Render an image using Ghostscript""" + global gs_binary + if not has_ghostscript(): + msg = "Unable to locate Ghostscript on paths" + raise OSError(msg) # Unpack decoder tile decoder, tile, offset, data = tile[0] @@ -113,7 +119,7 @@ def Ghostscript(tile, size, fp, scale=1, transparency=False): # Build Ghostscript command command = [ - "gs", + gs_binary, "-q", # quiet mode "-g%dx%d" % size, # set output geometry (pixels) "-r%fx%f" % res, # set input DPI (dots per inch) @@ -132,19 +138,6 @@ def Ghostscript(tile, size, fp, scale=1, transparency=False): "showpage", ] - if gs_windows_binary is not None: - if not gs_windows_binary: - try: - os.unlink(outfile) - if infile_temp: - os.unlink(infile_temp) - except OSError: - pass - - msg = "Unable to locate Ghostscript on paths" - raise OSError(msg) - command[0] = gs_windows_binary - # push data through Ghostscript try: startupinfo = None