def test_unsupported_module(): # Arrange module = "unsupported_module" # Act / Assert with pytest.raises(ValueError): features.check_module(module) with pytest.raises(ValueError): features.version_module(module)
def test_combine(name, text, dir, anchor, epsilon): if (parse_version(features.version_module("freetype2")) < parse_version("2.5.1") and dir == "ttb"): # FreeType 2.5.1 README: Miscellaneous Changes: # Improved computation of emulated vertical metrics for TrueType fonts. pytest.skip("FreeType <2.5.1 has incompatible ttb metrics") path = f"Tests/images/test_combine_{name}.png" f = ImageFont.truetype("Tests/fonts/NotoSans-Regular.ttf", 48) im = Image.new("RGB", (400, 400), "white") d = ImageDraw.Draw(im) d.line(((0, 200), (400, 200)), "gray") d.line(((200, 0), (200, 400)), "gray") try: d.text((200, 200), text, fill="black", anchor=anchor, direction=dir, font=f) except ValueError as ex: if str(ex) == "libraqm 0.7 or greater required for 'ttb' direction": pytest.skip("libraqm 0.7 or greater not available") assert_image_similar_tofile(im, path, epsilon)
def test_write_animation_L(tmp_path): """ Convert an animated GIF to animated WebP, then compare the frame count, and first and last frames to ensure they're visually similar. """ with Image.open("Tests/images/iss634.gif") as orig: assert orig.n_frames > 1 temp_file = str(tmp_path / "temp.webp") orig.save(temp_file, save_all=True) with Image.open(temp_file) as im: assert im.n_frames == orig.n_frames # Compare first and last frames to the original animated GIF orig.load() im.load() assert_image_similar(im, orig.convert("RGBA"), 32.9) if is_big_endian(): webp = parse_version(features.version_module("webp")) if webp < parse_version("1.2.2"): pytest.skip("Fails with libwebp earlier than 1.2.2") orig.seek(orig.n_frames - 1) im.seek(im.n_frames - 1) orig.load() im.load() assert_image_similar(im, orig.convert("RGBA"), 32.9)
def test_anchor(self, anchor, left, left_old, top): name, text = "quick", "Quick" path = f"Tests/images/test_anchor_{name}_{anchor}.png" freetype = parse_version(features.version_module("freetype2")) if freetype < parse_version("2.4"): width, height = (129, 44) left = left_old elif self.LAYOUT_ENGINE == ImageFont.LAYOUT_RAQM: width, height = (129, 44) else: width, height = (128, 44) bbox_expected = (left, top, left + width, top + height) f = ImageFont.truetype("Tests/fonts/NotoSans-Regular.ttf", 48, layout_engine=self.LAYOUT_ENGINE) im = Image.new("RGB", (200, 200), "white") d = ImageDraw.Draw(im) d.line(((0, 100), (200, 100)), "gray") d.line(((100, 0), (100, 200)), "gray") d.text((100, 100), text, fill="black", anchor=anchor, font=f) assert d.textbbox((0, 0), text, f, anchor=anchor) == bbox_expected assert_image_similar_tofile(im, path, 7)
def test_anchor_ttb(anchor): if parse_version( features.version_module("freetype2")) < parse_version("2.5.1"): # FreeType 2.5.1 README: Miscellaneous Changes: # Improved computation of emulated vertical metrics for TrueType fonts. pytest.skip("FreeType <2.5.1 has incompatible ttb metrics") text = "f" path = f"Tests/images/test_anchor_ttb_{text}_{anchor}.png" f = ImageFont.truetype("Tests/fonts/NotoSans-Regular.ttf", 120) im = Image.new("RGB", (200, 400), "white") d = ImageDraw.Draw(im) d.line(((0, 200), (200, 200)), "gray") d.line(((100, 0), (100, 400)), "gray") try: d.text((100, 200), text, fill="black", anchor=anchor, direction="ttb", font=f) except ValueError as ex: if str(ex) == "libraqm 0.7 or greater required for 'ttb' direction": pytest.skip("libraqm 0.7 or greater not available") with Image.open(path) as expected: assert_image_similar(im, expected, 1) # fails at 5
def test_variation_get(self): font = self.get_font() freetype = parse_version(features.version_module("freetype2")) if freetype < parse_version("2.9.1"): with pytest.raises(NotImplementedError): font.get_variation_names() with pytest.raises(NotImplementedError): font.get_variation_axes() return with pytest.raises(OSError): font.get_variation_names() with pytest.raises(OSError): font.get_variation_axes() font = ImageFont.truetype("Tests/fonts/AdobeVFPrototype.ttf") assert font.get_variation_names(), [ b"ExtraLight", b"Light", b"Regular", b"Semibold", b"Bold", b"Black", b"Black Medium Contrast", b"Black High Contrast", b"Default", ] assert font.get_variation_axes() == [ {"name": b"Weight", "minimum": 200, "maximum": 900, "default": 389}, {"name": b"Contrast", "minimum": 0, "maximum": 100, "default": 0}, ] font = ImageFont.truetype("Tests/fonts/TINY5x3GX.ttf") assert font.get_variation_names() == [ b"20", b"40", b"60", b"80", b"100", b"120", b"140", b"160", b"180", b"200", b"220", b"240", b"260", b"280", b"300", b"Regular", ] assert font.get_variation_axes() == [ {"name": b"Size", "minimum": 0, "maximum": 300, "default": 0} ]
def check(temp_file): with Image.open(temp_file) as im: assert im.n_frames == 2 # Compare first frame to original im.load() assert_image_equal(im, frame1.convert("RGBA")) # Compare second frame to original if is_big_endian(): webp = parse_version(features.version_module("webp")) if webp < parse_version("1.2.2"): pytest.skip("Fails with libwebp earlier than 1.2.2") im.seek(1) im.load() assert_image_equal(im, frame2.convert("RGBA"))
def test_variation_set_by_axes(self): font = self.get_font() freetype = parse_version(features.version_module("freetype2")) if freetype < parse_version("2.9.1"): with pytest.raises(NotImplementedError): font.set_variation_by_axes([100]) return with pytest.raises(OSError): font.set_variation_by_axes([500, 50]) font = ImageFont.truetype("Tests/fonts/AdobeVFPrototype.ttf", 36) font.set_variation_by_axes([500, 50]) self._check_text(font, "Tests/images/variation_adobe_axes.png", 11.05) font = ImageFont.truetype("Tests/fonts/TINY5x3GX.ttf", 36) font.set_variation_by_axes([100]) self._check_text(font, "Tests/images/variation_tiny_axes.png", 32.5)
def test_sanity(): # basic smoke test. # this mostly follows the cms_test outline. v = ImageCms.versions() # should return four strings assert v[0] == "1.0.0 pil" assert list(map(type, v)) == [str, str, str, str] # internal version number assert re.search(r"\d+\.\d+(\.\d+)?$", features.version_module("littlecms2")) skip_missing() i = ImageCms.profileToProfile(hopper(), SRGB, SRGB) assert_image(i, "RGB", (128, 128)) i = hopper() ImageCms.profileToProfile(i, SRGB, SRGB, inPlace=True) assert_image(i, "RGB", (128, 128)) t = ImageCms.buildTransform(SRGB, SRGB, "RGB", "RGB") i = ImageCms.applyTransform(hopper(), t) assert_image(i, "RGB", (128, 128)) with hopper() as i: t = ImageCms.buildTransform(SRGB, SRGB, "RGB", "RGB") ImageCms.applyTransform(hopper(), t, inPlace=True) assert_image(i, "RGB", (128, 128)) p = ImageCms.createProfile("sRGB") o = ImageCms.getOpenProfile(SRGB) t = ImageCms.buildTransformFromOpenProfiles(p, o, "RGB", "RGB") i = ImageCms.applyTransform(hopper(), t) assert_image(i, "RGB", (128, 128)) t = ImageCms.buildProofTransform(SRGB, SRGB, SRGB, "RGB", "RGB") assert t.inputMode == "RGB" assert t.outputMode == "RGB" i = ImageCms.applyTransform(hopper(), t) assert_image(i, "RGB", (128, 128)) # test PointTransform convenience API hopper().point(t)
def setup_class(self): freetype = parse_version(features.version_module("freetype2")) self.metrics = self.METRICS["Default"] for conditions, metrics in self.METRICS.items(): if not isinstance(conditions, tuple): continue for condition in conditions: version = parse_version(re.sub("[<=>]", "", condition)) if (condition.startswith(">=") and freetype >= version) or (condition.startswith("<") and freetype < version): # Condition was met continue # Condition failed break else: # All conditions were met self.metrics = metrics
def test_variation_set_by_name(self): font = self.get_font() freetype = parse_version(features.version_module("freetype2")) if freetype < parse_version("2.9.1"): with pytest.raises(NotImplementedError): font.set_variation_by_name("Bold") return with pytest.raises(OSError): font.set_variation_by_name("Bold") font = ImageFont.truetype("Tests/fonts/AdobeVFPrototype.ttf", 36) self._check_text(font, "Tests/images/variation_adobe.png", 11) for name in ["Bold", b"Bold"]: font.set_variation_by_name(name) self._check_text(font, "Tests/images/variation_adobe_name.png", 11) font = ImageFont.truetype("Tests/fonts/TINY5x3GX.ttf", 36) self._check_text(font, "Tests/images/variation_tiny.png", 40) for name in ["200", b"200"]: font.set_variation_by_name(name) self._check_text(font, "Tests/images/variation_tiny_name.png", 40)
def test_version(self): _webp.WebPDecoderVersion() _webp.WebPDecoderBuggyAlpha() assert re.search(r"\d+\.\d+\.\d+$", features.version_module("webp"))
def test_sanity(self): assert re.search(r"\d+\.\d+\.\d+$", features.version_module("freetype2"))
def test_version(self): _avif.AvifCodecVersions() assert re.search(r"\d+\.\d+\.\d+$", features.version_module("avif"))