mirror of
				https://github.com/python-pillow/Pillow.git
				synced 2025-11-04 09:57:43 +03:00 
			
		
		
		
	Merge pull request #4700 from nulano/features-version
This commit is contained in:
		
						commit
						1bc67c9f0f
					
				| 
						 | 
					@ -1,4 +1,5 @@
 | 
				
			||||||
import io
 | 
					import io
 | 
				
			||||||
 | 
					import re
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
from PIL import features
 | 
					from PIL import features
 | 
				
			||||||
| 
						 | 
					@ -21,6 +22,27 @@ def test_check():
 | 
				
			||||||
        assert features.check_feature(feature) == features.check(feature)
 | 
					        assert features.check_feature(feature) == features.check(feature)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_version():
 | 
				
			||||||
 | 
					    # Check the correctness of the convenience function
 | 
				
			||||||
 | 
					    # and the format of version numbers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test(name, function):
 | 
				
			||||||
 | 
					        version = features.version(name)
 | 
				
			||||||
 | 
					        if not features.check(name):
 | 
				
			||||||
 | 
					            assert version is None
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            assert function(name) == version
 | 
				
			||||||
 | 
					            if name != "PIL":
 | 
				
			||||||
 | 
					                assert version is None or re.search(r"\d+(\.\d+)*$", version)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for module in features.modules:
 | 
				
			||||||
 | 
					        test(module, features.version_module)
 | 
				
			||||||
 | 
					    for codec in features.codecs:
 | 
				
			||||||
 | 
					        test(codec, features.version_codec)
 | 
				
			||||||
 | 
					    for feature in features.features:
 | 
				
			||||||
 | 
					        test(feature, features.version_feature)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@skip_unless_feature("webp")
 | 
					@skip_unless_feature("webp")
 | 
				
			||||||
def test_webp_transparency():
 | 
					def test_webp_transparency():
 | 
				
			||||||
    assert features.check("transp_webp") != _webp.WebPDecoderBuggyAlpha()
 | 
					    assert features.check("transp_webp") != _webp.WebPDecoderBuggyAlpha()
 | 
				
			||||||
| 
						 | 
					@ -37,9 +59,22 @@ def test_webp_anim():
 | 
				
			||||||
    assert features.check("webp_anim") == _webp.HAVE_WEBPANIM
 | 
					    assert features.check("webp_anim") == _webp.HAVE_WEBPANIM
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@skip_unless_feature("libjpeg_turbo")
 | 
				
			||||||
 | 
					def test_libjpeg_turbo_version():
 | 
				
			||||||
 | 
					    assert re.search(r"\d+\.\d+\.\d+$", features.version("libjpeg_turbo"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@skip_unless_feature("libimagequant")
 | 
				
			||||||
 | 
					def test_libimagequant_version():
 | 
				
			||||||
 | 
					    assert re.search(r"\d+\.\d+\.\d+$", features.version("libimagequant"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_check_modules():
 | 
					def test_check_modules():
 | 
				
			||||||
    for feature in features.modules:
 | 
					    for feature in features.modules:
 | 
				
			||||||
        assert features.check_module(feature) in [True, False]
 | 
					        assert features.check_module(feature) in [True, False]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_check_codecs():
 | 
				
			||||||
    for feature in features.codecs:
 | 
					    for feature in features.codecs:
 | 
				
			||||||
        assert features.check_codec(feature) in [True, False]
 | 
					        assert features.check_codec(feature) in [True, False]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -64,6 +99,8 @@ def test_unsupported_codec():
 | 
				
			||||||
    # Act / Assert
 | 
					    # Act / Assert
 | 
				
			||||||
    with pytest.raises(ValueError):
 | 
					    with pytest.raises(ValueError):
 | 
				
			||||||
        features.check_codec(codec)
 | 
					        features.check_codec(codec)
 | 
				
			||||||
 | 
					    with pytest.raises(ValueError):
 | 
				
			||||||
 | 
					        features.version_codec(codec)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_unsupported_module():
 | 
					def test_unsupported_module():
 | 
				
			||||||
| 
						 | 
					@ -72,6 +109,8 @@ def test_unsupported_module():
 | 
				
			||||||
    # Act / Assert
 | 
					    # Act / Assert
 | 
				
			||||||
    with pytest.raises(ValueError):
 | 
					    with pytest.raises(ValueError):
 | 
				
			||||||
        features.check_module(module)
 | 
					        features.check_module(module)
 | 
				
			||||||
 | 
					    with pytest.raises(ValueError):
 | 
				
			||||||
 | 
					        features.version_module(module)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_pilinfo():
 | 
					def test_pilinfo():
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,14 +2,14 @@ import io
 | 
				
			||||||
import sys
 | 
					import sys
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
from PIL import IcnsImagePlugin, Image
 | 
					from PIL import IcnsImagePlugin, Image, features
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from .helper import assert_image_equal, assert_image_similar
 | 
					from .helper import assert_image_equal, assert_image_similar
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# sample icon file
 | 
					# sample icon file
 | 
				
			||||||
TEST_FILE = "Tests/images/pillow.icns"
 | 
					TEST_FILE = "Tests/images/pillow.icns"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ENABLE_JPEG2K = hasattr(Image.core, "jp2klib_version")
 | 
					ENABLE_JPEG2K = features.check_codec("jpg_2000")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_sanity():
 | 
					def test_sanity():
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,7 +3,7 @@ import re
 | 
				
			||||||
from io import BytesIO
 | 
					from io import BytesIO
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
from PIL import ExifTags, Image, ImageFile, JpegImagePlugin
 | 
					from PIL import ExifTags, Image, ImageFile, JpegImagePlugin, features
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from .helper import (
 | 
					from .helper import (
 | 
				
			||||||
    assert_image,
 | 
					    assert_image,
 | 
				
			||||||
| 
						 | 
					@ -41,7 +41,7 @@ class TestFileJpeg:
 | 
				
			||||||
    def test_sanity(self):
 | 
					    def test_sanity(self):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # internal version number
 | 
					        # internal version number
 | 
				
			||||||
        assert re.search(r"\d+\.\d+$", Image.core.jpeglib_version)
 | 
					        assert re.search(r"\d+\.\d+$", features.version_codec("jpg"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        with Image.open(TEST_FILE) as im:
 | 
					        with Image.open(TEST_FILE) as im:
 | 
				
			||||||
            im.load()
 | 
					            im.load()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,7 +2,7 @@ import re
 | 
				
			||||||
from io import BytesIO
 | 
					from io import BytesIO
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
from PIL import Image, ImageFile, Jpeg2KImagePlugin
 | 
					from PIL import Image, ImageFile, Jpeg2KImagePlugin, features
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from .helper import (
 | 
					from .helper import (
 | 
				
			||||||
    assert_image_equal,
 | 
					    assert_image_equal,
 | 
				
			||||||
| 
						 | 
					@ -35,7 +35,7 @@ def roundtrip(im, **options):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_sanity():
 | 
					def test_sanity():
 | 
				
			||||||
    # Internal version number
 | 
					    # Internal version number
 | 
				
			||||||
    assert re.search(r"\d+\.\d+\.\d+$", Image.core.jp2klib_version)
 | 
					    assert re.search(r"\d+\.\d+\.\d+$", features.version_codec("jpg_2000"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    with Image.open("Tests/images/test-card-lossless.jp2") as im:
 | 
					    with Image.open("Tests/images/test-card-lossless.jp2") as im:
 | 
				
			||||||
        px = im.load()
 | 
					        px = im.load()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,11 +3,12 @@ import io
 | 
				
			||||||
import itertools
 | 
					import itertools
 | 
				
			||||||
import logging
 | 
					import logging
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
 | 
					import re
 | 
				
			||||||
from collections import namedtuple
 | 
					from collections import namedtuple
 | 
				
			||||||
from ctypes import c_float
 | 
					from ctypes import c_float
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
from PIL import Image, ImageFilter, TiffImagePlugin, TiffTags
 | 
					from PIL import Image, ImageFilter, TiffImagePlugin, TiffTags, features
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from .helper import (
 | 
					from .helper import (
 | 
				
			||||||
    assert_image_equal,
 | 
					    assert_image_equal,
 | 
				
			||||||
| 
						 | 
					@ -47,6 +48,9 @@ class LibTiffTestCase:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TestFileLibTiff(LibTiffTestCase):
 | 
					class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
 | 
					    def test_version(self):
 | 
				
			||||||
 | 
					        assert re.search(r"\d+\.\d+\.\d+$", features.version_codec("libtiff"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_g4_tiff(self, tmp_path):
 | 
					    def test_g4_tiff(self, tmp_path):
 | 
				
			||||||
        """Test the ordinary file path load path"""
 | 
					        """Test the ordinary file path load path"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,7 +3,7 @@ import zlib
 | 
				
			||||||
from io import BytesIO
 | 
					from io import BytesIO
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
from PIL import Image, ImageFile, PngImagePlugin
 | 
					from PIL import Image, ImageFile, PngImagePlugin, features
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from .helper import (
 | 
					from .helper import (
 | 
				
			||||||
    PillowLeakTestCase,
 | 
					    PillowLeakTestCase,
 | 
				
			||||||
| 
						 | 
					@ -73,7 +73,7 @@ class TestFilePng:
 | 
				
			||||||
    def test_sanity(self, tmp_path):
 | 
					    def test_sanity(self, tmp_path):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # internal version number
 | 
					        # internal version number
 | 
				
			||||||
        assert re.search(r"\d+\.\d+\.\d+(\.\d+)?$", Image.core.zlib_version)
 | 
					        assert re.search(r"\d+\.\d+\.\d+(\.\d+)?$", features.version_codec("zlib"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        test_file = str(tmp_path / "temp.png")
 | 
					        test_file = str(tmp_path / "temp.png")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,8 @@
 | 
				
			||||||
import io
 | 
					import io
 | 
				
			||||||
 | 
					import re
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
from PIL import Image, WebPImagePlugin
 | 
					from PIL import Image, WebPImagePlugin, features
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from .helper import (
 | 
					from .helper import (
 | 
				
			||||||
    assert_image_similar,
 | 
					    assert_image_similar,
 | 
				
			||||||
| 
						 | 
					@ -38,6 +39,7 @@ class TestFileWebp:
 | 
				
			||||||
    def test_version(self):
 | 
					    def test_version(self):
 | 
				
			||||||
        _webp.WebPDecoderVersion()
 | 
					        _webp.WebPDecoderVersion()
 | 
				
			||||||
        _webp.WebPDecoderBuggyAlpha()
 | 
					        _webp.WebPDecoderBuggyAlpha()
 | 
				
			||||||
 | 
					        assert re.search(r"\d+\.\d+\.\d+$", features.version_module("webp"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_read_rgb(self):
 | 
					    def test_read_rgb(self):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,7 +4,7 @@ import re
 | 
				
			||||||
from io import BytesIO
 | 
					from io import BytesIO
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
from PIL import Image, ImageMode
 | 
					from PIL import Image, ImageMode, features
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from .helper import assert_image, assert_image_equal, assert_image_similar, hopper
 | 
					from .helper import assert_image, assert_image_equal, assert_image_similar, hopper
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -46,7 +46,7 @@ def test_sanity():
 | 
				
			||||||
    assert list(map(type, v)) == [str, str, str, str]
 | 
					    assert list(map(type, v)) == [str, str, str, str]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # internal version number
 | 
					    # internal version number
 | 
				
			||||||
    assert re.search(r"\d+\.\d+$", ImageCms.core.littlecms_version)
 | 
					    assert re.search(r"\d+\.\d+$", features.version_module("littlecms2"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    skip_missing()
 | 
					    skip_missing()
 | 
				
			||||||
    i = ImageCms.profileToProfile(hopper(), SRGB, SRGB)
 | 
					    i = ImageCms.profileToProfile(hopper(), SRGB, SRGB)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,7 +7,7 @@ import sys
 | 
				
			||||||
from io import BytesIO
 | 
					from io import BytesIO
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
from PIL import Image, ImageDraw, ImageFont
 | 
					from PIL import Image, ImageDraw, ImageFont, features
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from .helper import (
 | 
					from .helper import (
 | 
				
			||||||
    assert_image_equal,
 | 
					    assert_image_equal,
 | 
				
			||||||
| 
						 | 
					@ -41,7 +41,7 @@ class TestImageFont:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @classmethod
 | 
					    @classmethod
 | 
				
			||||||
    def setup_class(self):
 | 
					    def setup_class(self):
 | 
				
			||||||
        freetype = distutils.version.StrictVersion(ImageFont.core.freetype2_version)
 | 
					        freetype = distutils.version.StrictVersion(features.version_module("freetype2"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.metrics = self.METRICS["Default"]
 | 
					        self.metrics = self.METRICS["Default"]
 | 
				
			||||||
        for conditions, metrics in self.METRICS.items():
 | 
					        for conditions, metrics in self.METRICS.items():
 | 
				
			||||||
| 
						 | 
					@ -68,7 +68,7 @@ class TestImageFont:
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_sanity(self):
 | 
					    def test_sanity(self):
 | 
				
			||||||
        assert re.search(r"\d+\.\d+\.\d+$", ImageFont.core.freetype2_version)
 | 
					        assert re.search(r"\d+\.\d+\.\d+$", features.version_module("freetype2"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_font_properties(self):
 | 
					    def test_font_properties(self):
 | 
				
			||||||
        ttf = self.get_font()
 | 
					        ttf = self.get_font()
 | 
				
			||||||
| 
						 | 
					@ -620,7 +620,7 @@ class TestImageFont:
 | 
				
			||||||
    def test_variation_get(self):
 | 
					    def test_variation_get(self):
 | 
				
			||||||
        font = self.get_font()
 | 
					        font = self.get_font()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        freetype = distutils.version.StrictVersion(ImageFont.core.freetype2_version)
 | 
					        freetype = distutils.version.StrictVersion(features.version_module("freetype2"))
 | 
				
			||||||
        if freetype < "2.9.1":
 | 
					        if freetype < "2.9.1":
 | 
				
			||||||
            with pytest.raises(NotImplementedError):
 | 
					            with pytest.raises(NotImplementedError):
 | 
				
			||||||
                font.get_variation_names()
 | 
					                font.get_variation_names()
 | 
				
			||||||
| 
						 | 
					@ -692,7 +692,7 @@ class TestImageFont:
 | 
				
			||||||
    def test_variation_set_by_name(self):
 | 
					    def test_variation_set_by_name(self):
 | 
				
			||||||
        font = self.get_font()
 | 
					        font = self.get_font()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        freetype = distutils.version.StrictVersion(ImageFont.core.freetype2_version)
 | 
					        freetype = distutils.version.StrictVersion(features.version_module("freetype2"))
 | 
				
			||||||
        if freetype < "2.9.1":
 | 
					        if freetype < "2.9.1":
 | 
				
			||||||
            with pytest.raises(NotImplementedError):
 | 
					            with pytest.raises(NotImplementedError):
 | 
				
			||||||
                font.set_variation_by_name("Bold")
 | 
					                font.set_variation_by_name("Bold")
 | 
				
			||||||
| 
						 | 
					@ -716,7 +716,7 @@ class TestImageFont:
 | 
				
			||||||
    def test_variation_set_by_axes(self):
 | 
					    def test_variation_set_by_axes(self):
 | 
				
			||||||
        font = self.get_font()
 | 
					        font = self.get_font()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        freetype = distutils.version.StrictVersion(ImageFont.core.freetype2_version)
 | 
					        freetype = distutils.version.StrictVersion(features.version_module("freetype2"))
 | 
				
			||||||
        if freetype < "2.9.1":
 | 
					        if freetype < "2.9.1":
 | 
				
			||||||
            with pytest.raises(NotImplementedError):
 | 
					            with pytest.raises(NotImplementedError):
 | 
				
			||||||
                font.set_variation_by_axes([100])
 | 
					                font.set_variation_by_axes([100])
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,6 +8,7 @@ The :py:mod:`PIL.features` module can be used to detect which Pillow features ar
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. autofunction:: PIL.features.pilinfo
 | 
					.. autofunction:: PIL.features.pilinfo
 | 
				
			||||||
.. autofunction:: PIL.features.check
 | 
					.. autofunction:: PIL.features.check
 | 
				
			||||||
 | 
					.. autofunction:: PIL.features.version
 | 
				
			||||||
.. autofunction:: PIL.features.get_supported
 | 
					.. autofunction:: PIL.features.get_supported
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Modules
 | 
					Modules
 | 
				
			||||||
| 
						 | 
					@ -16,28 +17,31 @@ Modules
 | 
				
			||||||
Support for the following modules can be checked:
 | 
					Support for the following modules can be checked:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
* ``pil``: The Pillow core module, required for all functionality.
 | 
					* ``pil``: The Pillow core module, required for all functionality.
 | 
				
			||||||
* ``tkinter``: Tkinter support.
 | 
					* ``tkinter``: Tkinter support. Version number not available.
 | 
				
			||||||
* ``freetype2``: FreeType font support via :py:func:`PIL.ImageFont.truetype`.
 | 
					* ``freetype2``: FreeType font support via :py:func:`PIL.ImageFont.truetype`.
 | 
				
			||||||
* ``littlecms2``: LittleCMS 2 support via :py:mod:`PIL.ImageCms`.
 | 
					* ``littlecms2``: LittleCMS 2 support via :py:mod:`PIL.ImageCms`.
 | 
				
			||||||
* ``webp``: WebP image support.
 | 
					* ``webp``: WebP image support.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. autofunction:: PIL.features.check_module
 | 
					.. autofunction:: PIL.features.check_module
 | 
				
			||||||
 | 
					.. autofunction:: PIL.features.version_module
 | 
				
			||||||
.. autofunction:: PIL.features.get_supported_modules
 | 
					.. autofunction:: PIL.features.get_supported_modules
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Codecs
 | 
					Codecs
 | 
				
			||||||
------
 | 
					------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
These are only checked during Pillow compilation.
 | 
					Support for these is only checked during Pillow compilation.
 | 
				
			||||||
If the required library was uninstalled from the system, the ``pil`` core module may fail to load instead.
 | 
					If the required library was uninstalled from the system, the ``pil`` core module may fail to load instead.
 | 
				
			||||||
 | 
					Except for ``jpg``, the version number is checked at run-time.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Support for the following codecs can be checked:
 | 
					Support for the following codecs can be checked:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
* ``jpg``: (compile time) Libjpeg support, required for JPEG based image formats.
 | 
					* ``jpg``: (compile time) Libjpeg support, required for JPEG based image formats. Only compile time version number is available.
 | 
				
			||||||
* ``jpg_2000``: (compile time) OpenJPEG support, required for JPEG 2000 image formats.
 | 
					* ``jpg_2000``: (compile time) OpenJPEG support, required for JPEG 2000 image formats.
 | 
				
			||||||
* ``zlib``: (compile time) Zlib support, required for zlib compressed formats, such as PNG.
 | 
					* ``zlib``: (compile time) Zlib support, required for zlib compressed formats, such as PNG.
 | 
				
			||||||
* ``libtiff``: (compile time) LibTIFF support, required for TIFF based image formats.
 | 
					* ``libtiff``: (compile time) LibTIFF support, required for TIFF based image formats.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. autofunction:: PIL.features.check_codec
 | 
					.. autofunction:: PIL.features.check_codec
 | 
				
			||||||
 | 
					.. autofunction:: PIL.features.version_codec
 | 
				
			||||||
.. autofunction:: PIL.features.get_supported_codecs
 | 
					.. autofunction:: PIL.features.get_supported_codecs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Features
 | 
					Features
 | 
				
			||||||
| 
						 | 
					@ -45,16 +49,18 @@ Features
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Some of these are only checked during Pillow compilation.
 | 
					Some of these are only checked during Pillow compilation.
 | 
				
			||||||
If the required library was uninstalled from the system, the relevant module may fail to load instead.
 | 
					If the required library was uninstalled from the system, the relevant module may fail to load instead.
 | 
				
			||||||
 | 
					Feature version numbers are available only where stated.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Support for the following features can be checked:
 | 
					Support for the following features can be checked:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
* ``libjpeg_turbo``: (compile time) Whether Pillow was compiled against the libjpeg-turbo version of libjpeg.
 | 
					* ``libjpeg_turbo``: (compile time) Whether Pillow was compiled against the libjpeg-turbo version of libjpeg. Compile-time version number is available.
 | 
				
			||||||
* ``transp_webp``: Support for transparency in WebP images.
 | 
					* ``transp_webp``: Support for transparency in WebP images.
 | 
				
			||||||
* ``webp_mux``: (compile time) Support for EXIF data in WebP images.
 | 
					* ``webp_mux``: (compile time) Support for EXIF data in WebP images.
 | 
				
			||||||
* ``webp_anim``: (compile time) Support for animated WebP images.
 | 
					* ``webp_anim``: (compile time) Support for animated WebP images.
 | 
				
			||||||
* ``raqm``: Raqm library, required for ``ImageFont.LAYOUT_RAQM`` in :py:func:`PIL.ImageFont.truetype`.
 | 
					* ``raqm``: Raqm library, required for ``ImageFont.LAYOUT_RAQM`` in :py:func:`PIL.ImageFont.truetype`. Run-time version number is available for Raqm 0.7.0 or newer.
 | 
				
			||||||
* ``libimagequant``: (compile time) ImageQuant quantization support in :py:func:`PIL.Image.Image.quantize`.
 | 
					* ``libimagequant``: (compile time) ImageQuant quantization support in :py:func:`PIL.Image.Image.quantize`. Run-time version number is available.
 | 
				
			||||||
* ``xcb``: (compile time) Support for X11 in :py:func:`PIL.ImageGrab.grab` via the XCB library.
 | 
					* ``xcb``: (compile time) Support for X11 in :py:func:`PIL.ImageGrab.grab` via the XCB library.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. autofunction:: PIL.features.check_feature
 | 
					.. autofunction:: PIL.features.check_feature
 | 
				
			||||||
 | 
					.. autofunction:: PIL.features.version_feature
 | 
				
			||||||
.. autofunction:: PIL.features.get_supported_features
 | 
					.. autofunction:: PIL.features.get_supported_features
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,10 +23,10 @@ import subprocess
 | 
				
			||||||
import sys
 | 
					import sys
 | 
				
			||||||
import tempfile
 | 
					import tempfile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from PIL import Image, ImageFile, PngImagePlugin
 | 
					from PIL import Image, ImageFile, PngImagePlugin, features
 | 
				
			||||||
from PIL._binary import i8
 | 
					from PIL._binary import i8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enable_jpeg2k = hasattr(Image.core, "jp2klib_version")
 | 
					enable_jpeg2k = features.check_codec("jpg_2000")
 | 
				
			||||||
if enable_jpeg2k:
 | 
					if enable_jpeg2k:
 | 
				
			||||||
    from PIL import Jpeg2KImagePlugin
 | 
					    from PIL import Jpeg2KImagePlugin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,11 +8,11 @@ import PIL
 | 
				
			||||||
from . import Image
 | 
					from . import Image
 | 
				
			||||||
 | 
					
 | 
				
			||||||
modules = {
 | 
					modules = {
 | 
				
			||||||
    "pil": "PIL._imaging",
 | 
					    "pil": ("PIL._imaging", "PILLOW_VERSION"),
 | 
				
			||||||
    "tkinter": "PIL._tkinter_finder",
 | 
					    "tkinter": ("PIL._tkinter_finder", None),
 | 
				
			||||||
    "freetype2": "PIL._imagingft",
 | 
					    "freetype2": ("PIL._imagingft", "freetype2_version"),
 | 
				
			||||||
    "littlecms2": "PIL._imagingcms",
 | 
					    "littlecms2": ("PIL._imagingcms", "littlecms_version"),
 | 
				
			||||||
    "webp": "PIL._webp",
 | 
					    "webp": ("PIL._webp", "webpdecoder_version"),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -27,7 +27,7 @@ def check_module(feature):
 | 
				
			||||||
    if not (feature in modules):
 | 
					    if not (feature in modules):
 | 
				
			||||||
        raise ValueError("Unknown module %s" % feature)
 | 
					        raise ValueError("Unknown module %s" % feature)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    module = modules[feature]
 | 
					    module, ver = modules[feature]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
        __import__(module)
 | 
					        __import__(module)
 | 
				
			||||||
| 
						 | 
					@ -36,6 +36,24 @@ def check_module(feature):
 | 
				
			||||||
        return False
 | 
					        return False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def version_module(feature):
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    :param feature: The module to check for.
 | 
				
			||||||
 | 
					    :returns:
 | 
				
			||||||
 | 
					        The loaded version number as a string, or ``None`` if unknown or not available.
 | 
				
			||||||
 | 
					    :raises ValueError: If the module is not defined in this version of Pillow.
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    if not check_module(feature):
 | 
				
			||||||
 | 
					        return None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    module, ver = modules[feature]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ver is None:
 | 
				
			||||||
 | 
					        return None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return getattr(__import__(module, fromlist=[ver]), ver)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def get_supported_modules():
 | 
					def get_supported_modules():
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    :returns: A list of all supported modules.
 | 
					    :returns: A list of all supported modules.
 | 
				
			||||||
| 
						 | 
					@ -43,7 +61,12 @@ def get_supported_modules():
 | 
				
			||||||
    return [f for f in modules if check_module(f)]
 | 
					    return [f for f in modules if check_module(f)]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
codecs = {"jpg": "jpeg", "jpg_2000": "jpeg2k", "zlib": "zip", "libtiff": "libtiff"}
 | 
					codecs = {
 | 
				
			||||||
 | 
					    "jpg": ("jpeg", "jpeglib"),
 | 
				
			||||||
 | 
					    "jpg_2000": ("jpeg2k", "jp2klib"),
 | 
				
			||||||
 | 
					    "zlib": ("zip", "zlib"),
 | 
				
			||||||
 | 
					    "libtiff": ("libtiff", "libtiff"),
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def check_codec(feature):
 | 
					def check_codec(feature):
 | 
				
			||||||
| 
						 | 
					@ -57,11 +80,32 @@ def check_codec(feature):
 | 
				
			||||||
    if feature not in codecs:
 | 
					    if feature not in codecs:
 | 
				
			||||||
        raise ValueError("Unknown codec %s" % feature)
 | 
					        raise ValueError("Unknown codec %s" % feature)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    codec = codecs[feature]
 | 
					    codec, lib = codecs[feature]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return codec + "_encoder" in dir(Image.core)
 | 
					    return codec + "_encoder" in dir(Image.core)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def version_codec(feature):
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    :param feature: The codec to check for.
 | 
				
			||||||
 | 
					    :returns:
 | 
				
			||||||
 | 
					        The version number as a string, or ``None`` if not available.
 | 
				
			||||||
 | 
					        Checked at compile time for ``jpg``, run-time otherwise.
 | 
				
			||||||
 | 
					    :raises ValueError: If the codec is not defined in this version of Pillow.
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    if not check_codec(feature):
 | 
				
			||||||
 | 
					        return None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    codec, lib = codecs[feature]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    version = getattr(Image.core, lib + "_version")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if feature == "libtiff":
 | 
				
			||||||
 | 
					        return version.split("\n")[0].split("Version ")[1]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return version
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def get_supported_codecs():
 | 
					def get_supported_codecs():
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    :returns: A list of all supported codecs.
 | 
					    :returns: A list of all supported codecs.
 | 
				
			||||||
| 
						 | 
					@ -70,13 +114,13 @@ def get_supported_codecs():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
features = {
 | 
					features = {
 | 
				
			||||||
    "webp_anim": ("PIL._webp", "HAVE_WEBPANIM"),
 | 
					    "webp_anim": ("PIL._webp", "HAVE_WEBPANIM", None),
 | 
				
			||||||
    "webp_mux": ("PIL._webp", "HAVE_WEBPMUX"),
 | 
					    "webp_mux": ("PIL._webp", "HAVE_WEBPMUX", None),
 | 
				
			||||||
    "transp_webp": ("PIL._webp", "HAVE_TRANSPARENCY"),
 | 
					    "transp_webp": ("PIL._webp", "HAVE_TRANSPARENCY", None),
 | 
				
			||||||
    "raqm": ("PIL._imagingft", "HAVE_RAQM"),
 | 
					    "raqm": ("PIL._imagingft", "HAVE_RAQM", "raqm_version"),
 | 
				
			||||||
    "libjpeg_turbo": ("PIL._imaging", "HAVE_LIBJPEGTURBO"),
 | 
					    "libjpeg_turbo": ("PIL._imaging", "HAVE_LIBJPEGTURBO", "libjpeg_turbo_version"),
 | 
				
			||||||
    "libimagequant": ("PIL._imaging", "HAVE_LIBIMAGEQUANT"),
 | 
					    "libimagequant": ("PIL._imaging", "HAVE_LIBIMAGEQUANT", "imagequant_version"),
 | 
				
			||||||
    "xcb": ("PIL._imaging", "HAVE_XCB"),
 | 
					    "xcb": ("PIL._imaging", "HAVE_XCB", None),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -91,7 +135,7 @@ def check_feature(feature):
 | 
				
			||||||
    if feature not in features:
 | 
					    if feature not in features:
 | 
				
			||||||
        raise ValueError("Unknown feature %s" % feature)
 | 
					        raise ValueError("Unknown feature %s" % feature)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    module, flag = features[feature]
 | 
					    module, flag, ver = features[feature]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
        imported_module = __import__(module, fromlist=["PIL"])
 | 
					        imported_module = __import__(module, fromlist=["PIL"])
 | 
				
			||||||
| 
						 | 
					@ -100,6 +144,23 @@ def check_feature(feature):
 | 
				
			||||||
        return None
 | 
					        return None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def version_feature(feature):
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    :param feature: The feature to check for.
 | 
				
			||||||
 | 
					    :returns: The version number as a string, or ``None`` if not available.
 | 
				
			||||||
 | 
					    :raises ValueError: If the feature is not defined in this version of Pillow.
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    if not check_feature(feature):
 | 
				
			||||||
 | 
					        return None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    module, flag, ver = features[feature]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ver is None:
 | 
				
			||||||
 | 
					        return None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return getattr(__import__(module, fromlist=[ver]), ver)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def get_supported_features():
 | 
					def get_supported_features():
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    :returns: A list of all supported features.
 | 
					    :returns: A list of all supported features.
 | 
				
			||||||
| 
						 | 
					@ -109,9 +170,9 @@ def get_supported_features():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def check(feature):
 | 
					def check(feature):
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    :param feature: A module, feature, or codec name.
 | 
					    :param feature: A module, codec, or feature name.
 | 
				
			||||||
    :returns:
 | 
					    :returns:
 | 
				
			||||||
        ``True`` if the module, feature, or codec is available,
 | 
					        ``True`` if the module, codec, or feature is available,
 | 
				
			||||||
        ``False`` or ``None`` otherwise.
 | 
					        ``False`` or ``None`` otherwise.
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -125,6 +186,22 @@ def check(feature):
 | 
				
			||||||
    return False
 | 
					    return False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def version(feature):
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    :param feature:
 | 
				
			||||||
 | 
					        The module, codec, or feature to check for.
 | 
				
			||||||
 | 
					    :returns:
 | 
				
			||||||
 | 
					        The version number as a string, or ``None`` if unknown or not available.
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    if feature in modules:
 | 
				
			||||||
 | 
					        return version_module(feature)
 | 
				
			||||||
 | 
					    if feature in codecs:
 | 
				
			||||||
 | 
					        return version_codec(feature)
 | 
				
			||||||
 | 
					    if feature in features:
 | 
				
			||||||
 | 
					        return version_feature(feature)
 | 
				
			||||||
 | 
					    return None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def get_supported():
 | 
					def get_supported():
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    :returns: A list of all supported modules, features, and codecs.
 | 
					    :returns: A list of all supported modules, features, and codecs.
 | 
				
			||||||
| 
						 | 
					@ -187,7 +264,15 @@ def pilinfo(out=None, supported_formats=True):
 | 
				
			||||||
        ("xcb", "XCB (X protocol)"),
 | 
					        ("xcb", "XCB (X protocol)"),
 | 
				
			||||||
    ]:
 | 
					    ]:
 | 
				
			||||||
        if check(name):
 | 
					        if check(name):
 | 
				
			||||||
            print("---", feature, "support ok", file=out)
 | 
					            if name == "jpg" and check_feature("libjpeg_turbo"):
 | 
				
			||||||
 | 
					                v = "libjpeg-turbo " + version_feature("libjpeg_turbo")
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                v = version(name)
 | 
				
			||||||
 | 
					            if v is not None:
 | 
				
			||||||
 | 
					                t = "compiled for" if name in ("pil", "jpg") else "loaded"
 | 
				
			||||||
 | 
					                print("---", feature, "support ok,", t, v, file=out)
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                print("---", feature, "support ok", file=out)
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            print("***", feature, "support not installed", file=out)
 | 
					            print("***", feature, "support not installed", file=out)
 | 
				
			||||||
    print("-" * 68, file=out)
 | 
					    print("-" * 68, file=out)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4168,12 +4168,21 @@ setup_module(PyObject* m) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef LIBJPEG_TURBO_VERSION
 | 
					#ifdef LIBJPEG_TURBO_VERSION
 | 
				
			||||||
    PyModule_AddObject(m, "HAVE_LIBJPEGTURBO", Py_True);
 | 
					    PyModule_AddObject(m, "HAVE_LIBJPEGTURBO", Py_True);
 | 
				
			||||||
 | 
					    #define tostr1(a) #a
 | 
				
			||||||
 | 
					    #define tostr(a) tostr1(a)
 | 
				
			||||||
 | 
					    PyDict_SetItemString(d, "libjpeg_turbo_version", PyUnicode_FromString(tostr(LIBJPEG_TURBO_VERSION)));
 | 
				
			||||||
 | 
					    #undef tostr
 | 
				
			||||||
 | 
					    #undef tostr1
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
    PyModule_AddObject(m, "HAVE_LIBJPEGTURBO", Py_False);
 | 
					    PyModule_AddObject(m, "HAVE_LIBJPEGTURBO", Py_False);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef HAVE_LIBIMAGEQUANT
 | 
					#ifdef HAVE_LIBIMAGEQUANT
 | 
				
			||||||
    PyModule_AddObject(m, "HAVE_LIBIMAGEQUANT", Py_True);
 | 
					    PyModule_AddObject(m, "HAVE_LIBIMAGEQUANT", Py_True);
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        extern const char* ImagingImageQuantVersion(void);
 | 
				
			||||||
 | 
					        PyDict_SetItemString(d, "imagequant_version", PyUnicode_FromString(ImagingImageQuantVersion()));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
    PyModule_AddObject(m, "HAVE_LIBIMAGEQUANT", Py_False);
 | 
					    PyModule_AddObject(m, "HAVE_LIBIMAGEQUANT", Py_False);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1608,6 +1608,7 @@ static int
 | 
				
			||||||
setup_module(PyObject* m) {
 | 
					setup_module(PyObject* m) {
 | 
				
			||||||
    PyObject *d;
 | 
					    PyObject *d;
 | 
				
			||||||
    PyObject *v;
 | 
					    PyObject *v;
 | 
				
			||||||
 | 
					    int vn;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    d = PyModule_GetDict(m);
 | 
					    d = PyModule_GetDict(m);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1622,7 +1623,8 @@ setup_module(PyObject* m) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    d = PyModule_GetDict(m);
 | 
					    d = PyModule_GetDict(m);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    v = PyUnicode_FromFormat("%d.%d", LCMS_VERSION / 100, LCMS_VERSION % 100);
 | 
					    vn = cmsGetEncodedCMMversion();
 | 
				
			||||||
 | 
					    v = PyUnicode_FromFormat("%d.%d", vn / 100, vn % 100);
 | 
				
			||||||
    PyDict_SetItemString(d, "littlecms_version", v);
 | 
					    PyDict_SetItemString(d, "littlecms_version", v);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -81,6 +81,7 @@ typedef struct {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static PyTypeObject Font_Type;
 | 
					static PyTypeObject Font_Type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef const char* (*t_raqm_version_string) (void);
 | 
				
			||||||
typedef bool (*t_raqm_version_atleast)(unsigned int major,
 | 
					typedef bool (*t_raqm_version_atleast)(unsigned int major,
 | 
				
			||||||
                                       unsigned int minor,
 | 
					                                       unsigned int minor,
 | 
				
			||||||
                                       unsigned int micro);
 | 
					                                       unsigned int micro);
 | 
				
			||||||
| 
						 | 
					@ -112,6 +113,7 @@ typedef void (*t_raqm_destroy) (raqm_t *rq);
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
    void* raqm;
 | 
					    void* raqm;
 | 
				
			||||||
    int version;
 | 
					    int version;
 | 
				
			||||||
 | 
					    t_raqm_version_string version_string;
 | 
				
			||||||
    t_raqm_version_atleast version_atleast;
 | 
					    t_raqm_version_atleast version_atleast;
 | 
				
			||||||
    t_raqm_create create;
 | 
					    t_raqm_create create;
 | 
				
			||||||
    t_raqm_set_text set_text;
 | 
					    t_raqm_set_text set_text;
 | 
				
			||||||
| 
						 | 
					@ -173,6 +175,7 @@ setraqm(void)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef _WIN32
 | 
					#ifndef _WIN32
 | 
				
			||||||
 | 
					    p_raqm.version_string = (t_raqm_version_atleast)dlsym(p_raqm.raqm, "raqm_version_string");
 | 
				
			||||||
    p_raqm.version_atleast = (t_raqm_version_atleast)dlsym(p_raqm.raqm, "raqm_version_atleast");
 | 
					    p_raqm.version_atleast = (t_raqm_version_atleast)dlsym(p_raqm.raqm, "raqm_version_atleast");
 | 
				
			||||||
    p_raqm.create = (t_raqm_create)dlsym(p_raqm.raqm, "raqm_create");
 | 
					    p_raqm.create = (t_raqm_create)dlsym(p_raqm.raqm, "raqm_create");
 | 
				
			||||||
    p_raqm.set_text = (t_raqm_set_text)dlsym(p_raqm.raqm, "raqm_set_text");
 | 
					    p_raqm.set_text = (t_raqm_set_text)dlsym(p_raqm.raqm, "raqm_set_text");
 | 
				
			||||||
| 
						 | 
					@ -206,6 +209,7 @@ setraqm(void)
 | 
				
			||||||
        return 2;
 | 
					        return 2;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
 | 
					    p_raqm.version_string = (t_raqm_version_atleast)GetProcAddress(p_raqm.raqm, "raqm_version_string");
 | 
				
			||||||
    p_raqm.version_atleast = (t_raqm_version_atleast)GetProcAddress(p_raqm.raqm, "raqm_version_atleast");
 | 
					    p_raqm.version_atleast = (t_raqm_version_atleast)GetProcAddress(p_raqm.raqm, "raqm_version_atleast");
 | 
				
			||||||
    p_raqm.create = (t_raqm_create)GetProcAddress(p_raqm.raqm, "raqm_create");
 | 
					    p_raqm.create = (t_raqm_create)GetProcAddress(p_raqm.raqm, "raqm_create");
 | 
				
			||||||
    p_raqm.set_text = (t_raqm_set_text)GetProcAddress(p_raqm.raqm, "raqm_set_text");
 | 
					    p_raqm.set_text = (t_raqm_set_text)GetProcAddress(p_raqm.raqm, "raqm_set_text");
 | 
				
			||||||
| 
						 | 
					@ -1257,6 +1261,9 @@ setup_module(PyObject* m) {
 | 
				
			||||||
    setraqm();
 | 
					    setraqm();
 | 
				
			||||||
    v = PyBool_FromLong(!!p_raqm.raqm);
 | 
					    v = PyBool_FromLong(!!p_raqm.raqm);
 | 
				
			||||||
    PyDict_SetItemString(d, "HAVE_RAQM", v);
 | 
					    PyDict_SetItemString(d, "HAVE_RAQM", v);
 | 
				
			||||||
 | 
					    if (p_raqm.version_string) {
 | 
				
			||||||
 | 
					        PyDict_SetItemString(d, "raqm_version", PyUnicode_FromString(p_raqm.version_string()));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										13
									
								
								src/_webp.c
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								src/_webp.c
									
									
									
									
									
								
							| 
						 | 
					@ -821,6 +821,16 @@ PyObject* WebPDecoderVersion_wrapper() {
 | 
				
			||||||
    return Py_BuildValue("i", WebPGetDecoderVersion());
 | 
					    return Py_BuildValue("i", WebPGetDecoderVersion());
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Version as string
 | 
				
			||||||
 | 
					const char*
 | 
				
			||||||
 | 
					WebPDecoderVersion_str(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    static char version[20];
 | 
				
			||||||
 | 
					    int version_number = WebPGetDecoderVersion();
 | 
				
			||||||
 | 
					    sprintf(version, "%d.%d.%d", version_number >> 16, (version_number >> 8) % 0x100, version_number % 0x100);
 | 
				
			||||||
 | 
					    return version;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * The version of webp that ships with (0.1.3) Ubuntu 12.04 doesn't handle alpha well.
 | 
					 * The version of webp that ships with (0.1.3) Ubuntu 12.04 doesn't handle alpha well.
 | 
				
			||||||
 * Files that are valid with 0.3 are reported as being invalid.
 | 
					 * Files that are valid with 0.3 are reported as being invalid.
 | 
				
			||||||
| 
						 | 
					@ -872,10 +882,13 @@ void addTransparencyFlagToModule(PyObject* m) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int setup_module(PyObject* m) {
 | 
					static int setup_module(PyObject* m) {
 | 
				
			||||||
 | 
					    PyObject* d = PyModule_GetDict(m);
 | 
				
			||||||
    addMuxFlagToModule(m);
 | 
					    addMuxFlagToModule(m);
 | 
				
			||||||
    addAnimFlagToModule(m);
 | 
					    addAnimFlagToModule(m);
 | 
				
			||||||
    addTransparencyFlagToModule(m);
 | 
					    addTransparencyFlagToModule(m);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    PyDict_SetItemString(d, "webpdecoder_version", PyUnicode_FromString(WebPDecoderVersion_str()));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef HAVE_WEBPANIM
 | 
					#ifdef HAVE_WEBPANIM
 | 
				
			||||||
    /* Ready object types */
 | 
					    /* Ready object types */
 | 
				
			||||||
    if (PyType_Ready(&WebPAnimDecoder_Type) < 0 ||
 | 
					    if (PyType_Ready(&WebPAnimDecoder_Type) < 0 ||
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -113,4 +113,13 @@ err:
 | 
				
			||||||
    return result;
 | 
					    return result;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const char*
 | 
				
			||||||
 | 
					ImagingImageQuantVersion(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    static char version[20];
 | 
				
			||||||
 | 
					    int number = liq_version();
 | 
				
			||||||
 | 
					    sprintf(version, "%d.%d.%d", number / 10000, (number / 100) % 100, number % 100);
 | 
				
			||||||
 | 
					    return version;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -373,7 +373,7 @@ ImagingZipEncodeCleanup(ImagingCodecState state) {
 | 
				
			||||||
const char*
 | 
					const char*
 | 
				
			||||||
ImagingZipVersion(void)
 | 
					ImagingZipVersion(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    return ZLIB_VERSION;
 | 
					    return zlibVersion();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user