Skip to content

Commit

Permalink
Merge branch 'main' into improved_dds
Browse files Browse the repository at this point in the history
  • Loading branch information
radarhere committed Oct 21, 2023
2 parents 935958c + d05ff50 commit a54d28a
Show file tree
Hide file tree
Showing 73 changed files with 856 additions and 300 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/cifuzz.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ name: CIFuzz

on:
push:
branches:
- "**"
paths:
- ".github/workflows/cifuzz.yml"
- "**.c"
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ name: Docs

on:
push:
branches:
- "**"
paths:
- ".github/workflows/docs.yml"
- "docs/**"
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/test-cygwin.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ name: Test Cygwin

on:
push:
branches:
- "**"
paths-ignore:
- ".github/workflows/docs.yml"
- ".github/workflows/wheels*"
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/test-docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ name: Test Docker

on:
push:
branches:
- "**"
paths-ignore:
- ".github/workflows/docs.yml"
- ".github/workflows/wheels*"
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/test-mingw.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ name: Test MinGW

on:
push:
branches:
- "**"
paths-ignore:
- ".github/workflows/docs.yml"
- ".github/workflows/wheels*"
Expand Down
4 changes: 3 additions & 1 deletion .github/workflows/test-valgrind.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
name: Test Valgrind

# like the docker tests, but running valgrind only on *.c/*.h changes.
# like the Docker tests, but running valgrind only on *.c/*.h changes.

on:
push:
branches:
- "**"
paths:
- ".github/workflows/test-valgrind.yml"
- "**.c"
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ name: Test

on:
push:
branches:
- "**"
paths-ignore:
- ".github/workflows/docs.yml"
- ".github/workflows/wheels*"
Expand Down
29 changes: 22 additions & 7 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,24 @@
Changelog (Pillow)
==================

10.1.0 (unreleased)
10.1.0 (2023-10-15)
-------------------

- Added TrueType default font to allow for different sizes #7354
[radarhere]

- Fixed invalid argument warning #7442
[radarhere]

- Added ImageOps cover method #7412
[radarhere, hugovk]

- Catch struct.error from truncated EXIF when reading JPEG DPI #7458
[radarhere]

- Consider default image when selecting mode for PNG save_all #7437
[radarhere]

- Support BGR;15, BGR;16 and BGR;24 access, unpacking and putdata #7303
[radarhere]

Expand Down Expand Up @@ -2176,7 +2191,7 @@ Changelog (Pillow)
- Cache EXIF information #3498
[Glandos]

- Added transparency for all PNG greyscale modes #3744
- Added transparency for all PNG grayscale modes #3744
[radarhere]

- Fix deprecation warnings in Python 3.8 #3749
Expand Down Expand Up @@ -4678,7 +4693,7 @@ Changelog (Pillow)
- Fix Bicubic interpolation #970
[homm]

- Support for 4-bit greyscale TIFF images #980
- Support for 4-bit grayscale TIFF images #980
[hugovk]

- Updated manifest #957
Expand Down Expand Up @@ -6753,7 +6768,7 @@ The test suite includes 750 individual tests.

- You can now convert directly between all modes supported by
PIL. When converting colour images to "P", PIL defaults to
a "web" palette and dithering. When converting greyscale
a "web" palette and dithering. When converting grayscale
images to "1", PIL uses a thresholding and dithering.

- Added a "dither" option to "convert". By default, "convert"
Expand Down Expand Up @@ -6831,13 +6846,13 @@ The test suite includes 530 individual tests.
- Fixed "paste" to allow a mask also for mode "F" images.

- The BMP driver now saves mode "1" images. When loading images, the mode
is set to "L" for 8-bit files with greyscale palettes, and to "P" for
is set to "L" for 8-bit files with grayscale palettes, and to "P" for
other 8-bit files.

- The IM driver now reads and saves "1" images (file modes "0 1" or "L 1").

- The JPEG and GIF drivers now saves "1" images. For JPEG, the image
is saved as 8-bit greyscale (it will load as mode "L"). For GIF, the
is saved as 8-bit grayscale (it will load as mode "L"). For GIF, the
image will be loaded as a "P" image.

- Fixed a potential buffer overrun in the GIF encoder.
Expand Down Expand Up @@ -7141,7 +7156,7 @@ The test suite includes 400 individual tests.
drawing capabilities can be used to render vector and metafile
formats.

- Added restricted drivers for images from Image Tools (greyscale
- Added restricted drivers for images from Image Tools (grayscale
only) and LabEye/IFUNC (common interchange modes only).

- Some minor improvements to the sample scripts provided in the
Expand Down
2 changes: 1 addition & 1 deletion RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ Released as needed privately to individual vendors for critical security-related
and copy into `dist/`. For example using [GitHub CLI](https://github.com/cli/cli):
```bash
gh run download --dir dist
# select dist-x.y.z
# select wheels
```
* [ ] Download the Linux aarch64 wheels created by Travis CI from [GitHub releases](https://github.com/python-pillow/Pillow/releases)
and copy into `dist`.
Expand Down
File renamed without changes
File renamed without changes
Binary file added Tests/images/default_font_freetype.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
File renamed without changes.
Binary file added Tests/images/imagedraw_default_font_size.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Tests/images/truncated_exif_dpi.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 10 additions & 4 deletions Tests/test_file_apng.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,13 +231,13 @@ def test_apng_mode():
assert im.getpixel((0, 0)) == (0, 0, 128, 191)
assert im.getpixel((64, 32)) == (0, 0, 128, 191)

with Image.open("Tests/images/apng/mode_greyscale.png") as im:
with Image.open("Tests/images/apng/mode_grayscale.png") as im:
assert im.mode == "L"
im.seek(im.n_frames - 1)
assert im.getpixel((0, 0)) == 128
assert im.getpixel((64, 32)) == 255

with Image.open("Tests/images/apng/mode_greyscale_alpha.png") as im:
with Image.open("Tests/images/apng/mode_grayscale_alpha.png") as im:
assert im.mode == "LA"
im.seek(im.n_frames - 1)
assert im.getpixel((0, 0)) == (128, 191)
Expand Down Expand Up @@ -673,10 +673,16 @@ def test_seek_after_close():


@pytest.mark.parametrize("mode", ("RGBA", "RGB", "P"))
def test_different_modes_in_later_frames(mode, tmp_path):
@pytest.mark.parametrize("default_image", (True, False))
def test_different_modes_in_later_frames(mode, default_image, tmp_path):
test_file = str(tmp_path / "temp.png")

im = Image.new("L", (1, 1))
im.save(test_file, save_all=True, append_images=[Image.new(mode, (1, 1))])
im.save(
test_file,
save_all=True,
default_image=default_image,
append_images=[Image.new(mode, (1, 1))],
)
with Image.open(test_file) as reloaded:
assert reloaded.mode == mode
2 changes: 1 addition & 1 deletion Tests/test_file_bmp.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ def test_rle8():
with Image.open("Tests/images/hopper_rle8.bmp") as im:
assert_image_similar_tofile(im.convert("RGB"), "Tests/images/hopper.bmp", 12)

with Image.open("Tests/images/hopper_rle8_greyscale.bmp") as im:
with Image.open("Tests/images/hopper_rle8_grayscale.bmp") as im:
assert_image_equal_tofile(im, "Tests/images/bw_gradient.png")

# This test image has been manually hexedited
Expand Down
2 changes: 1 addition & 1 deletion Tests/test_file_gif.py
Original file line number Diff line number Diff line change
Expand Up @@ -590,7 +590,7 @@ def test_save_dispose(tmp_path):
def test_dispose2_palette(tmp_path):
out = str(tmp_path / "temp.gif")

# Four colors: white, grey, black, red
# Four colors: white, gray, black, red
circles = [(255, 255, 255), (153, 153, 153), (0, 0, 0), (255, 0, 0)]

im_list = []
Expand Down
7 changes: 7 additions & 0 deletions Tests/test_file_jpeg.py
Original file line number Diff line number Diff line change
Expand Up @@ -767,6 +767,13 @@ def test_dpi_exif_string(self):
# This should return the default
assert im.info.get("dpi") == (72, 72)

def test_dpi_exif_truncated(self):
# Arrange
with Image.open("Tests/images/truncated_exif_dpi.jpg") as im:
# Act / Assert
# This should return the default
assert im.info.get("dpi") == (72, 72)

def test_no_dpi_in_exif(self):
# Arrange
# This is photoshop-200dpi.jpg with resolution removed from EXIF:
Expand Down
3 changes: 1 addition & 2 deletions Tests/test_file_palm.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@ def open_with_magick(magick, tmp_path, f):
rc = subprocess.call(
magick + [f, outfile], stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT
)
if rc:
raise OSError
assert not rc
return Image.open(outfile)


Expand Down
2 changes: 1 addition & 1 deletion Tests/test_file_png.py
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ def test_save_p_transparent_black(self, tmp_path):
assert_image(im, "RGBA", (10, 10))
assert im.getcolors() == [(100, (0, 0, 0, 0))]

def test_save_greyscale_transparency(self, tmp_path):
def test_save_grayscale_transparency(self, tmp_path):
for mode, num_transparent in {"1": 1994, "L": 559, "I": 559}.items():
in_file = "Tests/images/" + mode.lower() + "_trns.png"
with Image.open(in_file) as im:
Expand Down
8 changes: 4 additions & 4 deletions Tests/test_imagechops.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
ORANGE = (255, 128, 0)
WHITE = (255, 255, 255)

GREY = 128
GRAY = 128


def test_sanity():
Expand Down Expand Up @@ -121,12 +121,12 @@ def test_constant():
im = Image.new("RGB", (20, 10))

# Act
new = ImageChops.constant(im, GREY)
new = ImageChops.constant(im, GRAY)

# Assert
assert new.size == im.size
assert new.getpixel((0, 0)) == GREY
assert new.getpixel((19, 9)) == GREY
assert new.getpixel((0, 0)) == GRAY
assert new.getpixel((19, 9)) == GRAY


def test_darker_image():
Expand Down
31 changes: 29 additions & 2 deletions Tests/test_imagedraw.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import contextlib
import os.path

import pytest

from PIL import Image, ImageColor, ImageDraw, ImageFont
from PIL import Image, ImageColor, ImageDraw, ImageFont, features

from .helper import (
assert_image_equal,
Expand Down Expand Up @@ -1353,7 +1354,33 @@ def test_setting_default_font():
assert draw.getfont() == font
finally:
ImageDraw.ImageDraw.font = None
assert isinstance(draw.getfont(), ImageFont.ImageFont)
assert isinstance(draw.getfont(), ImageFont.load_default().__class__)


def test_default_font_size():
freetype_support = features.check_module("freetype2")
text = "Default font at a specific size."

im = Image.new("RGB", (220, 25))
draw = ImageDraw.Draw(im)
with contextlib.nullcontext() if freetype_support else pytest.raises(ImportError):
draw.text((0, 0), text, font_size=16)
assert_image_equal_tofile(im, "Tests/images/imagedraw_default_font_size.png")

with contextlib.nullcontext() if freetype_support else pytest.raises(ImportError):
assert draw.textlength(text, font_size=16) == 216

with contextlib.nullcontext() if freetype_support else pytest.raises(ImportError):
assert draw.textbbox((0, 0), text, font_size=16) == (0, 3, 216, 19)

im = Image.new("RGB", (220, 25))
draw = ImageDraw.Draw(im)
with contextlib.nullcontext() if freetype_support else pytest.raises(ImportError):
draw.multiline_text((0, 0), text, font_size=16)
assert_image_equal_tofile(im, "Tests/images/imagedraw_default_font_size.png")

with contextlib.nullcontext() if freetype_support else pytest.raises(ImportError):
assert draw.multiline_textbbox((0, 0), text, font_size=16) == (0, 3, 216, 19)


@pytest.mark.parametrize("bbox", BBOX)
Expand Down
31 changes: 9 additions & 22 deletions Tests/test_imagefont.py
Original file line number Diff line number Diff line change
Expand Up @@ -303,8 +303,8 @@ def test_multiline_spacing(font):
"orientation", (Image.Transpose.ROTATE_90, Image.Transpose.ROTATE_270)
)
def test_rotated_transposed_font(font, orientation):
img_grey = Image.new("L", (100, 100))
draw = ImageDraw.Draw(img_grey)
img_gray = Image.new("L", (100, 100))
draw = ImageDraw.Draw(img_gray)
word = "testing"

transposed_font = ImageFont.TransposedFont(font, orientation=orientation)
Expand Down Expand Up @@ -344,8 +344,8 @@ def test_rotated_transposed_font(font, orientation):
),
)
def test_unrotated_transposed_font(font, orientation):
img_grey = Image.new("L", (100, 100))
draw = ImageDraw.Draw(img_grey)
img_gray = Image.new("L", (100, 100))
draw = ImageDraw.Draw(img_gray)
word = "testing"

transposed_font = ImageFont.TransposedFont(font, orientation=orientation)
Expand Down Expand Up @@ -453,16 +453,19 @@ def test_load_non_font_bytes():

def test_default_font():
# Arrange
txt = 'This is a "better than nothing" default font.'
txt = "This is a default font using FreeType support."
im = Image.new(mode="RGB", size=(300, 100))
draw = ImageDraw.Draw(im)

# Act
default_font = ImageFont.load_default()
draw.text((10, 10), txt, font=default_font)

larger_default_font = ImageFont.load_default(size=14)
draw.text((10, 60), txt, font=larger_default_font)

# Assert
assert_image_equal_tofile(im, "Tests/images/default_font.png")
assert_image_equal_tofile(im, "Tests/images/default_font_freetype.png")


@pytest.mark.parametrize("mode", (None, "1", "RGBA"))
Expand All @@ -485,14 +488,6 @@ def test_render_empty(font):
assert_image_equal(im, target)


def test_unicode_pilfont():
# should not segfault, should return UnicodeDecodeError
# issue #2826
font = ImageFont.load_default()
with pytest.raises(UnicodeEncodeError):
font.getbbox("’")


def test_unicode_extended(layout_engine):
# issue #3777
text = "A\u278A\U0001F12B"
Expand Down Expand Up @@ -722,14 +717,6 @@ def test_variation_set_by_axes(font):
_check_text(font, "Tests/images/variation_tiny_axes.png", 32.5)


def test_textbbox_non_freetypefont():
im = Image.new("RGB", (200, 200))
d = ImageDraw.Draw(im)
default_font = ImageFont.load_default()
assert d.textlength("test", font=default_font) == 24
assert d.textbbox((0, 0), "test", font=default_font) == (0, 0, 24, 11)


@pytest.mark.parametrize(
"anchor, left, top",
(
Expand Down
Loading

0 comments on commit a54d28a

Please sign in to comment.