Merge branch 'main' into improved_dds
2
.github/workflows/cifuzz.yml
vendored
|
@ -2,6 +2,8 @@ name: CIFuzz
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
|
branches:
|
||||||
|
- "**"
|
||||||
paths:
|
paths:
|
||||||
- ".github/workflows/cifuzz.yml"
|
- ".github/workflows/cifuzz.yml"
|
||||||
- "**.c"
|
- "**.c"
|
||||||
|
|
2
.github/workflows/docs.yml
vendored
|
@ -2,6 +2,8 @@ name: Docs
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
|
branches:
|
||||||
|
- "**"
|
||||||
paths:
|
paths:
|
||||||
- ".github/workflows/docs.yml"
|
- ".github/workflows/docs.yml"
|
||||||
- "docs/**"
|
- "docs/**"
|
||||||
|
|
2
.github/workflows/test-cygwin.yml
vendored
|
@ -2,6 +2,8 @@ name: Test Cygwin
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
|
branches:
|
||||||
|
- "**"
|
||||||
paths-ignore:
|
paths-ignore:
|
||||||
- ".github/workflows/docs.yml"
|
- ".github/workflows/docs.yml"
|
||||||
- ".github/workflows/wheels*"
|
- ".github/workflows/wheels*"
|
||||||
|
|
2
.github/workflows/test-docker.yml
vendored
|
@ -2,6 +2,8 @@ name: Test Docker
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
|
branches:
|
||||||
|
- "**"
|
||||||
paths-ignore:
|
paths-ignore:
|
||||||
- ".github/workflows/docs.yml"
|
- ".github/workflows/docs.yml"
|
||||||
- ".github/workflows/wheels*"
|
- ".github/workflows/wheels*"
|
||||||
|
|
2
.github/workflows/test-mingw.yml
vendored
|
@ -2,6 +2,8 @@ name: Test MinGW
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
|
branches:
|
||||||
|
- "**"
|
||||||
paths-ignore:
|
paths-ignore:
|
||||||
- ".github/workflows/docs.yml"
|
- ".github/workflows/docs.yml"
|
||||||
- ".github/workflows/wheels*"
|
- ".github/workflows/wheels*"
|
||||||
|
|
4
.github/workflows/test-valgrind.yml
vendored
|
@ -1,9 +1,11 @@
|
||||||
name: Test Valgrind
|
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:
|
on:
|
||||||
push:
|
push:
|
||||||
|
branches:
|
||||||
|
- "**"
|
||||||
paths:
|
paths:
|
||||||
- ".github/workflows/test-valgrind.yml"
|
- ".github/workflows/test-valgrind.yml"
|
||||||
- "**.c"
|
- "**.c"
|
||||||
|
|
2
.github/workflows/test.yml
vendored
|
@ -2,6 +2,8 @@ name: Test
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
|
branches:
|
||||||
|
- "**"
|
||||||
paths-ignore:
|
paths-ignore:
|
||||||
- ".github/workflows/docs.yml"
|
- ".github/workflows/docs.yml"
|
||||||
- ".github/workflows/wheels*"
|
- ".github/workflows/wheels*"
|
||||||
|
|
29
CHANGES.rst
|
@ -2,9 +2,24 @@
|
||||||
Changelog (Pillow)
|
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
|
- Support BGR;15, BGR;16 and BGR;24 access, unpacking and putdata #7303
|
||||||
[radarhere]
|
[radarhere]
|
||||||
|
|
||||||
|
@ -2176,7 +2191,7 @@ Changelog (Pillow)
|
||||||
- Cache EXIF information #3498
|
- Cache EXIF information #3498
|
||||||
[Glandos]
|
[Glandos]
|
||||||
|
|
||||||
- Added transparency for all PNG greyscale modes #3744
|
- Added transparency for all PNG grayscale modes #3744
|
||||||
[radarhere]
|
[radarhere]
|
||||||
|
|
||||||
- Fix deprecation warnings in Python 3.8 #3749
|
- Fix deprecation warnings in Python 3.8 #3749
|
||||||
|
@ -4678,7 +4693,7 @@ Changelog (Pillow)
|
||||||
- Fix Bicubic interpolation #970
|
- Fix Bicubic interpolation #970
|
||||||
[homm]
|
[homm]
|
||||||
|
|
||||||
- Support for 4-bit greyscale TIFF images #980
|
- Support for 4-bit grayscale TIFF images #980
|
||||||
[hugovk]
|
[hugovk]
|
||||||
|
|
||||||
- Updated manifest #957
|
- Updated manifest #957
|
||||||
|
@ -6753,7 +6768,7 @@ The test suite includes 750 individual tests.
|
||||||
|
|
||||||
- You can now convert directly between all modes supported by
|
- You can now convert directly between all modes supported by
|
||||||
PIL. When converting colour images to "P", PIL defaults to
|
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.
|
images to "1", PIL uses a thresholding and dithering.
|
||||||
|
|
||||||
- Added a "dither" option to "convert". By default, "convert"
|
- Added a "dither" option to "convert". By default, "convert"
|
||||||
|
@ -6831,13 +6846,13 @@ The test suite includes 530 individual tests.
|
||||||
- Fixed "paste" to allow a mask also for mode "F" images.
|
- Fixed "paste" to allow a mask also for mode "F" images.
|
||||||
|
|
||||||
- The BMP driver now saves mode "1" images. When loading images, the mode
|
- 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.
|
other 8-bit files.
|
||||||
|
|
||||||
- The IM driver now reads and saves "1" images (file modes "0 1" or "L 1").
|
- 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
|
- 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.
|
image will be loaded as a "P" image.
|
||||||
|
|
||||||
- Fixed a potential buffer overrun in the GIF encoder.
|
- Fixed a potential buffer overrun in the GIF encoder.
|
||||||
|
@ -7141,7 +7156,7 @@ The test suite includes 400 individual tests.
|
||||||
drawing capabilities can be used to render vector and metafile
|
drawing capabilities can be used to render vector and metafile
|
||||||
formats.
|
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).
|
only) and LabEye/IFUNC (common interchange modes only).
|
||||||
|
|
||||||
- Some minor improvements to the sample scripts provided in the
|
- Some minor improvements to the sample scripts provided in the
|
||||||
|
|
|
@ -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):
|
and copy into `dist/`. For example using [GitHub CLI](https://github.com/cli/cli):
|
||||||
```bash
|
```bash
|
||||||
gh run download --dir dist
|
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)
|
* [ ] Download the Linux aarch64 wheels created by Travis CI from [GitHub releases](https://github.com/python-pillow/Pillow/releases)
|
||||||
and copy into `dist`.
|
and copy into `dist`.
|
||||||
|
|
Before Width: | Height: | Size: 331 B After Width: | Height: | Size: 331 B |
Before Width: | Height: | Size: 668 B After Width: | Height: | Size: 668 B |
BIN
Tests/images/default_font_freetype.png
Normal file
After Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 6.1 KiB |
BIN
Tests/images/imagedraw_default_font_size.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
BIN
Tests/images/truncated_exif_dpi.jpg
Normal file
After Width: | Height: | Size: 7.5 KiB |
|
@ -231,13 +231,13 @@ def test_apng_mode():
|
||||||
assert im.getpixel((0, 0)) == (0, 0, 128, 191)
|
assert im.getpixel((0, 0)) == (0, 0, 128, 191)
|
||||||
assert im.getpixel((64, 32)) == (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"
|
assert im.mode == "L"
|
||||||
im.seek(im.n_frames - 1)
|
im.seek(im.n_frames - 1)
|
||||||
assert im.getpixel((0, 0)) == 128
|
assert im.getpixel((0, 0)) == 128
|
||||||
assert im.getpixel((64, 32)) == 255
|
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"
|
assert im.mode == "LA"
|
||||||
im.seek(im.n_frames - 1)
|
im.seek(im.n_frames - 1)
|
||||||
assert im.getpixel((0, 0)) == (128, 191)
|
assert im.getpixel((0, 0)) == (128, 191)
|
||||||
|
@ -673,10 +673,16 @@ def test_seek_after_close():
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("mode", ("RGBA", "RGB", "P"))
|
@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")
|
test_file = str(tmp_path / "temp.png")
|
||||||
|
|
||||||
im = Image.new("L", (1, 1))
|
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:
|
with Image.open(test_file) as reloaded:
|
||||||
assert reloaded.mode == mode
|
assert reloaded.mode == mode
|
||||||
|
|
|
@ -159,7 +159,7 @@ def test_rle8():
|
||||||
with Image.open("Tests/images/hopper_rle8.bmp") as im:
|
with Image.open("Tests/images/hopper_rle8.bmp") as im:
|
||||||
assert_image_similar_tofile(im.convert("RGB"), "Tests/images/hopper.bmp", 12)
|
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")
|
assert_image_equal_tofile(im, "Tests/images/bw_gradient.png")
|
||||||
|
|
||||||
# This test image has been manually hexedited
|
# This test image has been manually hexedited
|
||||||
|
|
|
@ -590,7 +590,7 @@ def test_save_dispose(tmp_path):
|
||||||
def test_dispose2_palette(tmp_path):
|
def test_dispose2_palette(tmp_path):
|
||||||
out = str(tmp_path / "temp.gif")
|
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)]
|
circles = [(255, 255, 255), (153, 153, 153), (0, 0, 0), (255, 0, 0)]
|
||||||
|
|
||||||
im_list = []
|
im_list = []
|
||||||
|
|
|
@ -767,6 +767,13 @@ class TestFileJpeg:
|
||||||
# This should return the default
|
# This should return the default
|
||||||
assert im.info.get("dpi") == (72, 72)
|
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):
|
def test_no_dpi_in_exif(self):
|
||||||
# Arrange
|
# Arrange
|
||||||
# This is photoshop-200dpi.jpg with resolution removed from EXIF:
|
# This is photoshop-200dpi.jpg with resolution removed from EXIF:
|
||||||
|
|
|
@ -26,8 +26,7 @@ def open_with_magick(magick, tmp_path, f):
|
||||||
rc = subprocess.call(
|
rc = subprocess.call(
|
||||||
magick + [f, outfile], stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT
|
magick + [f, outfile], stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT
|
||||||
)
|
)
|
||||||
if rc:
|
assert not rc
|
||||||
raise OSError
|
|
||||||
return Image.open(outfile)
|
return Image.open(outfile)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -297,7 +297,7 @@ class TestFilePng:
|
||||||
assert_image(im, "RGBA", (10, 10))
|
assert_image(im, "RGBA", (10, 10))
|
||||||
assert im.getcolors() == [(100, (0, 0, 0, 0))]
|
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():
|
for mode, num_transparent in {"1": 1994, "L": 559, "I": 559}.items():
|
||||||
in_file = "Tests/images/" + mode.lower() + "_trns.png"
|
in_file = "Tests/images/" + mode.lower() + "_trns.png"
|
||||||
with Image.open(in_file) as im:
|
with Image.open(in_file) as im:
|
||||||
|
|
|
@ -10,7 +10,7 @@ GREEN = (0, 255, 0)
|
||||||
ORANGE = (255, 128, 0)
|
ORANGE = (255, 128, 0)
|
||||||
WHITE = (255, 255, 255)
|
WHITE = (255, 255, 255)
|
||||||
|
|
||||||
GREY = 128
|
GRAY = 128
|
||||||
|
|
||||||
|
|
||||||
def test_sanity():
|
def test_sanity():
|
||||||
|
@ -121,12 +121,12 @@ def test_constant():
|
||||||
im = Image.new("RGB", (20, 10))
|
im = Image.new("RGB", (20, 10))
|
||||||
|
|
||||||
# Act
|
# Act
|
||||||
new = ImageChops.constant(im, GREY)
|
new = ImageChops.constant(im, GRAY)
|
||||||
|
|
||||||
# Assert
|
# Assert
|
||||||
assert new.size == im.size
|
assert new.size == im.size
|
||||||
assert new.getpixel((0, 0)) == GREY
|
assert new.getpixel((0, 0)) == GRAY
|
||||||
assert new.getpixel((19, 9)) == GREY
|
assert new.getpixel((19, 9)) == GRAY
|
||||||
|
|
||||||
|
|
||||||
def test_darker_image():
|
def test_darker_image():
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
|
import contextlib
|
||||||
import os.path
|
import os.path
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from PIL import Image, ImageColor, ImageDraw, ImageFont
|
from PIL import Image, ImageColor, ImageDraw, ImageFont, features
|
||||||
|
|
||||||
from .helper import (
|
from .helper import (
|
||||||
assert_image_equal,
|
assert_image_equal,
|
||||||
|
@ -1353,7 +1354,33 @@ def test_setting_default_font():
|
||||||
assert draw.getfont() == font
|
assert draw.getfont() == font
|
||||||
finally:
|
finally:
|
||||||
ImageDraw.ImageDraw.font = None
|
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)
|
@pytest.mark.parametrize("bbox", BBOX)
|
||||||
|
|
|
@ -303,8 +303,8 @@ def test_multiline_spacing(font):
|
||||||
"orientation", (Image.Transpose.ROTATE_90, Image.Transpose.ROTATE_270)
|
"orientation", (Image.Transpose.ROTATE_90, Image.Transpose.ROTATE_270)
|
||||||
)
|
)
|
||||||
def test_rotated_transposed_font(font, orientation):
|
def test_rotated_transposed_font(font, orientation):
|
||||||
img_grey = Image.new("L", (100, 100))
|
img_gray = Image.new("L", (100, 100))
|
||||||
draw = ImageDraw.Draw(img_grey)
|
draw = ImageDraw.Draw(img_gray)
|
||||||
word = "testing"
|
word = "testing"
|
||||||
|
|
||||||
transposed_font = ImageFont.TransposedFont(font, orientation=orientation)
|
transposed_font = ImageFont.TransposedFont(font, orientation=orientation)
|
||||||
|
@ -344,8 +344,8 @@ def test_rotated_transposed_font(font, orientation):
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
def test_unrotated_transposed_font(font, orientation):
|
def test_unrotated_transposed_font(font, orientation):
|
||||||
img_grey = Image.new("L", (100, 100))
|
img_gray = Image.new("L", (100, 100))
|
||||||
draw = ImageDraw.Draw(img_grey)
|
draw = ImageDraw.Draw(img_gray)
|
||||||
word = "testing"
|
word = "testing"
|
||||||
|
|
||||||
transposed_font = ImageFont.TransposedFont(font, orientation=orientation)
|
transposed_font = ImageFont.TransposedFont(font, orientation=orientation)
|
||||||
|
@ -453,7 +453,7 @@ def test_load_non_font_bytes():
|
||||||
|
|
||||||
def test_default_font():
|
def test_default_font():
|
||||||
# Arrange
|
# 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))
|
im = Image.new(mode="RGB", size=(300, 100))
|
||||||
draw = ImageDraw.Draw(im)
|
draw = ImageDraw.Draw(im)
|
||||||
|
|
||||||
|
@ -461,8 +461,11 @@ def test_default_font():
|
||||||
default_font = ImageFont.load_default()
|
default_font = ImageFont.load_default()
|
||||||
draw.text((10, 10), txt, font=default_font)
|
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
|
||||||
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"))
|
@pytest.mark.parametrize("mode", (None, "1", "RGBA"))
|
||||||
|
@ -485,14 +488,6 @@ def test_render_empty(font):
|
||||||
assert_image_equal(im, target)
|
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):
|
def test_unicode_extended(layout_engine):
|
||||||
# issue #3777
|
# issue #3777
|
||||||
text = "A\u278A\U0001F12B"
|
text = "A\u278A\U0001F12B"
|
||||||
|
@ -722,14 +717,6 @@ def test_variation_set_by_axes(font):
|
||||||
_check_text(font, "Tests/images/variation_tiny_axes.png", 32.5)
|
_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(
|
@pytest.mark.parametrize(
|
||||||
"anchor, left, top",
|
"anchor, left, top",
|
||||||
(
|
(
|
||||||
|
|
45
Tests/test_imagefontpil.py
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from PIL import Image, ImageDraw, ImageFont, features
|
||||||
|
|
||||||
|
from .helper import assert_image_equal_tofile
|
||||||
|
|
||||||
|
pytestmark = pytest.mark.skipif(
|
||||||
|
features.check_module("freetype2"),
|
||||||
|
reason="PILfont superseded if FreeType is supported",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_default_font():
|
||||||
|
# Arrange
|
||||||
|
txt = 'This is a "better than nothing" default font.'
|
||||||
|
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)
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
assert_image_equal_tofile(im, "Tests/images/default_font.png")
|
||||||
|
|
||||||
|
|
||||||
|
def test_size_without_freetype():
|
||||||
|
with pytest.raises(ImportError):
|
||||||
|
ImageFont.load_default(size=14)
|
||||||
|
|
||||||
|
|
||||||
|
def test_unicode():
|
||||||
|
# should not segfault, should return UnicodeDecodeError
|
||||||
|
# issue #2826
|
||||||
|
font = ImageFont.load_default()
|
||||||
|
with pytest.raises(UnicodeEncodeError):
|
||||||
|
font.getbbox("’")
|
||||||
|
|
||||||
|
|
||||||
|
def test_textbbox():
|
||||||
|
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)
|
|
@ -39,6 +39,9 @@ def test_sanity():
|
||||||
ImageOps.contain(hopper("L"), (128, 128))
|
ImageOps.contain(hopper("L"), (128, 128))
|
||||||
ImageOps.contain(hopper("RGB"), (128, 128))
|
ImageOps.contain(hopper("RGB"), (128, 128))
|
||||||
|
|
||||||
|
ImageOps.cover(hopper("L"), (128, 128))
|
||||||
|
ImageOps.cover(hopper("RGB"), (128, 128))
|
||||||
|
|
||||||
ImageOps.crop(hopper("L"), 1)
|
ImageOps.crop(hopper("L"), 1)
|
||||||
ImageOps.crop(hopper("RGB"), 1)
|
ImageOps.crop(hopper("RGB"), 1)
|
||||||
|
|
||||||
|
@ -119,6 +122,20 @@ def test_contain_round():
|
||||||
assert new_im.height == 5
|
assert new_im.height == 5
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"image_name, expected_size",
|
||||||
|
(
|
||||||
|
("colr_bungee.png", (1024, 256)), # landscape
|
||||||
|
("imagedraw_stroke_multiline.png", (256, 640)), # portrait
|
||||||
|
("hopper.png", (256, 256)), # square
|
||||||
|
),
|
||||||
|
)
|
||||||
|
def test_cover(image_name, expected_size):
|
||||||
|
with Image.open("Tests/images/" + image_name) as im:
|
||||||
|
new_im = ImageOps.cover(im, (256, 256))
|
||||||
|
assert new_im.size == expected_size
|
||||||
|
|
||||||
|
|
||||||
def test_pad():
|
def test_pad():
|
||||||
# Same ratio
|
# Same ratio
|
||||||
im = hopper()
|
im = hopper()
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# install libimagequant
|
# install libimagequant
|
||||||
|
|
||||||
archive=libimagequant-4.2.1
|
archive=libimagequant-4.2.2
|
||||||
|
|
||||||
./download-and-extract.sh $archive https://raw.githubusercontent.com/python-pillow/pillow-depends/main/$archive.tar.gz
|
./download-and-extract.sh $archive https://raw.githubusercontent.com/python-pillow/pillow-depends/main/$archive.tar.gz
|
||||||
|
|
||||||
|
|
BIN
docs/example/image_thumbnail.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
docs/example/imageops_contain.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
docs/example/imageops_cover.png
Normal file
After Width: | Height: | Size: 38 KiB |
BIN
docs/example/imageops_fit.png
Normal file
After Width: | Height: | Size: 28 KiB |
BIN
docs/example/imageops_pad.png
Normal file
After Width: | Height: | Size: 19 KiB |
|
@ -26,7 +26,7 @@ image. If the image was not read from a file, it is set to None. The size
|
||||||
attribute is a 2-tuple containing width and height (in pixels). The
|
attribute is a 2-tuple containing width and height (in pixels). The
|
||||||
:py:attr:`~PIL.Image.Image.mode` attribute defines the number and names of the
|
:py:attr:`~PIL.Image.Image.mode` attribute defines the number and names of the
|
||||||
bands in the image, and also the pixel type and depth. Common modes are “L”
|
bands in the image, and also the pixel type and depth. Common modes are “L”
|
||||||
(luminance) for greyscale images, “RGB” for true color images, and “CMYK” for
|
(luminance) for grayscale images, “RGB” for true color images, and “CMYK” for
|
||||||
pre-press images.
|
pre-press images.
|
||||||
|
|
||||||
If the file cannot be opened, an :py:exc:`OSError` exception is raised.
|
If the file cannot be opened, an :py:exc:`OSError` exception is raised.
|
||||||
|
@ -268,6 +268,37 @@ true, to provide for the same changes to the image's size.
|
||||||
A more general form of image transformations can be carried out via the
|
A more general form of image transformations can be carried out via the
|
||||||
:py:meth:`~PIL.Image.Image.transform` method.
|
:py:meth:`~PIL.Image.Image.transform` method.
|
||||||
|
|
||||||
|
Relative resizing
|
||||||
|
^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Instead of calculating the size of the new image when resizing, you can also
|
||||||
|
choose to resize relative to a given size.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
from PIL import Image, ImageOps
|
||||||
|
size = (100, 150)
|
||||||
|
with Image.open("Tests/images/hopper.png") as im:
|
||||||
|
ImageOps.contain(im, size).save("imageops_contain.png")
|
||||||
|
ImageOps.cover(im, size).save("imageops_cover.png")
|
||||||
|
ImageOps.fit(im, size).save("imageops_fit.png")
|
||||||
|
ImageOps.pad(im, size, color="#f00").save("imageops_pad.png")
|
||||||
|
|
||||||
|
# thumbnail() can also be used,
|
||||||
|
# but will modify the image object in place
|
||||||
|
im.thumbnail(size)
|
||||||
|
im.save("imageops_thumbnail.png")
|
||||||
|
|
||||||
|
+----------------+-------------------------------------------+--------------------------------------------+------------------------------------------+----------------------------------------+----------------------------------------+
|
||||||
|
| | :py:meth:`~PIL.Image.Image.thumbnail` | :py:meth:`~PIL.ImageOps.contain` | :py:meth:`~PIL.ImageOps.cover` | :py:meth:`~PIL.ImageOps.fit` | :py:meth:`~PIL.ImageOps.pad` |
|
||||||
|
+================+===========================================+============================================+==========================================+========================================+========================================+
|
||||||
|
|Given size | ``(100, 150)`` | ``(100, 150)`` | ``(100, 150)`` | ``(100, 150)`` | ``(100, 150)`` |
|
||||||
|
+----------------+-------------------------------------------+--------------------------------------------+------------------------------------------+----------------------------------------+----------------------------------------+
|
||||||
|
|Resulting image | .. image:: ../example/image_thumbnail.png | .. image:: ../example/imageops_contain.png | .. image:: ../example/imageops_cover.png | .. image:: ../example/imageops_fit.png | .. image:: ../example/imageops_pad.png |
|
||||||
|
+----------------+-------------------------------------------+--------------------------------------------+------------------------------------------+----------------------------------------+----------------------------------------+
|
||||||
|
|Resulting size | ``100×100`` | ``100×100`` | ``150×150`` | ``100×150`` | ``100×150`` |
|
||||||
|
+----------------+-------------------------------------------+--------------------------------------------+------------------------------------------+----------------------------------------+----------------------------------------+
|
||||||
|
|
||||||
.. _color-transforms:
|
.. _color-transforms:
|
||||||
|
|
||||||
Color transforms
|
Color transforms
|
||||||
|
@ -568,7 +599,7 @@ Controlling the decoder
|
||||||
Some decoders allow you to manipulate the image while reading it from a file.
|
Some decoders allow you to manipulate the image while reading it from a file.
|
||||||
This can often be used to speed up decoding when creating thumbnails (when
|
This can often be used to speed up decoding when creating thumbnails (when
|
||||||
speed is usually more important than quality) and printing to a monochrome
|
speed is usually more important than quality) and printing to a monochrome
|
||||||
laser printer (when only a greyscale version of the image is needed).
|
laser printer (when only a grayscale version of the image is needed).
|
||||||
|
|
||||||
The :py:meth:`~PIL.Image.Image.draft` method manipulates an opened but not yet
|
The :py:meth:`~PIL.Image.Image.draft` method manipulates an opened but not yet
|
||||||
loaded image so it as closely as possible matches the given mode and size. This
|
loaded image so it as closely as possible matches the given mode and size. This
|
||||||
|
|
|
@ -26,14 +26,14 @@ Pillow decodes files in two stages:
|
||||||
it.
|
it.
|
||||||
|
|
||||||
An image plugin should contain a format handler derived from the
|
An image plugin should contain a format handler derived from the
|
||||||
:py:class:`PIL.ImageFile.ImageFile` base class. This class should
|
:py:class:`PIL.ImageFile.ImageFile` base class. This class should provide an
|
||||||
provide an ``_open`` method, which reads the file header and
|
``_open`` method, which reads the file header and set at least the internal
|
||||||
sets up at least the :py:attr:`~PIL.Image.Image.mode` and
|
``_size`` and ``_mode`` attributes so that :py:attr:`~PIL.Image.Image.mode` and
|
||||||
:py:attr:`~PIL.Image.Image.size` attributes. To be able to load the
|
:py:attr:`~PIL.Image.Image.size` are populated. To be able to load the file,
|
||||||
file, the method must also create a list of ``tile`` descriptors,
|
the method must also create a list of ``tile`` descriptors, which contain a
|
||||||
which contain a decoder name, extents of the tile, and
|
decoder name, extents of the tile, and any decoder-specific data. The format
|
||||||
any decoder-specific data. The format handler class must be explicitly
|
handler class must be explicitly registered, via a call to the
|
||||||
registered, via a call to the :py:mod:`~PIL.Image` module.
|
:py:mod:`~PIL.Image` module.
|
||||||
|
|
||||||
.. note:: For performance reasons, it is important that the
|
.. note:: For performance reasons, it is important that the
|
||||||
``_open`` method quickly rejects files that do not have the
|
``_open`` method quickly rejects files that do not have the
|
||||||
|
@ -45,7 +45,7 @@ Example
|
||||||
The following plugin supports a simple format, which has a 128-byte header
|
The following plugin supports a simple format, which has a 128-byte header
|
||||||
consisting of the words “SPAM” followed by the width, height, and pixel size in
|
consisting of the words “SPAM” followed by the width, height, and pixel size in
|
||||||
bits. The header fields are separated by spaces. The image data follows
|
bits. The header fields are separated by spaces. The image data follows
|
||||||
directly after the header, and can be either bi-level, greyscale, or 24-bit
|
directly after the header, and can be either bi-level, grayscale, or 24-bit
|
||||||
true color.
|
true color.
|
||||||
|
|
||||||
**SpamImagePlugin.py**::
|
**SpamImagePlugin.py**::
|
||||||
|
@ -96,13 +96,13 @@ true color.
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
The format handler must always set the
|
The format handler must always set the internal ``_size`` and ``_mode``
|
||||||
:py:attr:`~PIL.Image.Image.size` and :py:attr:`~PIL.Image.Image.mode`
|
attributes so that :py:attr:`~PIL.Image.Image.size` and
|
||||||
attributes. If these are not set, the file cannot be opened. To
|
:py:attr:`~PIL.Image.Image.mode` are populated. If these are not set, the file
|
||||||
simplify the plugin, the calling code considers exceptions like
|
cannot be opened. To simplify the plugin, the calling code considers exceptions
|
||||||
:py:exc:`SyntaxError`, :py:exc:`KeyError`, :py:exc:`IndexError`,
|
like :py:exc:`SyntaxError`, :py:exc:`KeyError`, :py:exc:`IndexError`,
|
||||||
:py:exc:`EOFError` and :py:exc:`struct.error` as a failure to identify
|
:py:exc:`EOFError` and :py:exc:`struct.error` as a failure to identify the
|
||||||
the file.
|
file.
|
||||||
|
|
||||||
Note that the image plugin must be explicitly registered using
|
Note that the image plugin must be explicitly registered using
|
||||||
:py:func:`PIL.Image.register_open`. Although not required, it is also a good
|
:py:func:`PIL.Image.register_open`. Although not required, it is also a good
|
||||||
|
@ -211,9 +211,9 @@ table describes some commonly used **raw modes**:
|
||||||
| ``1;R`` | | 1-bit reversed bilevel, stored with the leftmost pixel in the |
|
| ``1;R`` | | 1-bit reversed bilevel, stored with the leftmost pixel in the |
|
||||||
| | | least significant bit. 0 means black, 1 means white. |
|
| | | least significant bit. 0 means black, 1 means white. |
|
||||||
+-----------+-------------------------------------------------------------------+
|
+-----------+-------------------------------------------------------------------+
|
||||||
| ``L`` | 8-bit greyscale. 0 means black, 255 means white. |
|
| ``L`` | 8-bit grayscale. 0 means black, 255 means white. |
|
||||||
+-----------+-------------------------------------------------------------------+
|
+-----------+-------------------------------------------------------------------+
|
||||||
| ``L;I`` | 8-bit inverted greyscale. 0 means white, 255 means black. |
|
| ``L;I`` | 8-bit inverted grayscale. 0 means white, 255 means black. |
|
||||||
+-----------+-------------------------------------------------------------------+
|
+-----------+-------------------------------------------------------------------+
|
||||||
| ``P`` | 8-bit palette-mapped image. |
|
| ``P`` | 8-bit palette-mapped image. |
|
||||||
+-----------+-------------------------------------------------------------------+
|
+-----------+-------------------------------------------------------------------+
|
||||||
|
|
|
@ -182,7 +182,7 @@ Many of Pillow's features require external libraries:
|
||||||
|
|
||||||
* **libimagequant** provides improved color quantization
|
* **libimagequant** provides improved color quantization
|
||||||
|
|
||||||
* Pillow has been tested with libimagequant **2.6-4.2.1**
|
* Pillow has been tested with libimagequant **2.6-4.2.2**
|
||||||
* Libimagequant is licensed GPLv3, which is more restrictive than
|
* Libimagequant is licensed GPLv3, which is more restrictive than
|
||||||
the Pillow license, therefore we will not be distributing binaries
|
the Pillow license, therefore we will not be distributing binaries
|
||||||
with libimagequant support enabled.
|
with libimagequant support enabled.
|
||||||
|
@ -496,93 +496,93 @@ These platforms have been reported to work at the versions mentioned.
|
||||||
Contributors please test Pillow on your platform then update this
|
Contributors please test Pillow on your platform then update this
|
||||||
document and send a pull request.
|
document and send a pull request.
|
||||||
|
|
||||||
+----------------------------------+---------------------------+------------------+--------------+
|
+----------------------------------+----------------------------+------------------+--------------+
|
||||||
| Operating system | | Tested Python | | Latest tested | | Tested |
|
| Operating system | | Tested Python | | Latest tested | | Tested |
|
||||||
| | | versions | | Pillow version | | processors |
|
| | | versions | | Pillow version | | processors |
|
||||||
+==================================+===========================+==================+==============+
|
+==================================+============================+==================+==============+
|
||||||
| macOS 14 Sonoma | 3.8, 3.9, 3.10, 3.11 | 10.0.1 |arm |
|
| macOS 14 Sonoma | 3.8, 3.9, 3.10, 3.11, 3.12 | 10.1.0 |arm |
|
||||||
+----------------------------------+---------------------------+------------------+--------------+
|
+----------------------------------+----------------------------+------------------+--------------+
|
||||||
| macOS 13 Ventura | 3.8, 3.9, 3.10, 3.11 | 10.0.1 |arm |
|
| macOS 13 Ventura | 3.8, 3.9, 3.10, 3.11 | 10.0.1 |arm |
|
||||||
| +---------------------------+------------------+ |
|
| +----------------------------+------------------+ |
|
||||||
| | 3.7 | 9.5.0 | |
|
| | 3.7 | 9.5.0 | |
|
||||||
+----------------------------------+---------------------------+------------------+--------------+
|
+----------------------------------+----------------------------+------------------+--------------+
|
||||||
| macOS 12 Monterey | 3.7, 3.8, 3.9, 3.10, 3.11 | 9.3.0 |arm |
|
| macOS 12 Monterey | 3.7, 3.8, 3.9, 3.10, 3.11 | 9.3.0 |arm |
|
||||||
+----------------------------------+---------------------------+------------------+--------------+
|
+----------------------------------+----------------------------+------------------+--------------+
|
||||||
| macOS 11 Big Sur | 3.7, 3.8, 3.9, 3.10 | 8.4.0 |arm |
|
| macOS 11 Big Sur | 3.7, 3.8, 3.9, 3.10 | 8.4.0 |arm |
|
||||||
| +---------------------------+------------------+--------------+
|
| +----------------------------+------------------+--------------+
|
||||||
| | 3.7, 3.8, 3.9, 3.10, 3.11 | 9.4.0 |x86-64 |
|
| | 3.7, 3.8, 3.9, 3.10, 3.11 | 9.4.0 |x86-64 |
|
||||||
| +---------------------------+------------------+ |
|
| +----------------------------+------------------+ |
|
||||||
| | 3.6 | 8.4.0 | |
|
| | 3.6 | 8.4.0 | |
|
||||||
+----------------------------------+---------------------------+------------------+--------------+
|
+----------------------------------+----------------------------+------------------+--------------+
|
||||||
| macOS 10.15 Catalina | 3.6, 3.7, 3.8, 3.9 | 8.3.2 |x86-64 |
|
| macOS 10.15 Catalina | 3.6, 3.7, 3.8, 3.9 | 8.3.2 |x86-64 |
|
||||||
| +---------------------------+------------------+ |
|
| +----------------------------+------------------+ |
|
||||||
| | 3.5 | 7.2.0 | |
|
| | 3.5 | 7.2.0 | |
|
||||||
+----------------------------------+---------------------------+------------------+--------------+
|
+----------------------------------+----------------------------+------------------+--------------+
|
||||||
| macOS 10.14 Mojave | 3.5, 3.6, 3.7, 3.8 | 7.2.0 |x86-64 |
|
| macOS 10.14 Mojave | 3.5, 3.6, 3.7, 3.8 | 7.2.0 |x86-64 |
|
||||||
| +---------------------------+------------------+ |
|
| +----------------------------+------------------+ |
|
||||||
| | 2.7 | 6.0.0 | |
|
| | 2.7 | 6.0.0 | |
|
||||||
| +---------------------------+------------------+ |
|
| +----------------------------+------------------+ |
|
||||||
| | 3.4 | 5.4.1 | |
|
| | 3.4 | 5.4.1 | |
|
||||||
+----------------------------------+---------------------------+------------------+--------------+
|
+----------------------------------+----------------------------+------------------+--------------+
|
||||||
| macOS 10.13 High Sierra | 2.7, 3.4, 3.5, 3.6 | 4.2.1 |x86-64 |
|
| macOS 10.13 High Sierra | 2.7, 3.4, 3.5, 3.6 | 4.2.1 |x86-64 |
|
||||||
+----------------------------------+---------------------------+------------------+--------------+
|
+----------------------------------+----------------------------+------------------+--------------+
|
||||||
| macOS 10.12 Sierra | 2.7, 3.4, 3.5, 3.6 | 4.1.1 |x86-64 |
|
| macOS 10.12 Sierra | 2.7, 3.4, 3.5, 3.6 | 4.1.1 |x86-64 |
|
||||||
+----------------------------------+---------------------------+------------------+--------------+
|
+----------------------------------+----------------------------+------------------+--------------+
|
||||||
| Mac OS X 10.11 El Capitan | 2.7, 3.4, 3.5, 3.6, 3.7 | 5.4.1 |x86-64 |
|
| Mac OS X 10.11 El Capitan | 2.7, 3.4, 3.5, 3.6, 3.7 | 5.4.1 |x86-64 |
|
||||||
| +---------------------------+------------------+ |
|
| +----------------------------+------------------+ |
|
||||||
| | 3.3 | 4.1.0 | |
|
| | 3.3 | 4.1.0 | |
|
||||||
+----------------------------------+---------------------------+------------------+--------------+
|
+----------------------------------+----------------------------+------------------+--------------+
|
||||||
| Mac OS X 10.9 Mavericks | 2.7, 3.2, 3.3, 3.4 | 3.0.0 |x86-64 |
|
| Mac OS X 10.9 Mavericks | 2.7, 3.2, 3.3, 3.4 | 3.0.0 |x86-64 |
|
||||||
+----------------------------------+---------------------------+------------------+--------------+
|
+----------------------------------+----------------------------+------------------+--------------+
|
||||||
| Mac OS X 10.8 Mountain Lion | 2.6, 2.7, 3.2, 3.3 | |x86-64 |
|
| Mac OS X 10.8 Mountain Lion | 2.6, 2.7, 3.2, 3.3 | |x86-64 |
|
||||||
+----------------------------------+---------------------------+------------------+--------------+
|
+----------------------------------+----------------------------+------------------+--------------+
|
||||||
| Redhat Linux 6 | 2.6 | |x86 |
|
| Redhat Linux 6 | 2.6 | |x86 |
|
||||||
+----------------------------------+---------------------------+------------------+--------------+
|
+----------------------------------+----------------------------+------------------+--------------+
|
||||||
| CentOS 6.3 | 2.7, 3.3 | |x86 |
|
| CentOS 6.3 | 2.7, 3.3 | |x86 |
|
||||||
+----------------------------------+---------------------------+------------------+--------------+
|
+----------------------------------+----------------------------+------------------+--------------+
|
||||||
| CentOS 8 | 3.9 | 9.0.0 |x86-64 |
|
| CentOS 8 | 3.9 | 9.0.0 |x86-64 |
|
||||||
+----------------------------------+---------------------------+------------------+--------------+
|
+----------------------------------+----------------------------+------------------+--------------+
|
||||||
| Fedora 23 | 2.7, 3.4 | 3.1.0 |x86-64 |
|
| Fedora 23 | 2.7, 3.4 | 3.1.0 |x86-64 |
|
||||||
+----------------------------------+---------------------------+------------------+--------------+
|
+----------------------------------+----------------------------+------------------+--------------+
|
||||||
| Ubuntu Linux 12.04 LTS (Precise) | | 2.6, 3.2, 3.3, 3.4, 3.5 | 3.4.1 |x86,x86-64 |
|
| Ubuntu Linux 12.04 LTS (Precise) | | 2.6, 3.2, 3.3, 3.4, 3.5 | 3.4.1 |x86,x86-64 |
|
||||||
| | | PyPy5.3.1, PyPy3 v2.4.0 | | |
|
| | | PyPy5.3.1, PyPy3 v2.4.0 | | |
|
||||||
| +---------------------------+------------------+--------------+
|
| +----------------------------+------------------+--------------+
|
||||||
| | 2.7 | 4.3.0 |x86-64 |
|
| | 2.7 | 4.3.0 |x86-64 |
|
||||||
| +---------------------------+------------------+--------------+
|
| +----------------------------+------------------+--------------+
|
||||||
| | 2.7, 3.2 | 3.4.1 |ppc |
|
| | 2.7, 3.2 | 3.4.1 |ppc |
|
||||||
+----------------------------------+---------------------------+------------------+--------------+
|
+----------------------------------+----------------------------+------------------+--------------+
|
||||||
| Ubuntu Linux 10.04 LTS (Lucid) | 2.6 | 2.3.0 |x86,x86-64 |
|
| Ubuntu Linux 10.04 LTS (Lucid) | 2.6 | 2.3.0 |x86,x86-64 |
|
||||||
+----------------------------------+---------------------------+------------------+--------------+
|
+----------------------------------+----------------------------+------------------+--------------+
|
||||||
| Debian 8.2 Jessie | 2.7, 3.4 | 3.1.0 |x86-64 |
|
| Debian 8.2 Jessie | 2.7, 3.4 | 3.1.0 |x86-64 |
|
||||||
+----------------------------------+---------------------------+------------------+--------------+
|
+----------------------------------+----------------------------+------------------+--------------+
|
||||||
| Raspbian Jessie | 2.7, 3.4 | 3.1.0 |arm |
|
| Raspbian Jessie | 2.7, 3.4 | 3.1.0 |arm |
|
||||||
+----------------------------------+---------------------------+------------------+--------------+
|
+----------------------------------+----------------------------+------------------+--------------+
|
||||||
| Raspbian Stretch | 2.7, 3.5 | 4.0.0 |arm |
|
| Raspbian Stretch | 2.7, 3.5 | 4.0.0 |arm |
|
||||||
+----------------------------------+---------------------------+------------------+--------------+
|
+----------------------------------+----------------------------+------------------+--------------+
|
||||||
| Raspberry Pi OS | 3.6, 3.7, 3.8, 3.9 | 8.2.0 |arm |
|
| Raspberry Pi OS | 3.6, 3.7, 3.8, 3.9 | 8.2.0 |arm |
|
||||||
| +---------------------------+------------------+ |
|
| +----------------------------+------------------+ |
|
||||||
| | 2.7 | 6.2.2 | |
|
| | 2.7 | 6.2.2 | |
|
||||||
+----------------------------------+---------------------------+------------------+--------------+
|
+----------------------------------+----------------------------+------------------+--------------+
|
||||||
| Gentoo Linux | 2.7, 3.2 | 2.1.0 |x86-64 |
|
| Gentoo Linux | 2.7, 3.2 | 2.1.0 |x86-64 |
|
||||||
+----------------------------------+---------------------------+------------------+--------------+
|
+----------------------------------+----------------------------+------------------+--------------+
|
||||||
| FreeBSD 11.1 | 2.7, 3.4, 3.5, 3.6 | 4.3.0 |x86-64 |
|
| FreeBSD 11.1 | 2.7, 3.4, 3.5, 3.6 | 4.3.0 |x86-64 |
|
||||||
+----------------------------------+---------------------------+------------------+--------------+
|
+----------------------------------+----------------------------+------------------+--------------+
|
||||||
| FreeBSD 10.3 | 2.7, 3.4, 3.5 | 4.2.0 |x86-64 |
|
| FreeBSD 10.3 | 2.7, 3.4, 3.5 | 4.2.0 |x86-64 |
|
||||||
+----------------------------------+---------------------------+------------------+--------------+
|
+----------------------------------+----------------------------+------------------+--------------+
|
||||||
| FreeBSD 10.2 | 2.7, 3.4 | 3.1.0 |x86-64 |
|
| FreeBSD 10.2 | 2.7, 3.4 | 3.1.0 |x86-64 |
|
||||||
+----------------------------------+---------------------------+------------------+--------------+
|
+----------------------------------+----------------------------+------------------+--------------+
|
||||||
| Windows 10 | 3.7 | 7.1.0 |x86-64 |
|
| Windows 10 | 3.7 | 7.1.0 |x86-64 |
|
||||||
+----------------------------------+---------------------------+------------------+--------------+
|
+----------------------------------+----------------------------+------------------+--------------+
|
||||||
| Windows 10/Cygwin 3.3 | 3.6, 3.7, 3.8, 3.9 | 8.4.0 |x86-64 |
|
| Windows 10/Cygwin 3.3 | 3.6, 3.7, 3.8, 3.9 | 8.4.0 |x86-64 |
|
||||||
+----------------------------------+---------------------------+------------------+--------------+
|
+----------------------------------+----------------------------+------------------+--------------+
|
||||||
| Windows 8.1 Pro | 2.6, 2.7, 3.2, 3.3, 3.4 | 2.4.0 |x86,x86-64 |
|
| Windows 8.1 Pro | 2.6, 2.7, 3.2, 3.3, 3.4 | 2.4.0 |x86,x86-64 |
|
||||||
+----------------------------------+---------------------------+------------------+--------------+
|
+----------------------------------+----------------------------+------------------+--------------+
|
||||||
| Windows 8 Pro | 2.6, 2.7, 3.2, 3.3, 3.4a3 | 2.2.0 |x86,x86-64 |
|
| Windows 8 Pro | 2.6, 2.7, 3.2, 3.3, 3.4a3 | 2.2.0 |x86,x86-64 |
|
||||||
+----------------------------------+---------------------------+------------------+--------------+
|
+----------------------------------+----------------------------+------------------+--------------+
|
||||||
| Windows 7 Professional | 3.7 | 7.0.0 |x86,x86-64 |
|
| Windows 7 Professional | 3.7 | 7.0.0 |x86,x86-64 |
|
||||||
+----------------------------------+---------------------------+------------------+--------------+
|
+----------------------------------+----------------------------+------------------+--------------+
|
||||||
| Windows Server 2008 R2 Enterprise| 3.3 | |x86-64 |
|
| Windows Server 2008 R2 Enterprise| 3.3 | |x86-64 |
|
||||||
+----------------------------------+---------------------------+------------------+--------------+
|
+----------------------------------+----------------------------+------------------+--------------+
|
||||||
|
|
||||||
Old Versions
|
Old Versions
|
||||||
------------
|
------------
|
||||||
|
|
|
@ -59,7 +59,7 @@ Functions
|
||||||
.. py:method:: getcolor(color, mode)
|
.. py:method:: getcolor(color, mode)
|
||||||
|
|
||||||
Same as :py:func:`~PIL.ImageColor.getrgb`, but converts the RGB value to a
|
Same as :py:func:`~PIL.ImageColor.getrgb`, but converts the RGB value to a
|
||||||
greyscale value if the mode is not color or a palette image. If the string
|
grayscale value if the mode is not color or a palette image. If the string
|
||||||
cannot be parsed, this function raises a :py:exc:`ValueError` exception.
|
cannot be parsed, this function raises a :py:exc:`ValueError` exception.
|
||||||
|
|
||||||
.. versionadded:: 1.1.4
|
.. versionadded:: 1.1.4
|
||||||
|
|
|
@ -351,7 +351,7 @@ Methods
|
||||||
|
|
||||||
Draw a shape.
|
Draw a shape.
|
||||||
|
|
||||||
.. py:method:: ImageDraw.text(xy, text, fill=None, font=None, anchor=None, spacing=4, align="left", direction=None, features=None, language=None, stroke_width=0, stroke_fill=None, embedded_color=False)
|
.. py:method:: ImageDraw.text(xy, text, fill=None, font=None, anchor=None, spacing=4, align="left", direction=None, features=None, language=None, stroke_width=0, stroke_fill=None, embedded_color=False, font_size=None)
|
||||||
|
|
||||||
Draws the string at the given position.
|
Draws the string at the given position.
|
||||||
|
|
||||||
|
@ -416,8 +416,14 @@ Methods
|
||||||
|
|
||||||
.. versionadded:: 8.0.0
|
.. versionadded:: 8.0.0
|
||||||
|
|
||||||
|
:param font_size: If ``font`` is not provided, then the size to use for the default
|
||||||
|
font.
|
||||||
|
Keyword-only argument.
|
||||||
|
|
||||||
.. py:method:: ImageDraw.multiline_text(xy, text, fill=None, font=None, anchor=None, spacing=4, align="left", direction=None, features=None, language=None, stroke_width=0, stroke_fill=None, embedded_color=False)
|
.. versionadded:: 10.1.0
|
||||||
|
|
||||||
|
|
||||||
|
.. py:method:: ImageDraw.multiline_text(xy, text, fill=None, font=None, anchor=None, spacing=4, align="left", direction=None, features=None, language=None, stroke_width=0, stroke_fill=None, embedded_color=False, font_size=None)
|
||||||
|
|
||||||
Draws the string at the given position.
|
Draws the string at the given position.
|
||||||
|
|
||||||
|
@ -477,7 +483,13 @@ Methods
|
||||||
|
|
||||||
.. versionadded:: 8.0.0
|
.. versionadded:: 8.0.0
|
||||||
|
|
||||||
.. py:method:: ImageDraw.textlength(text, font=None, direction=None, features=None, language=None, embedded_color=False)
|
:param font_size: If ``font`` is not provided, then the size to use for the default
|
||||||
|
font.
|
||||||
|
Keyword-only argument.
|
||||||
|
|
||||||
|
.. versionadded:: 10.1.0
|
||||||
|
|
||||||
|
.. py:method:: ImageDraw.textlength(text, font=None, direction=None, features=None, language=None, embedded_color=False, font_size=None)
|
||||||
|
|
||||||
Returns length (in pixels with 1/64 precision) of given text when rendered
|
Returns length (in pixels with 1/64 precision) of given text when rendered
|
||||||
in font with provided direction, features, and language.
|
in font with provided direction, features, and language.
|
||||||
|
@ -538,9 +550,15 @@ Methods
|
||||||
It should be a `BCP 47 language code`_.
|
It should be a `BCP 47 language code`_.
|
||||||
Requires libraqm.
|
Requires libraqm.
|
||||||
:param embedded_color: Whether to use font embedded color glyphs (COLR, CBDT, SBIX).
|
:param embedded_color: Whether to use font embedded color glyphs (COLR, CBDT, SBIX).
|
||||||
|
:param font_size: If ``font`` is not provided, then the size to use for the default
|
||||||
|
font.
|
||||||
|
Keyword-only argument.
|
||||||
|
|
||||||
|
.. versionadded:: 10.1.0
|
||||||
|
|
||||||
:return: Either width for horizontal text, or height for vertical text.
|
:return: Either width for horizontal text, or height for vertical text.
|
||||||
|
|
||||||
.. py:method:: ImageDraw.textbbox(xy, text, font=None, anchor=None, spacing=4, align="left", direction=None, features=None, language=None, stroke_width=0, embedded_color=False)
|
.. py:method:: ImageDraw.textbbox(xy, text, font=None, anchor=None, spacing=4, align="left", direction=None, features=None, language=None, stroke_width=0, embedded_color=False, font_size=None)
|
||||||
|
|
||||||
Returns bounding box (in pixels) of given text relative to given anchor
|
Returns bounding box (in pixels) of given text relative to given anchor
|
||||||
when rendered in font with provided direction, features, and language.
|
when rendered in font with provided direction, features, and language.
|
||||||
|
@ -588,9 +606,15 @@ Methods
|
||||||
Requires libraqm.
|
Requires libraqm.
|
||||||
:param stroke_width: The width of the text stroke.
|
:param stroke_width: The width of the text stroke.
|
||||||
:param embedded_color: Whether to use font embedded color glyphs (COLR, CBDT, SBIX).
|
:param embedded_color: Whether to use font embedded color glyphs (COLR, CBDT, SBIX).
|
||||||
|
:param font_size: If ``font`` is not provided, then the size to use for the default
|
||||||
|
font.
|
||||||
|
Keyword-only argument.
|
||||||
|
|
||||||
|
.. versionadded:: 10.1.0
|
||||||
|
|
||||||
:return: ``(left, top, right, bottom)`` bounding box
|
:return: ``(left, top, right, bottom)`` bounding box
|
||||||
|
|
||||||
.. py:method:: ImageDraw.multiline_textbbox(xy, text, font=None, anchor=None, spacing=4, align="left", direction=None, features=None, language=None, stroke_width=0, embedded_color=False)
|
.. py:method:: ImageDraw.multiline_textbbox(xy, text, font=None, anchor=None, spacing=4, align="left", direction=None, features=None, language=None, stroke_width=0, embedded_color=False, font_size=None)
|
||||||
|
|
||||||
Returns bounding box (in pixels) of given text relative to given anchor
|
Returns bounding box (in pixels) of given text relative to given anchor
|
||||||
when rendered in font with provided direction, features, and language.
|
when rendered in font with provided direction, features, and language.
|
||||||
|
@ -632,6 +656,12 @@ Methods
|
||||||
Requires libraqm.
|
Requires libraqm.
|
||||||
:param stroke_width: The width of the text stroke.
|
:param stroke_width: The width of the text stroke.
|
||||||
:param embedded_color: Whether to use font embedded color glyphs (COLR, CBDT, SBIX).
|
:param embedded_color: Whether to use font embedded color glyphs (COLR, CBDT, SBIX).
|
||||||
|
:param font_size: If ``font`` is not provided, then the size to use for the default
|
||||||
|
font.
|
||||||
|
Keyword-only argument.
|
||||||
|
|
||||||
|
.. versionadded:: 10.1.0
|
||||||
|
|
||||||
:return: ``(left, top, right, bottom)`` bounding box
|
:return: ``(left, top, right, bottom)`` bounding box
|
||||||
|
|
||||||
.. py:method:: getdraw(im=None, hints=None)
|
.. py:method:: getdraw(im=None, hints=None)
|
||||||
|
|
|
@ -58,7 +58,7 @@ method:
|
||||||
|
|
||||||
This class can be used to control the contrast of an image, similar to the
|
This class can be used to control the contrast of an image, similar to the
|
||||||
contrast control on a TV set. An
|
contrast control on a TV set. An
|
||||||
:ref:`enhancement factor <enhancement-factor>` of 0.0 gives a solid grey
|
:ref:`enhancement factor <enhancement-factor>` of 0.0 gives a solid gray
|
||||||
image, a factor of 1.0 gives the original image, and greater values
|
image, a factor of 1.0 gives the original image, and greater values
|
||||||
increase the contrast of the image.
|
increase the contrast of the image.
|
||||||
|
|
||||||
|
|
|
@ -72,7 +72,7 @@ pixel bits.
|
||||||
|
|
||||||
Note that the operands are converted to 32-bit signed integers before the
|
Note that the operands are converted to 32-bit signed integers before the
|
||||||
bitwise operation is applied. This means that you’ll get negative values if
|
bitwise operation is applied. This means that you’ll get negative values if
|
||||||
you invert an ordinary greyscale image. You can use the and (&) operator to
|
you invert an ordinary grayscale image. You can use the and (&) operator to
|
||||||
mask off unwanted bits.
|
mask off unwanted bits.
|
||||||
|
|
||||||
Bitwise operators don’t work on floating point images.
|
Bitwise operators don’t work on floating point images.
|
||||||
|
|
|
@ -12,14 +12,11 @@ only work on L and RGB images.
|
||||||
|
|
||||||
.. autofunction:: autocontrast
|
.. autofunction:: autocontrast
|
||||||
.. autofunction:: colorize
|
.. autofunction:: colorize
|
||||||
.. autofunction:: contain
|
|
||||||
.. autofunction:: pad
|
|
||||||
.. autofunction:: crop
|
.. autofunction:: crop
|
||||||
.. autofunction:: scale
|
.. autofunction:: scale
|
||||||
.. autofunction:: deform
|
.. autofunction:: deform
|
||||||
.. autofunction:: equalize
|
.. autofunction:: equalize
|
||||||
.. autofunction:: expand
|
.. autofunction:: expand
|
||||||
.. autofunction:: fit
|
|
||||||
.. autofunction:: flip
|
.. autofunction:: flip
|
||||||
.. autofunction:: grayscale
|
.. autofunction:: grayscale
|
||||||
.. autofunction:: invert
|
.. autofunction:: invert
|
||||||
|
@ -27,3 +24,38 @@ only work on L and RGB images.
|
||||||
.. autofunction:: posterize
|
.. autofunction:: posterize
|
||||||
.. autofunction:: solarize
|
.. autofunction:: solarize
|
||||||
.. autofunction:: exif_transpose
|
.. autofunction:: exif_transpose
|
||||||
|
|
||||||
|
.. _relative-resize:
|
||||||
|
|
||||||
|
Resize relative to a given size
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
from PIL import Image, ImageOps
|
||||||
|
size = (100, 150)
|
||||||
|
with Image.open("Tests/images/hopper.png") as im:
|
||||||
|
ImageOps.contain(im, size).save("imageops_contain.png")
|
||||||
|
ImageOps.cover(im, size).save("imageops_cover.png")
|
||||||
|
ImageOps.fit(im, size).save("imageops_fit.png")
|
||||||
|
ImageOps.pad(im, size, color="#f00").save("imageops_pad.png")
|
||||||
|
|
||||||
|
# thumbnail() can also be used,
|
||||||
|
# but will modify the image object in place
|
||||||
|
im.thumbnail(size)
|
||||||
|
im.save("imageops_thumbnail.png")
|
||||||
|
|
||||||
|
+----------------+-------------------------------------------+--------------------------------------------+------------------------------------------+----------------------------------------+----------------------------------------+
|
||||||
|
| | :py:meth:`~PIL.Image.Image.thumbnail` | :py:meth:`~PIL.ImageOps.contain` | :py:meth:`~PIL.ImageOps.cover` | :py:meth:`~PIL.ImageOps.fit` | :py:meth:`~PIL.ImageOps.pad` |
|
||||||
|
+================+===========================================+============================================+==========================================+========================================+========================================+
|
||||||
|
|Given size | ``(100, 150)`` | ``(100, 150)`` | ``(100, 150)`` | ``(100, 150)`` | ``(100, 150)`` |
|
||||||
|
+----------------+-------------------------------------------+--------------------------------------------+------------------------------------------+----------------------------------------+----------------------------------------+
|
||||||
|
|Resulting image | .. image:: ../example/image_thumbnail.png | .. image:: ../example/imageops_contain.png | .. image:: ../example/imageops_cover.png | .. image:: ../example/imageops_fit.png | .. image:: ../example/imageops_pad.png |
|
||||||
|
+----------------+-------------------------------------------+--------------------------------------------+------------------------------------------+----------------------------------------+----------------------------------------+
|
||||||
|
|Resulting size | ``100×100`` | ``100×100`` | ``150×150`` | ``100×150`` | ``100×150`` |
|
||||||
|
+----------------+-------------------------------------------+--------------------------------------------+------------------------------------------+----------------------------------------+----------------------------------------+
|
||||||
|
|
||||||
|
.. autofunction:: contain
|
||||||
|
.. autofunction:: cover
|
||||||
|
.. autofunction:: fit
|
||||||
|
.. autofunction:: pad
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
10.1.0
|
10.1.0
|
||||||
------
|
------
|
||||||
|
|
||||||
Backwards Incompatible Changes
|
API Changes
|
||||||
==============================
|
===========
|
||||||
|
|
||||||
Setting image mode
|
Setting image mode
|
||||||
^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -13,9 +13,6 @@ not about removing existing functionality, but instead about raising an
|
||||||
explicit error to prevent later consequences. The ``convert`` method is the
|
explicit error to prevent later consequences. The ``convert`` method is the
|
||||||
correct way to change an image's mode.
|
correct way to change an image's mode.
|
||||||
|
|
||||||
API Changes
|
|
||||||
===========
|
|
||||||
|
|
||||||
Accept a list in getpixel()
|
Accept a list in getpixel()
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
@ -60,9 +57,45 @@ channel, a palette with an alpha channel, or a "transparency" key in the
|
||||||
Even if this attribute is true, the image might still appear solid, if all of
|
Even if this attribute is true, the image might still appear solid, if all of
|
||||||
the values shown within are opaque.
|
the values shown within are opaque.
|
||||||
|
|
||||||
|
ImageOps.cover
|
||||||
|
^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Returns a resized version of the image, so that the requested size is covered,
|
||||||
|
while maintaining the original aspect ratio.
|
||||||
|
|
||||||
|
See :ref:`relative-resize` for a comparison between this and similar ``ImageOps``
|
||||||
|
methods.
|
||||||
|
|
||||||
|
size and font_size arguments when using default font
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Pillow has had a "better than nothing" default font, which can only be drawn at
|
||||||
|
one font size. Now, if FreeType support is available, a version of
|
||||||
|
`Aileron Regular <https://dotcolon.net/font/aileron>`_ is loaded, which can be
|
||||||
|
drawn at chosen font sizes.
|
||||||
|
|
||||||
|
The following ``size`` and ``font_size`` arguments can now be used to specify a
|
||||||
|
font size for this new builtin font::
|
||||||
|
|
||||||
|
ImageFont.load_default(size=24)
|
||||||
|
draw.text((0, 0), "test", font_size=24)
|
||||||
|
draw.textlength((0, 0), "test", font_size=24)
|
||||||
|
draw.textbbox((0, 0), "test", font_size=24)
|
||||||
|
draw.multiline_text((0, 0), "test", font_size=24)
|
||||||
|
draw.multiline_textbbox((0, 0), "test", font_size=24)
|
||||||
|
|
||||||
Other Changes
|
Other Changes
|
||||||
=============
|
=============
|
||||||
|
|
||||||
|
Python 3.12
|
||||||
|
^^^^^^^^^^^
|
||||||
|
|
||||||
|
Pillow 10.0.0 had wheels built against Python 3.12 beta, available as a preview to help
|
||||||
|
others prepare for 3.12, and to ensure Pillow could be used immediately at the release
|
||||||
|
of 3.12.0 final (2023-10-02, :pep:`693`).
|
||||||
|
|
||||||
|
Pillow 10.1.0 now officially supports Python 3.12.
|
||||||
|
|
||||||
Added support for DDS BC5U and 8-bit color indexed images
|
Added support for DDS BC5U and 8-bit color indexed images
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
|
|
@ -29,10 +29,10 @@ API Additions
|
||||||
Image.entropy
|
Image.entropy
|
||||||
^^^^^^^^^^^^^
|
^^^^^^^^^^^^^
|
||||||
Calculates and returns the entropy for the image. A bilevel image (mode "1") is treated
|
Calculates and returns the entropy for the image. A bilevel image (mode "1") is treated
|
||||||
as a greyscale ("L") image by this method. If a mask is provided, the method employs
|
as a grayscale ("L") image by this method. If a mask is provided, the method employs
|
||||||
the histogram for those parts of the image where the mask image is non-zero. The mask
|
the histogram for those parts of the image where the mask image is non-zero. The mask
|
||||||
image must have the same size as the image, and be either a bi-level image (mode "1") or
|
image must have the same size as the image, and be either a bi-level image (mode "1") or
|
||||||
a greyscale image ("L").
|
a grayscale image ("L").
|
||||||
|
|
||||||
ImageGrab.grab
|
ImageGrab.grab
|
||||||
^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^
|
||||||
|
|
|
@ -230,21 +230,21 @@ class BmpImageFile(ImageFile.ImageFile):
|
||||||
else:
|
else:
|
||||||
padding = file_info["palette_padding"]
|
padding = file_info["palette_padding"]
|
||||||
palette = read(padding * file_info["colors"])
|
palette = read(padding * file_info["colors"])
|
||||||
greyscale = True
|
grayscale = True
|
||||||
indices = (
|
indices = (
|
||||||
(0, 255)
|
(0, 255)
|
||||||
if file_info["colors"] == 2
|
if file_info["colors"] == 2
|
||||||
else list(range(file_info["colors"]))
|
else list(range(file_info["colors"]))
|
||||||
)
|
)
|
||||||
|
|
||||||
# ----------------- Check if greyscale and ignore palette if so
|
# ----------------- Check if grayscale and ignore palette if so
|
||||||
for ind, val in enumerate(indices):
|
for ind, val in enumerate(indices):
|
||||||
rgb = palette[ind * padding : ind * padding + 3]
|
rgb = palette[ind * padding : ind * padding + 3]
|
||||||
if rgb != o8(val) * 3:
|
if rgb != o8(val) * 3:
|
||||||
greyscale = False
|
grayscale = False
|
||||||
|
|
||||||
# ------- If all colors are grey, white or black, ditch palette
|
# ------- If all colors are gray, white or black, ditch palette
|
||||||
if greyscale:
|
if grayscale:
|
||||||
self._mode = "1" if file_info["colors"] == 2 else "L"
|
self._mode = "1" if file_info["colors"] == 2 else "L"
|
||||||
raw_mode = self.mode
|
raw_mode = self.mode
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -150,7 +150,8 @@ class FliImageFile(ImageFile.ImageFile):
|
||||||
|
|
||||||
s = self.fp.read(4)
|
s = self.fp.read(4)
|
||||||
if not s:
|
if not s:
|
||||||
raise EOFError
|
msg = "missing frame size"
|
||||||
|
raise EOFError(msg)
|
||||||
|
|
||||||
framesize = i32(s)
|
framesize = i32(s)
|
||||||
|
|
||||||
|
|
|
@ -183,7 +183,8 @@ class GifImageFile(ImageFile.ImageFile):
|
||||||
|
|
||||||
s = self.fp.read(1)
|
s = self.fp.read(1)
|
||||||
if not s or s == b";":
|
if not s or s == b";":
|
||||||
raise EOFError
|
msg = "no more images in GIF file"
|
||||||
|
raise EOFError(msg)
|
||||||
|
|
||||||
palette = None
|
palette = None
|
||||||
|
|
||||||
|
@ -288,7 +289,8 @@ class GifImageFile(ImageFile.ImageFile):
|
||||||
|
|
||||||
if interlace is None:
|
if interlace is None:
|
||||||
# self._fp = None
|
# self._fp = None
|
||||||
raise EOFError
|
msg = "image not found in GIF frame"
|
||||||
|
raise EOFError(msg)
|
||||||
|
|
||||||
self.__frame = frame
|
self.__frame = frame
|
||||||
if not update_image:
|
if not update_image:
|
||||||
|
|
|
@ -888,12 +888,12 @@ class Image:
|
||||||
"L", "RGB" and "CMYK". The ``matrix`` argument only supports "L"
|
"L", "RGB" and "CMYK". The ``matrix`` argument only supports "L"
|
||||||
and "RGB".
|
and "RGB".
|
||||||
|
|
||||||
When translating a color image to greyscale (mode "L"),
|
When translating a color image to grayscale (mode "L"),
|
||||||
the library uses the ITU-R 601-2 luma transform::
|
the library uses the ITU-R 601-2 luma transform::
|
||||||
|
|
||||||
L = R * 299/1000 + G * 587/1000 + B * 114/1000
|
L = R * 299/1000 + G * 587/1000 + B * 114/1000
|
||||||
|
|
||||||
The default method of converting a greyscale ("L") or "RGB"
|
The default method of converting a grayscale ("L") or "RGB"
|
||||||
image into a bilevel (mode "1") image uses Floyd-Steinberg
|
image into a bilevel (mode "1") image uses Floyd-Steinberg
|
||||||
dither to approximate the original image luminosity levels. If
|
dither to approximate the original image luminosity levels. If
|
||||||
dither is ``None``, all values larger than 127 are set to 255 (white),
|
dither is ``None``, all values larger than 127 are set to 255 (white),
|
||||||
|
@ -943,9 +943,9 @@ class Image:
|
||||||
msg = "illegal conversion"
|
msg = "illegal conversion"
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
im = self.im.convert_matrix(mode, matrix)
|
im = self.im.convert_matrix(mode, matrix)
|
||||||
new = self._new(im)
|
new_im = self._new(im)
|
||||||
if has_transparency and self.im.bands == 3:
|
if has_transparency and self.im.bands == 3:
|
||||||
transparency = new.info["transparency"]
|
transparency = new_im.info["transparency"]
|
||||||
|
|
||||||
def convert_transparency(m, v):
|
def convert_transparency(m, v):
|
||||||
v = m[0] * v[0] + m[1] * v[1] + m[2] * v[2] + m[3] * 0.5
|
v = m[0] * v[0] + m[1] * v[1] + m[2] * v[2] + m[3] * 0.5
|
||||||
|
@ -958,8 +958,8 @@ class Image:
|
||||||
convert_transparency(matrix[i * 4 : i * 4 + 4], transparency)
|
convert_transparency(matrix[i * 4 : i * 4 + 4], transparency)
|
||||||
for i in range(0, len(transparency))
|
for i in range(0, len(transparency))
|
||||||
)
|
)
|
||||||
new.info["transparency"] = transparency
|
new_im.info["transparency"] = transparency
|
||||||
return new
|
return new_im
|
||||||
|
|
||||||
if mode == "P" and self.mode == "RGBA":
|
if mode == "P" and self.mode == "RGBA":
|
||||||
return self.quantize(colors)
|
return self.quantize(colors)
|
||||||
|
@ -990,7 +990,7 @@ class Image:
|
||||||
else:
|
else:
|
||||||
# get the new transparency color.
|
# get the new transparency color.
|
||||||
# use existing conversions
|
# use existing conversions
|
||||||
trns_im = Image()._new(core.new(self.mode, (1, 1)))
|
trns_im = new(self.mode, (1, 1))
|
||||||
if self.mode == "P":
|
if self.mode == "P":
|
||||||
trns_im.putpalette(self.palette)
|
trns_im.putpalette(self.palette)
|
||||||
if isinstance(t, tuple):
|
if isinstance(t, tuple):
|
||||||
|
@ -1031,23 +1031,25 @@ class Image:
|
||||||
|
|
||||||
if mode == "P" and palette == Palette.ADAPTIVE:
|
if mode == "P" and palette == Palette.ADAPTIVE:
|
||||||
im = self.im.quantize(colors)
|
im = self.im.quantize(colors)
|
||||||
new = self._new(im)
|
new_im = self._new(im)
|
||||||
from . import ImagePalette
|
from . import ImagePalette
|
||||||
|
|
||||||
new.palette = ImagePalette.ImagePalette("RGB", new.im.getpalette("RGB"))
|
new_im.palette = ImagePalette.ImagePalette(
|
||||||
|
"RGB", new_im.im.getpalette("RGB")
|
||||||
|
)
|
||||||
if delete_trns:
|
if delete_trns:
|
||||||
# This could possibly happen if we requantize to fewer colors.
|
# This could possibly happen if we requantize to fewer colors.
|
||||||
# The transparency would be totally off in that case.
|
# The transparency would be totally off in that case.
|
||||||
del new.info["transparency"]
|
del new_im.info["transparency"]
|
||||||
if trns is not None:
|
if trns is not None:
|
||||||
try:
|
try:
|
||||||
new.info["transparency"] = new.palette.getcolor(trns, new)
|
new_im.info["transparency"] = new_im.palette.getcolor(trns, new_im)
|
||||||
except Exception:
|
except Exception:
|
||||||
# if we can't make a transparent color, don't leave the old
|
# if we can't make a transparent color, don't leave the old
|
||||||
# transparency hanging around to mess us up.
|
# transparency hanging around to mess us up.
|
||||||
del new.info["transparency"]
|
del new_im.info["transparency"]
|
||||||
warnings.warn("Couldn't allocate palette entry for transparency")
|
warnings.warn("Couldn't allocate palette entry for transparency")
|
||||||
return new
|
return new_im
|
||||||
|
|
||||||
if "LAB" in (self.mode, mode):
|
if "LAB" in (self.mode, mode):
|
||||||
other_mode = mode if self.mode == "LAB" else self.mode
|
other_mode = mode if self.mode == "LAB" else self.mode
|
||||||
|
@ -1246,7 +1248,7 @@ class Image:
|
||||||
Configures the image file loader so it returns a version of the
|
Configures the image file loader so it returns a version of the
|
||||||
image that as closely as possible matches the given mode and
|
image that as closely as possible matches the given mode and
|
||||||
size. For example, you can use this method to convert a color
|
size. For example, you can use this method to convert a color
|
||||||
JPEG to greyscale while loading it.
|
JPEG to grayscale while loading it.
|
||||||
|
|
||||||
If any changes are made, returns a tuple with the chosen ``mode`` and
|
If any changes are made, returns a tuple with the chosen ``mode`` and
|
||||||
``box`` with coordinates of the original image within the altered one.
|
``box`` with coordinates of the original image within the altered one.
|
||||||
|
@ -1618,13 +1620,13 @@ class Image:
|
||||||
than one band, the histograms for all bands are concatenated (for
|
than one band, the histograms for all bands are concatenated (for
|
||||||
example, the histogram for an "RGB" image contains 768 values).
|
example, the histogram for an "RGB" image contains 768 values).
|
||||||
|
|
||||||
A bilevel image (mode "1") is treated as a greyscale ("L") image
|
A bilevel image (mode "1") is treated as a grayscale ("L") image
|
||||||
by this method.
|
by this method.
|
||||||
|
|
||||||
If a mask is provided, the method returns a histogram for those
|
If a mask is provided, the method returns a histogram for those
|
||||||
parts of the image where the mask image is non-zero. The mask
|
parts of the image where the mask image is non-zero. The mask
|
||||||
image must have the same size as the image, and be either a
|
image must have the same size as the image, and be either a
|
||||||
bi-level image (mode "1") or a greyscale image ("L").
|
bi-level image (mode "1") or a grayscale image ("L").
|
||||||
|
|
||||||
:param mask: An optional mask.
|
:param mask: An optional mask.
|
||||||
:param extrema: An optional tuple of manually-specified extrema.
|
:param extrema: An optional tuple of manually-specified extrema.
|
||||||
|
@ -1644,13 +1646,13 @@ class Image:
|
||||||
"""
|
"""
|
||||||
Calculates and returns the entropy for the image.
|
Calculates and returns the entropy for the image.
|
||||||
|
|
||||||
A bilevel image (mode "1") is treated as a greyscale ("L")
|
A bilevel image (mode "1") is treated as a grayscale ("L")
|
||||||
image by this method.
|
image by this method.
|
||||||
|
|
||||||
If a mask is provided, the method employs the histogram for
|
If a mask is provided, the method employs the histogram for
|
||||||
those parts of the image where the mask image is non-zero.
|
those parts of the image where the mask image is non-zero.
|
||||||
The mask image must have the same size as the image, and be
|
The mask image must have the same size as the image, and be
|
||||||
either a bi-level image (mode "1") or a greyscale image ("L").
|
either a bi-level image (mode "1") or a grayscale image ("L").
|
||||||
|
|
||||||
:param mask: An optional mask.
|
:param mask: An optional mask.
|
||||||
:param extrema: An optional tuple of manually-specified extrema.
|
:param extrema: An optional tuple of manually-specified extrema.
|
||||||
|
@ -1870,7 +1872,8 @@ class Image:
|
||||||
# do things the hard way
|
# do things the hard way
|
||||||
im = self.im.convert(mode)
|
im = self.im.convert(mode)
|
||||||
if im.mode not in ("LA", "PA", "RGBA"):
|
if im.mode not in ("LA", "PA", "RGBA"):
|
||||||
raise ValueError from e # sanity check
|
msg = "alpha channel could not be added"
|
||||||
|
raise ValueError(msg) from e # sanity check
|
||||||
self.im = im
|
self.im = im
|
||||||
self.pyaccess = None
|
self.pyaccess = None
|
||||||
self._mode = self.im.mode
|
self._mode = self.im.mode
|
||||||
|
@ -2475,7 +2478,8 @@ class Image:
|
||||||
|
|
||||||
# overridden by file handlers
|
# overridden by file handlers
|
||||||
if frame != 0:
|
if frame != 0:
|
||||||
raise EOFError
|
msg = "no more images in file"
|
||||||
|
raise EOFError(msg)
|
||||||
|
|
||||||
def show(self, title=None):
|
def show(self, title=None):
|
||||||
"""
|
"""
|
||||||
|
@ -2882,7 +2886,7 @@ class ImageTransformHandler:
|
||||||
|
|
||||||
|
|
||||||
def _wedge():
|
def _wedge():
|
||||||
"""Create greyscale wedge (for debugging only)"""
|
"""Create grayscale wedge (for debugging only)"""
|
||||||
|
|
||||||
return Image()._new(core.wedge("L"))
|
return Image()._new(core.wedge("L"))
|
||||||
|
|
||||||
|
@ -3759,6 +3763,7 @@ class Exif(MutableMapping):
|
||||||
self.endian = self._info._endian
|
self.endian = self._info._endian
|
||||||
if offset is None:
|
if offset is None:
|
||||||
offset = self._info.next
|
offset = self._info.next
|
||||||
|
self.fp.tell()
|
||||||
self.fp.seek(offset)
|
self.fp.seek(offset)
|
||||||
self._info.load(self.fp)
|
self._info.load(self.fp)
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ from . import Image
|
||||||
|
|
||||||
|
|
||||||
def constant(image, value):
|
def constant(image, value):
|
||||||
"""Fill a channel with a given grey level.
|
"""Fill a channel with a given gray level.
|
||||||
|
|
||||||
:rtype: :py:class:`~PIL.Image.Image`
|
:rtype: :py:class:`~PIL.Image.Image`
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -124,7 +124,7 @@ def getcolor(color, mode):
|
||||||
"""
|
"""
|
||||||
Same as :py:func:`~PIL.ImageColor.getrgb` for most modes. However, if
|
Same as :py:func:`~PIL.ImageColor.getrgb` for most modes. However, if
|
||||||
``mode`` is HSV, converts the RGB value to a HSV value, or if ``mode`` is
|
``mode`` is HSV, converts the RGB value to a HSV value, or if ``mode`` is
|
||||||
not color or a palette image, converts the RGB value to a greyscale value.
|
not color or a palette image, converts the RGB value to a grayscale value.
|
||||||
If the string cannot be parsed, this function raises a :py:exc:`ValueError`
|
If the string cannot be parsed, this function raises a :py:exc:`ValueError`
|
||||||
exception.
|
exception.
|
||||||
|
|
||||||
|
|
|
@ -113,6 +113,15 @@ class ImageDraw:
|
||||||
self.font = ImageFont.load_default()
|
self.font = ImageFont.load_default()
|
||||||
return self.font
|
return self.font
|
||||||
|
|
||||||
|
def _getfont(self, font_size):
|
||||||
|
if font_size is not None:
|
||||||
|
from . import ImageFont
|
||||||
|
|
||||||
|
font = ImageFont.load_default(font_size)
|
||||||
|
else:
|
||||||
|
font = self.getfont()
|
||||||
|
return font
|
||||||
|
|
||||||
def _getink(self, ink, fill=None):
|
def _getink(self, ink, fill=None):
|
||||||
if ink is None and fill is None:
|
if ink is None and fill is None:
|
||||||
if self.fill:
|
if self.fill:
|
||||||
|
@ -456,6 +465,13 @@ class ImageDraw:
|
||||||
**kwargs,
|
**kwargs,
|
||||||
):
|
):
|
||||||
"""Draw text."""
|
"""Draw text."""
|
||||||
|
if embedded_color and self.mode not in ("RGB", "RGBA"):
|
||||||
|
msg = "Embedded color supported only in RGB and RGBA modes"
|
||||||
|
raise ValueError(msg)
|
||||||
|
|
||||||
|
if font is None:
|
||||||
|
font = self._getfont(kwargs.get("font_size"))
|
||||||
|
|
||||||
if self._multiline_check(text):
|
if self._multiline_check(text):
|
||||||
return self.multiline_text(
|
return self.multiline_text(
|
||||||
xy,
|
xy,
|
||||||
|
@ -473,13 +489,6 @@ class ImageDraw:
|
||||||
embedded_color,
|
embedded_color,
|
||||||
)
|
)
|
||||||
|
|
||||||
if embedded_color and self.mode not in ("RGB", "RGBA"):
|
|
||||||
msg = "Embedded color supported only in RGB and RGBA modes"
|
|
||||||
raise ValueError(msg)
|
|
||||||
|
|
||||||
if font is None:
|
|
||||||
font = self.getfont()
|
|
||||||
|
|
||||||
def getink(fill):
|
def getink(fill):
|
||||||
ink, fill = self._getink(fill)
|
ink, fill = self._getink(fill)
|
||||||
if ink is None:
|
if ink is None:
|
||||||
|
@ -570,6 +579,8 @@ class ImageDraw:
|
||||||
stroke_width=0,
|
stroke_width=0,
|
||||||
stroke_fill=None,
|
stroke_fill=None,
|
||||||
embedded_color=False,
|
embedded_color=False,
|
||||||
|
*,
|
||||||
|
font_size=None,
|
||||||
):
|
):
|
||||||
if direction == "ttb":
|
if direction == "ttb":
|
||||||
msg = "ttb direction is unsupported for multiline text"
|
msg = "ttb direction is unsupported for multiline text"
|
||||||
|
@ -584,6 +595,9 @@ class ImageDraw:
|
||||||
msg = "anchor not supported for multiline text"
|
msg = "anchor not supported for multiline text"
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
|
|
||||||
|
if font is None:
|
||||||
|
font = self._getfont(font_size)
|
||||||
|
|
||||||
widths = []
|
widths = []
|
||||||
max_width = 0
|
max_width = 0
|
||||||
lines = self._multiline_split(text)
|
lines = self._multiline_split(text)
|
||||||
|
@ -645,6 +659,8 @@ class ImageDraw:
|
||||||
features=None,
|
features=None,
|
||||||
language=None,
|
language=None,
|
||||||
embedded_color=False,
|
embedded_color=False,
|
||||||
|
*,
|
||||||
|
font_size=None,
|
||||||
):
|
):
|
||||||
"""Get the length of a given string, in pixels with 1/64 precision."""
|
"""Get the length of a given string, in pixels with 1/64 precision."""
|
||||||
if self._multiline_check(text):
|
if self._multiline_check(text):
|
||||||
|
@ -655,7 +671,7 @@ class ImageDraw:
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
|
|
||||||
if font is None:
|
if font is None:
|
||||||
font = self.getfont()
|
font = self._getfont(font_size)
|
||||||
mode = "RGBA" if embedded_color else self.fontmode
|
mode = "RGBA" if embedded_color else self.fontmode
|
||||||
return font.getlength(text, mode, direction, features, language)
|
return font.getlength(text, mode, direction, features, language)
|
||||||
|
|
||||||
|
@ -672,12 +688,17 @@ class ImageDraw:
|
||||||
language=None,
|
language=None,
|
||||||
stroke_width=0,
|
stroke_width=0,
|
||||||
embedded_color=False,
|
embedded_color=False,
|
||||||
|
*,
|
||||||
|
font_size=None,
|
||||||
):
|
):
|
||||||
"""Get the bounding box of a given string, in pixels."""
|
"""Get the bounding box of a given string, in pixels."""
|
||||||
if embedded_color and self.mode not in ("RGB", "RGBA"):
|
if embedded_color and self.mode not in ("RGB", "RGBA"):
|
||||||
msg = "Embedded color supported only in RGB and RGBA modes"
|
msg = "Embedded color supported only in RGB and RGBA modes"
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
|
|
||||||
|
if font is None:
|
||||||
|
font = self._getfont(font_size)
|
||||||
|
|
||||||
if self._multiline_check(text):
|
if self._multiline_check(text):
|
||||||
return self.multiline_textbbox(
|
return self.multiline_textbbox(
|
||||||
xy,
|
xy,
|
||||||
|
@ -693,8 +714,6 @@ class ImageDraw:
|
||||||
embedded_color,
|
embedded_color,
|
||||||
)
|
)
|
||||||
|
|
||||||
if font is None:
|
|
||||||
font = self.getfont()
|
|
||||||
mode = "RGBA" if embedded_color else self.fontmode
|
mode = "RGBA" if embedded_color else self.fontmode
|
||||||
bbox = font.getbbox(
|
bbox = font.getbbox(
|
||||||
text, mode, direction, features, language, stroke_width, anchor
|
text, mode, direction, features, language, stroke_width, anchor
|
||||||
|
@ -714,6 +733,8 @@ class ImageDraw:
|
||||||
language=None,
|
language=None,
|
||||||
stroke_width=0,
|
stroke_width=0,
|
||||||
embedded_color=False,
|
embedded_color=False,
|
||||||
|
*,
|
||||||
|
font_size=None,
|
||||||
):
|
):
|
||||||
if direction == "ttb":
|
if direction == "ttb":
|
||||||
msg = "ttb direction is unsupported for multiline text"
|
msg = "ttb direction is unsupported for multiline text"
|
||||||
|
@ -728,6 +749,9 @@ class ImageDraw:
|
||||||
msg = "anchor not supported for multiline text"
|
msg = "anchor not supported for multiline text"
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
|
|
||||||
|
if font is None:
|
||||||
|
font = self._getfont(font_size)
|
||||||
|
|
||||||
widths = []
|
widths = []
|
||||||
max_width = 0
|
max_width = 0
|
||||||
lines = self._multiline_split(text)
|
lines = self._multiline_split(text)
|
||||||
|
|
|
@ -59,7 +59,7 @@ class Contrast(_Enhance):
|
||||||
|
|
||||||
This class can be used to control the contrast of an image, similar
|
This class can be used to control the contrast of an image, similar
|
||||||
to the contrast control on a TV set. An enhancement factor of 0.0
|
to the contrast control on a TV set. An enhancement factor of 0.0
|
||||||
gives a solid grey image. A factor of 1.0 gives the original image.
|
gives a solid gray image. A factor of 1.0 gives the original image.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, image):
|
def __init__(self, image):
|
||||||
|
|
|
@ -201,8 +201,8 @@ class ImageFile(Image.Image):
|
||||||
with open(self.filename) as fp:
|
with open(self.filename) as fp:
|
||||||
self.map = mmap.mmap(fp.fileno(), 0, access=mmap.ACCESS_READ)
|
self.map = mmap.mmap(fp.fileno(), 0, access=mmap.ACCESS_READ)
|
||||||
if offset + self.size[1] * args[1] > self.map.size():
|
if offset + self.size[1] * args[1] > self.map.size():
|
||||||
# buffer is not large enough
|
msg = "buffer is not large enough"
|
||||||
raise OSError
|
raise OSError(msg)
|
||||||
self.im = Image.core.map_buffer(
|
self.im = Image.core.map_buffer(
|
||||||
self.map, self.size, decoder_name, offset, args
|
self.map, self.size, decoder_name, offset, args
|
||||||
)
|
)
|
||||||
|
@ -691,7 +691,8 @@ class PyDecoder(PyCodec):
|
||||||
If finished with decoding return -1 for the bytes consumed.
|
If finished with decoding return -1 for the bytes consumed.
|
||||||
Err codes are from :data:`.ImageFile.ERRORS`.
|
Err codes are from :data:`.ImageFile.ERRORS`.
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError()
|
msg = "unavailable in base decoder"
|
||||||
|
raise NotImplementedError(msg)
|
||||||
|
|
||||||
def set_as_raw(self, data, rawmode=None):
|
def set_as_raw(self, data, rawmode=None):
|
||||||
"""
|
"""
|
||||||
|
@ -740,7 +741,8 @@ class PyEncoder(PyCodec):
|
||||||
If finished with encoding return 1 for the error code.
|
If finished with encoding return 1 for the error code.
|
||||||
Err codes are from :data:`.ImageFile.ERRORS`.
|
Err codes are from :data:`.ImageFile.ERRORS`.
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError()
|
msg = "unavailable in base encoder"
|
||||||
|
raise NotImplementedError(msg)
|
||||||
|
|
||||||
def encode_to_pyfd(self):
|
def encode_to_pyfd(self):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -861,19 +861,258 @@ def load_path(filename):
|
||||||
raise OSError(msg)
|
raise OSError(msg)
|
||||||
|
|
||||||
|
|
||||||
def load_default():
|
def load_default(size=None):
|
||||||
"""Load a "better than nothing" default font.
|
"""If FreeType support is available, load a version of Aileron Regular,
|
||||||
|
https://dotcolon.net/font/aileron, with a more limited character set.
|
||||||
|
|
||||||
|
Otherwise, load a "better than nothing" font.
|
||||||
|
|
||||||
.. versionadded:: 1.1.4
|
.. versionadded:: 1.1.4
|
||||||
|
|
||||||
|
:param size: The font size of Aileron Regular.
|
||||||
|
|
||||||
|
.. versionadded:: 10.1.0
|
||||||
|
|
||||||
:return: A font object.
|
:return: A font object.
|
||||||
"""
|
"""
|
||||||
f = ImageFont()
|
if core.__class__.__name__ == "module" or size is not None:
|
||||||
f._load_pilfont_data(
|
f = truetype(
|
||||||
# courB08
|
BytesIO(
|
||||||
BytesIO(
|
base64.b64decode(
|
||||||
base64.b64decode(
|
b"""
|
||||||
b"""
|
AAEAAAAPAIAAAwBwRkZUTYwDlUAAADFoAAAAHEdERUYAqADnAAAo8AAAACRHUE9ThhmITwAAKfgAA
|
||||||
|
AduR1NVQnHxefoAACkUAAAA4k9TLzJovoHLAAABeAAAAGBjbWFw5lFQMQAAA6gAAAGqZ2FzcP//AA
|
||||||
|
MAACjoAAAACGdseWYmRXoPAAAGQAAAHfhoZWFkE18ayQAAAPwAAAA2aGhlYQboArEAAAE0AAAAJGh
|
||||||
|
tdHjjERZ8AAAB2AAAAdBsb2NhuOexrgAABVQAAADqbWF4cAC7AEYAAAFYAAAAIG5hbWUr+h5lAAAk
|
||||||
|
OAAAA6Jwb3N0D3oPTQAAJ9wAAAEKAAEAAAABGhxJDqIhXw889QALA+gAAAAA0Bqf2QAAAADhCh2h/
|
||||||
|
2r/LgOxAyAAAAAIAAIAAAAAAAAAAQAAA8r/GgAAA7j/av9qA7EAAQAAAAAAAAAAAAAAAAAAAHQAAQ
|
||||||
|
AAAHQAQwAFAAAAAAACAAAAAQABAAAAQAAAAAAAAAADAfoBkAAFAAgCigJYAAAASwKKAlgAAAFeADI
|
||||||
|
BPgAAAAAFAAAAAAAAAAAAAAcAAAAAAAAAAAAAAABVS1dOAEAAIPsCAwL/GgDIA8oA5iAAAJMAAAAA
|
||||||
|
AhICsgAAACAAAwH0AAAAAAAAAU0AAADYAAAA8gA5AVMAVgJEAEYCRAA1AuQAKQKOAEAAsAArATsAZ
|
||||||
|
AE7AB4CMABVAkQAUADc/+EBEgAgANwAJQEv//sCRAApAkQAggJEADwCRAAtAkQAIQJEADkCRAArAk
|
||||||
|
QAMgJEACwCRAAxANwAJQDc/+ECRABnAkQAUAJEAEQB8wAjA1QANgJ/AB0CcwBkArsALwLFAGQCSwB
|
||||||
|
kAjcAZALGAC8C2gBkAQgAZAIgADcCYQBkAj8AZANiAGQCzgBkAuEALwJWAGQC3QAvAmsAZAJJADQC
|
||||||
|
ZAAiAqoAXgJuACADuAAaAnEAGQJFABMCTwAuATMAYgEv//sBJwAiAkQAUAH0ADIBLAApAhMAJAJjA
|
||||||
|
EoCEQAeAmcAHgIlAB4BIgAVAmcAHgJRAEoA7gA+AOn/8wIKAEoA9wBGA1cASgJRAEoCSgAeAmMASg
|
||||||
|
JnAB4BSgBKAcsAGAE5ABQCUABCAgIAAQMRAAEB4v/6AgEAAQHOABQBLwBAAPoAYAEvACECRABNA0Y
|
||||||
|
AJAItAHgBKgAcAkQAUAEsAHQAygAgAi0AOQD3ADYA9wAWAaEANgGhABYCbAAlAYMAeAGDADkA6/9q
|
||||||
|
AhsAFAIKABUB/QAVAAAAAwAAAAMAAAAcAAEAAAAAAKQAAwABAAAAHAAEAIgAAAAeABAAAwAOAH4Aq
|
||||||
|
QCrALEAtAC3ALsgGSAdICYgOiBEISL7Av//AAAAIACpAKsAsAC0ALcAuyAYIBwgJiA5IEQhIvsB//
|
||||||
|
//4/+5/7j/tP+y/7D/reBR4E/gR+A14CzfTwVxAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAEGAAABAAAAAAAAAAECAAAAAgAAAAAAAAAAAAAAAAAAAAEAAAMEBQYHCAkKCwwNDg8QERIT
|
||||||
|
FBUWFxgZGhscHR4fICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODk6Ozw9Pj9AQUJDREVGR0hJSktMT
|
||||||
|
U5PUFFSU1RVVldYWVpbXF1eX2BhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGQAAA
|
||||||
|
AAAAAAYnFmAAAAAABlAAAAAAAAAAAAAAAAAAAAAAAAAAAAY2htAAAAAAAAAABrbGlqAAAAAHAAbm9
|
||||||
|
ycwBnAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmACYAJgAmAD4AUgCCAMoBCgFO
|
||||||
|
AVwBcgGIAaYBvAHKAdYB6AH2AgwCIAJKAogCpgLWAw4DIgNkA5wDugPUA+gD/AQQBEYEogS8BPoFJ
|
||||||
|
gVSBWoFgAWwBcoF1gX6BhQGJAZMBmgGiga0BuIHGgdUB2YHkAeiB8AH3AfyCAoIHAgqCDoITghcCG
|
||||||
|
oIogjSCPoJKglYCXwJwgnqCgIKKApACl4Klgq8CtwLDAs8C1YLjAuyC9oL7gwMDCYMSAxgDKAMrAz
|
||||||
|
qDQoNTA1mDYQNoA2uDcAN2g3oDfYODA4iDkoOXA5sDnoOnA7EDvwAAAAFAAAAAAH0ArwAAwAGAAkA
|
||||||
|
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
|
||||||
|
AAAxLjEwMjtVS1dOO0FpbGVyb24tUmVndWxhcgAAQQBpAGwAZQByAG8AbgAAQWlsZXJvbgAAVgBlA
|
||||||
|
HIAcwBpAG8AbgAgADEALgAxADAAMgA7AFAAUwAgADAAMAAxAC4AMQAwADIAOwBoAG8AdABjAG8Abg
|
||||||
|
B2ACAAMQAuADAALgA3ADAAOwBtAGEAawBlAG8AdABmAC4AbABpAGIAMgAuADUALgA1ADgAMwAyADk
|
||||||
|
AAFZlcnNpb24gMS4xMDI7UFMgMDAxLjEwMjtob3Rjb252IDEuMC43MDttYWtlb3RmLmxpYjIuNS41
|
||||||
|
ODMyOQAAQQBpAGwAZQByAG8AbgAtAFIAZQBnAHUAbABhAHIAAEFpbGVyb24tUmVndWxhcgAAUwBvA
|
||||||
|
HIAYQAgAFMAYQBnAGEAbgBvAABTb3JhIFNhZ2FubwAAUwBvAHIAYQAgAFMAYQBnAGEAbgBvAABTb3
|
||||||
|
JhIFNhZ2FubwAAaAB0AHQAcAA6AC8ALwB3AHcAdwAuAGQAbwB0AGMAbwBsAG8AbgAuAG4AZQB0AAB
|
||||||
|
odHRwOi8vd3d3LmRvdGNvbG9uLm5ldAAAaAB0AHQAcAA6AC8ALwB3AHcAdwAuAGQAbwB0AGMAbwBs
|
||||||
|
AG8AbgAuAG4AZQB0AABodHRwOi8vd3d3LmRvdGNvbG9uLm5ldAAAAAACAAAAAAAA/4MAMgAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAHQAAAABAAIAAwAEAAUABgAHAAgACQAKAAsADAANAA4ADwAQABEAEgATAB
|
||||||
|
QAFQAWABcAGAAZABoAGwAcAB0AHgAfACAAIQAiACMAJAAlACYAJwAoACkAKgArACwALQAuAC8AMAA
|
||||||
|
xADIAMwA0ADUANgA3ADgAOQA6ADsAPAA9AD4APwBAAEEAQgBDAEQARQBGAEcASABJAEoASwBMAE0A
|
||||||
|
TgBPAFAAUQBSAFMAVABVAFYAVwBYAFkAWgBbAFwAXQBeAF8AYABhAIsAqQCDAJMAjQDDAKoAtgC3A
|
||||||
|
LQAtQCrAL4AvwC8AIwAwADBAAAAAAAB//8AAgABAAAADAAAABwAAAACAAIAAwBxAAEAcgBzAAIABA
|
||||||
|
AAAAIAAAABAAAACgBMAGYAAkRGTFQADmxhdG4AGgAEAAAAAP//AAEAAAAWAANDQVQgAB5NT0wgABZ
|
||||||
|
ST00gABYAAP//AAEAAAAA//8AAgAAAAEAAmxpZ2EADmxvY2wAFAAAAAEAAQAAAAEAAAACAAYAEAAG
|
||||||
|
AAAAAgASADQABAAAAAEATAADAAAAAgAQABYAAQAcAAAAAQABAE8AAQABAGcAAQABAE8AAwAAAAIAE
|
||||||
|
AAWAAEAHAAAAAEAAQAvAAEAAQBnAAEAAQAvAAEAGgABAAgAAgAGAAwAcwACAE8AcgACAEwAAQABAE
|
||||||
|
kAAAABAAAACgBGAGAAAkRGTFQADmxhdG4AHAAEAAAAAP//AAIAAAABABYAA0NBVCAAFk1PTCAAFlJ
|
||||||
|
PTSAAFgAA//8AAgAAAAEAAmNwc3AADmtlcm4AFAAAAAEAAAAAAAEAAQACAAYADgABAAAAAQASAAIA
|
||||||
|
AAACAB4ANgABAAoABQAFAAoAAgABACQAPQAAAAEAEgAEAAAAAQAMAAEAOP/nAAEAAQAkAAIGigAEA
|
||||||
|
AAFJAXKABoAGQAA//gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAD/sv+4/+z/7v/MAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAD/xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/9T/6AAAAAD/8QAA
|
||||||
|
ABD/vQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/7gAAAAAAAAAAAAAAAAAA//MAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABIAAAAAAAAAAP/5AAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/gAAD/4AAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//L/9AAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAA/+gAAAAAAAkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/zAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/mAAAAAAAAAAAAAAAAAAD
|
||||||
|
/4gAA//AAAAAA//YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/+AAAAAAAAP/OAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/zv/qAAAAAP/0AAAACAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/ZAAD/egAA/1kAAAAA/5D/rgAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAD/9AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAD/8AAA/7b/8P+wAAD/8P/E/98AAAAA/8P/+P/0//oAAAAAAAAAAAAA//gA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/+AAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/w//C/9MAAP/SAAD/9wAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAD/yAAA/+kAAAAA//QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/9wAAAAD//QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAP/2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAP/cAAAAAAAAAAAAAAAA/7YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAP/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/6AAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAkAFAAEAAAAAQACwAAABcA
|
||||||
|
BgAAAAAAAAAIAA4AAAAAAAsAEgAAAAAAAAATABkAAwANAAAAAQAJAAAAAAAAAAAAAAAAAAAAGAAAA
|
||||||
|
AAABwAAAAAAAAAAAAAAFQAFAAAAAAAYABgAAAAUAAAACgAAAAwAAgAPABEAFgAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAEAEQBdAAYAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAcAAAAAAAAABwAAAAAACAAAAAAAAAAAAAcAAAAHAAAAEwAJ
|
||||||
|
ABUADgAPAAAACwAQAAAAAAAAAAAAAAAAAAUAGAACAAIAAgAAAAIAGAAXAAAAGAAAABYAFgACABYAA
|
||||||
|
gAWAAAAEQADAAoAFAAMAA0ABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASAAAAEgAGAAEAHgAkAC
|
||||||
|
YAJwApACoALQAuAC8AMgAzADcAOAA5ADoAPAA9AEUASABOAE8AUgBTAFUAVwBZAFoAWwBcAF0AcwA
|
||||||
|
AAAAAAQAAAADa3tfFAAAAANAan9kAAAAA4QodoQ==
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
),
|
||||||
|
10 if size is None else size,
|
||||||
|
layout_engine=Layout.BASIC,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
f = ImageFont()
|
||||||
|
f._load_pilfont_data(
|
||||||
|
# courB08
|
||||||
|
BytesIO(
|
||||||
|
base64.b64decode(
|
||||||
|
b"""
|
||||||
UElMZm9udAo7Ozs7OzsxMDsKREFUQQoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
UElMZm9udAo7Ozs7OzsxMDsKREFUQQoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
@ -966,12 +1205,12 @@ pQAKAKwAEgAGAAD////4AAYAAACsAAoAswASAAYAAP////gABgAAALMACgC6ABIABgAA////+QAG
|
||||||
AAAAugAKAMEAEQAGAAD////4AAYAAgDBAAoAyAAUAAYAAP////kABQACAMgACgDOABMABgAA////
|
AAAAugAKAMEAEQAGAAD////4AAYAAgDBAAoAyAAUAAYAAP////kABQACAMgACgDOABMABgAA////
|
||||||
+QAGAAIAzgAKANUAEw==
|
+QAGAAIAzgAKANUAEw==
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
Image.open(
|
Image.open(
|
||||||
BytesIO(
|
BytesIO(
|
||||||
base64.b64decode(
|
base64.b64decode(
|
||||||
b"""
|
b"""
|
||||||
iVBORw0KGgoAAAANSUhEUgAAAx4AAAAUAQAAAAArMtZoAAAEwElEQVR4nABlAJr/AHVE4czCI/4u
|
iVBORw0KGgoAAAANSUhEUgAAAx4AAAAUAQAAAAArMtZoAAAEwElEQVR4nABlAJr/AHVE4czCI/4u
|
||||||
Mc4b7vuds/xzjz5/3/7u/n9vMe7vnfH/9++vPn/xyf5zhxzjt8GHw8+2d83u8x27199/nxuQ6Od9
|
Mc4b7vuds/xzjz5/3/7u/n9vMe7vnfH/9++vPn/xyf5zhxzjt8GHw8+2d83u8x27199/nxuQ6Od9
|
||||||
M43/5z2I+9n9ZtmDBwMQECDRQw/eQIQohJXxpBCNVE6QCCAAAAD//wBlAJr/AgALyj1t/wINwq0g
|
M43/5z2I+9n9ZtmDBwMQECDRQw/eQIQohJXxpBCNVE6QCCAAAAD//wBlAJr/AgALyj1t/wINwq0g
|
||||||
|
@ -996,8 +1235,8 @@ AAD//2Ji2FrkY3iYpYC5qDeGgeEMAwPDvwQBBoYvcTwOVLMEAAAA//9isDBgkP///0EOg9z35v//
|
||||||
Gc/eeW7BwPj5+QGZhANUswMAAAD//2JgqGBgYGBgqEMXlvhMPUsAAAAA//8iYDd1AAAAAP//AwDR
|
Gc/eeW7BwPj5+QGZhANUswMAAAD//2JgqGBgYGBgqEMXlvhMPUsAAAAA//8iYDd1AAAAAP//AwDR
|
||||||
w7IkEbzhVQAAAABJRU5ErkJggg==
|
w7IkEbzhVQAAAABJRU5ErkJggg==
|
||||||
"""
|
"""
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
),
|
||||||
),
|
)
|
||||||
)
|
|
||||||
return f
|
return f
|
||||||
|
|
|
@ -242,7 +242,7 @@ def contain(image, size, method=Image.Resampling.BICUBIC):
|
||||||
Returns a resized version of the image, set to the maximum width and height
|
Returns a resized version of the image, set to the maximum width and height
|
||||||
within the requested size, while maintaining the original aspect ratio.
|
within the requested size, while maintaining the original aspect ratio.
|
||||||
|
|
||||||
:param image: The image to resize and crop.
|
:param image: The image to resize.
|
||||||
:param size: The requested output size in pixels, given as a
|
:param size: The requested output size in pixels, given as a
|
||||||
(width, height) tuple.
|
(width, height) tuple.
|
||||||
:param method: Resampling method to use. Default is
|
:param method: Resampling method to use. Default is
|
||||||
|
@ -266,6 +266,35 @@ def contain(image, size, method=Image.Resampling.BICUBIC):
|
||||||
return image.resize(size, resample=method)
|
return image.resize(size, resample=method)
|
||||||
|
|
||||||
|
|
||||||
|
def cover(image, size, method=Image.Resampling.BICUBIC):
|
||||||
|
"""
|
||||||
|
Returns a resized version of the image, so that the requested size is
|
||||||
|
covered, while maintaining the original aspect ratio.
|
||||||
|
|
||||||
|
:param image: The image to resize.
|
||||||
|
:param size: The requested output size in pixels, given as a
|
||||||
|
(width, height) tuple.
|
||||||
|
:param method: Resampling method to use. Default is
|
||||||
|
:py:attr:`~PIL.Image.Resampling.BICUBIC`.
|
||||||
|
See :ref:`concept-filters`.
|
||||||
|
:return: An image.
|
||||||
|
"""
|
||||||
|
|
||||||
|
im_ratio = image.width / image.height
|
||||||
|
dest_ratio = size[0] / size[1]
|
||||||
|
|
||||||
|
if im_ratio != dest_ratio:
|
||||||
|
if im_ratio < dest_ratio:
|
||||||
|
new_height = round(image.height / image.width * size[0])
|
||||||
|
if new_height != size[1]:
|
||||||
|
size = (size[0], new_height)
|
||||||
|
else:
|
||||||
|
new_width = round(image.width / image.height * size[1])
|
||||||
|
if new_width != size[0]:
|
||||||
|
size = (new_width, size[1])
|
||||||
|
return image.resize(size, resample=method)
|
||||||
|
|
||||||
|
|
||||||
def pad(image, size, method=Image.Resampling.BICUBIC, color=None, centering=(0.5, 0.5)):
|
def pad(image, size, method=Image.Resampling.BICUBIC, color=None, centering=(0.5, 0.5)):
|
||||||
"""
|
"""
|
||||||
Returns a resized and padded version of the image, expanded to fill the
|
Returns a resized and padded version of the image, expanded to fill the
|
||||||
|
@ -564,7 +593,7 @@ def solarize(image, threshold=128):
|
||||||
Invert all pixel values above a threshold.
|
Invert all pixel values above a threshold.
|
||||||
|
|
||||||
:param image: The image to solarize.
|
:param image: The image to solarize.
|
||||||
:param threshold: All pixels above this greyscale level are inverted.
|
:param threshold: All pixels above this grayscale level are inverted.
|
||||||
:return: An image.
|
:return: An image.
|
||||||
"""
|
"""
|
||||||
lut = []
|
lut = []
|
||||||
|
|
|
@ -205,7 +205,8 @@ def make_linear_lut(black, white):
|
||||||
for i in range(256):
|
for i in range(256):
|
||||||
lut.append(white * i // 255)
|
lut.append(white * i // 255)
|
||||||
else:
|
else:
|
||||||
raise NotImplementedError # FIXME
|
msg = "unavailable when black is non-zero"
|
||||||
|
raise NotImplementedError(msg) # FIXME
|
||||||
return lut
|
return lut
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,8 @@ class Iterator:
|
||||||
self.im.seek(ix)
|
self.im.seek(ix)
|
||||||
return self.im
|
return self.im
|
||||||
except EOFError as e:
|
except EOFError as e:
|
||||||
raise IndexError from e # end of sequence
|
msg = "end of sequence"
|
||||||
|
raise IndexError(msg) from e
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
return self
|
return self
|
||||||
|
@ -51,7 +52,8 @@ class Iterator:
|
||||||
self.position += 1
|
self.position += 1
|
||||||
return self.im
|
return self.im
|
||||||
except EOFError as e:
|
except EOFError as e:
|
||||||
raise StopIteration from e
|
msg = "end of sequence"
|
||||||
|
raise StopIteration(msg) from e
|
||||||
|
|
||||||
|
|
||||||
def all_frames(im, func=None):
|
def all_frames(im, func=None):
|
||||||
|
|
|
@ -99,7 +99,8 @@ class Viewer:
|
||||||
Returns the command used to display the file.
|
Returns the command used to display the file.
|
||||||
Not implemented in the base class.
|
Not implemented in the base class.
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError
|
msg = "unavailable in base viewer"
|
||||||
|
raise NotImplementedError(msg)
|
||||||
|
|
||||||
def save_image(self, image):
|
def save_image(self, image):
|
||||||
"""Save to temporary file and return filename."""
|
"""Save to temporary file and return filename."""
|
||||||
|
|
|
@ -54,9 +54,9 @@ class Dib:
|
||||||
"L", "P", or "RGB".
|
"L", "P", or "RGB".
|
||||||
|
|
||||||
If the display requires a palette, this constructor creates a suitable
|
If the display requires a palette, this constructor creates a suitable
|
||||||
palette and associates it with the image. For an "L" image, 128 greylevels
|
palette and associates it with the image. For an "L" image, 128 graylevels
|
||||||
are allocated. For an "RGB" image, a 6x6x6 colour cube is used, together
|
are allocated. For an "RGB" image, a 6x6x6 colour cube is used, together
|
||||||
with 20 greylevels.
|
with 20 graylevels.
|
||||||
|
|
||||||
To make sure that palettes work properly under Windows, you must call the
|
To make sure that palettes work properly under Windows, you must call the
|
||||||
``palette`` method upon certain events from Windows.
|
``palette`` method upon certain events from Windows.
|
||||||
|
|
|
@ -165,16 +165,25 @@ def APP(self, marker):
|
||||||
except TypeError:
|
except TypeError:
|
||||||
dpi = x_resolution
|
dpi = x_resolution
|
||||||
if math.isnan(dpi):
|
if math.isnan(dpi):
|
||||||
raise ValueError
|
msg = "DPI is not a number"
|
||||||
|
raise ValueError(msg)
|
||||||
if resolution_unit == 3: # cm
|
if resolution_unit == 3: # cm
|
||||||
# 1 dpcm = 2.54 dpi
|
# 1 dpcm = 2.54 dpi
|
||||||
dpi *= 2.54
|
dpi *= 2.54
|
||||||
self.info["dpi"] = dpi, dpi
|
self.info["dpi"] = dpi, dpi
|
||||||
except (TypeError, KeyError, SyntaxError, ValueError, ZeroDivisionError):
|
except (
|
||||||
# SyntaxError for invalid/unreadable EXIF
|
struct.error,
|
||||||
|
KeyError,
|
||||||
|
SyntaxError,
|
||||||
|
TypeError,
|
||||||
|
ValueError,
|
||||||
|
ZeroDivisionError,
|
||||||
|
):
|
||||||
|
# struct.error for truncated EXIF
|
||||||
# KeyError for dpi not included
|
# KeyError for dpi not included
|
||||||
# ZeroDivisionError for invalid dpi rational value
|
# SyntaxError for invalid/unreadable EXIF
|
||||||
# ValueError or TypeError for dpi being an invalid float
|
# ValueError or TypeError for dpi being an invalid float
|
||||||
|
# ZeroDivisionError for invalid dpi rational value
|
||||||
self.info["dpi"] = 72, 72
|
self.info["dpi"] = 72, 72
|
||||||
|
|
||||||
|
|
||||||
|
@ -711,7 +720,8 @@ def _save(im, fp, filename):
|
||||||
for idx, table in enumerate(qtables):
|
for idx, table in enumerate(qtables):
|
||||||
try:
|
try:
|
||||||
if len(table) != 64:
|
if len(table) != 64:
|
||||||
raise TypeError
|
msg = "Invalid quantization table"
|
||||||
|
raise TypeError(msg)
|
||||||
table = array.array("H", table)
|
table = array.array("H", table)
|
||||||
except TypeError as e:
|
except TypeError as e:
|
||||||
msg = "Invalid quantization table"
|
msg = "Invalid quantization table"
|
||||||
|
|
|
@ -109,7 +109,7 @@ class PSDraw:
|
||||||
if im.mode == "1":
|
if im.mode == "1":
|
||||||
dpi = 200 # fax
|
dpi = 200 # fax
|
||||||
else:
|
else:
|
||||||
dpi = 100 # greyscale
|
dpi = 100 # grayscale
|
||||||
# image size (on paper)
|
# image size (on paper)
|
||||||
x = im.size[0] * 72 / dpi
|
x = im.size[0] * 72 / dpi
|
||||||
y = im.size[1] * 72 / dpi
|
y = im.size[1] * 72 / dpi
|
||||||
|
|
|
@ -124,7 +124,7 @@ def _save(im, fp, filename):
|
||||||
if im.encoderinfo.get("bpp") in (1, 2, 4):
|
if im.encoderinfo.get("bpp") in (1, 2, 4):
|
||||||
# this is 8-bit grayscale, so we shift it to get the high-order bits,
|
# this is 8-bit grayscale, so we shift it to get the high-order bits,
|
||||||
# and invert it because
|
# and invert it because
|
||||||
# Palm does greyscale from white (0) to black (1)
|
# Palm does grayscale from white (0) to black (1)
|
||||||
bpp = im.encoderinfo["bpp"]
|
bpp = im.encoderinfo["bpp"]
|
||||||
im = im.point(
|
im = im.point(
|
||||||
lambda x, shift=8 - bpp, maxval=(1 << bpp) - 1: maxval - (x >> shift)
|
lambda x, shift=8 - bpp, maxval=(1 << bpp) - 1: maxval - (x >> shift)
|
||||||
|
|
|
@ -91,7 +91,7 @@ class PcxImageFile(ImageFile.ImageFile):
|
||||||
self.fp.seek(-769, io.SEEK_END)
|
self.fp.seek(-769, io.SEEK_END)
|
||||||
s = self.fp.read(769)
|
s = self.fp.read(769)
|
||||||
if len(s) == 769 and s[0] == 12:
|
if len(s) == 769 and s[0] == 12:
|
||||||
# check if the palette is linear greyscale
|
# check if the palette is linear grayscale
|
||||||
for i in range(256):
|
for i in range(256):
|
||||||
if s[i * 3 + 1 : i * 3 + 4] != o8(i) * 3:
|
if s[i * 3 + 1 : i * 3 + 4] != o8(i) * 3:
|
||||||
mode = rawmode = "P"
|
mode = rawmode = "P"
|
||||||
|
@ -203,7 +203,7 @@ def _save(im, fp, filename):
|
||||||
palette += b"\x00" * (768 - len(palette))
|
palette += b"\x00" * (768 - len(palette))
|
||||||
fp.write(palette) # 768 bytes
|
fp.write(palette) # 768 bytes
|
||||||
elif im.mode == "L":
|
elif im.mode == "L":
|
||||||
# greyscale palette
|
# grayscale palette
|
||||||
fp.write(o8(12))
|
fp.write(o8(12))
|
||||||
for i in range(256):
|
for i in range(256):
|
||||||
fp.write(o8(i) * 3)
|
fp.write(o8(i) * 3)
|
||||||
|
|
|
@ -56,7 +56,7 @@ _MAGIC = b"\211PNG\r\n\032\n"
|
||||||
|
|
||||||
_MODES = {
|
_MODES = {
|
||||||
# supported bits/color combinations, and corresponding modes/rawmodes
|
# supported bits/color combinations, and corresponding modes/rawmodes
|
||||||
# Greyscale
|
# Grayscale
|
||||||
(1, 0): ("1", "1"),
|
(1, 0): ("1", "1"),
|
||||||
(2, 0): ("L", "L;2"),
|
(2, 0): ("L", "L;2"),
|
||||||
(4, 0): ("L", "L;4"),
|
(4, 0): ("L", "L;4"),
|
||||||
|
@ -70,7 +70,7 @@ _MODES = {
|
||||||
(2, 3): ("P", "P;2"),
|
(2, 3): ("P", "P;2"),
|
||||||
(4, 3): ("P", "P;4"),
|
(4, 3): ("P", "P;4"),
|
||||||
(8, 3): ("P", "P"),
|
(8, 3): ("P", "P"),
|
||||||
# Greyscale with alpha
|
# Grayscale with alpha
|
||||||
(8, 4): ("LA", "LA"),
|
(8, 4): ("LA", "LA"),
|
||||||
(16, 4): ("RGBA", "LA;16B"), # LA;16B->LA not yet available
|
(16, 4): ("RGBA", "LA;16B"), # LA;16B->LA not yet available
|
||||||
# Truecolour with alpha
|
# Truecolour with alpha
|
||||||
|
@ -438,11 +438,12 @@ class PngStream(ChunkStream):
|
||||||
tile = [("zip", (0, 0) + self.im_size, pos, self.im_rawmode)]
|
tile = [("zip", (0, 0) + self.im_size, pos, self.im_rawmode)]
|
||||||
self.im_tile = tile
|
self.im_tile = tile
|
||||||
self.im_idat = length
|
self.im_idat = length
|
||||||
raise EOFError
|
msg = "image data found"
|
||||||
|
raise EOFError(msg)
|
||||||
|
|
||||||
def chunk_IEND(self, pos, length):
|
def chunk_IEND(self, pos, length):
|
||||||
# end of PNG image
|
msg = "end of PNG image"
|
||||||
raise EOFError
|
raise EOFError(msg)
|
||||||
|
|
||||||
def chunk_PLTE(self, pos, length):
|
def chunk_PLTE(self, pos, length):
|
||||||
# palette
|
# palette
|
||||||
|
@ -891,7 +892,8 @@ class PngImageFile(ImageFile.ImageFile):
|
||||||
self.dispose_extent = self.info.get("bbox")
|
self.dispose_extent = self.info.get("bbox")
|
||||||
|
|
||||||
if not self.tile:
|
if not self.tile:
|
||||||
raise EOFError
|
msg = "image not found in APNG frame"
|
||||||
|
raise EOFError(msg)
|
||||||
|
|
||||||
# setup frame disposal (actual disposal done when needed in the next _seek())
|
# setup frame disposal (actual disposal done when needed in the next _seek())
|
||||||
if self._prev_im is None and self.dispose_op == Disposal.OP_PREVIOUS:
|
if self._prev_im is None and self.dispose_op == Disposal.OP_PREVIOUS:
|
||||||
|
@ -1105,10 +1107,7 @@ def _write_multiple_frames(im, fp, chunk, rawmode, default_image, append_images)
|
||||||
if im_frame.mode == rawmode:
|
if im_frame.mode == rawmode:
|
||||||
im_frame = im_frame.copy()
|
im_frame = im_frame.copy()
|
||||||
else:
|
else:
|
||||||
if rawmode == "P":
|
im_frame = im_frame.convert(rawmode)
|
||||||
im_frame = im_frame.convert(rawmode, palette=im.palette)
|
|
||||||
else:
|
|
||||||
im_frame = im_frame.convert(rawmode)
|
|
||||||
encoderinfo = im.encoderinfo.copy()
|
encoderinfo = im.encoderinfo.copy()
|
||||||
if isinstance(duration, (list, tuple)):
|
if isinstance(duration, (list, tuple)):
|
||||||
encoderinfo["duration"] = duration[frame_count]
|
encoderinfo["duration"] = duration[frame_count]
|
||||||
|
@ -1167,6 +1166,8 @@ def _write_multiple_frames(im, fp, chunk, rawmode, default_image, append_images)
|
||||||
|
|
||||||
# default image IDAT (if it exists)
|
# default image IDAT (if it exists)
|
||||||
if default_image:
|
if default_image:
|
||||||
|
if im.mode != rawmode:
|
||||||
|
im = im.convert(rawmode)
|
||||||
ImageFile._save(im, _idat(fp, chunk), [("zip", (0, 0) + im.size, 0, rawmode)])
|
ImageFile._save(im, _idat(fp, chunk), [("zip", (0, 0) + im.size, 0, rawmode)])
|
||||||
|
|
||||||
seq_num = 0
|
seq_num = 0
|
||||||
|
@ -1228,11 +1229,7 @@ def _save(im, fp, filename, chunk=putchunk, save_all=False):
|
||||||
)
|
)
|
||||||
modes = set()
|
modes = set()
|
||||||
append_images = im.encoderinfo.get("append_images", [])
|
append_images = im.encoderinfo.get("append_images", [])
|
||||||
if default_image:
|
for im_seq in itertools.chain([im], append_images):
|
||||||
chain = itertools.chain(append_images)
|
|
||||||
else:
|
|
||||||
chain = itertools.chain([im], append_images)
|
|
||||||
for im_seq in chain:
|
|
||||||
for im_frame in ImageSequence.Iterator(im_seq):
|
for im_frame in ImageSequence.Iterator(im_seq):
|
||||||
modes.add(im_frame.mode)
|
modes.add(im_frame.mode)
|
||||||
for mode in ("RGBA", "RGB", "P"):
|
for mode in ("RGBA", "RGB", "P"):
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
# Master version for Pillow
|
# Master version for Pillow
|
||||||
__version__ = "10.1.0.dev0"
|
__version__ = "10.2.0.dev0"
|
||||||
|
|
|
@ -1575,7 +1575,7 @@ if (PySequence_Check(op)) { \
|
||||||
}
|
}
|
||||||
double value;
|
double value;
|
||||||
if (image->bands == 1) {
|
if (image->bands == 1) {
|
||||||
int bigendian;
|
int bigendian = 0;
|
||||||
if (image->type == IMAGING_TYPE_SPECIAL) {
|
if (image->type == IMAGING_TYPE_SPECIAL) {
|
||||||
// I;16*
|
// I;16*
|
||||||
bigendian = strcmp(image->mode, "I;16B") == 0;
|
bigendian = strcmp(image->mode, "I;16B") == 0;
|
||||||
|
|
|
@ -1013,7 +1013,7 @@ static struct {
|
||||||
static void
|
static void
|
||||||
p2bit(UINT8 *out, const UINT8 *in, int xsize, ImagingPalette palette) {
|
p2bit(UINT8 *out, const UINT8 *in, int xsize, ImagingPalette palette) {
|
||||||
int x;
|
int x;
|
||||||
/* FIXME: precalculate greyscale palette? */
|
/* FIXME: precalculate grayscale palette? */
|
||||||
for (x = 0; x < xsize; x++) {
|
for (x = 0; x < xsize; x++) {
|
||||||
*out++ = (L(&palette->palette[in[x] * 4]) >= 128000) ? 255 : 0;
|
*out++ = (L(&palette->palette[in[x] * 4]) >= 128000) ? 255 : 0;
|
||||||
}
|
}
|
||||||
|
@ -1022,7 +1022,7 @@ p2bit(UINT8 *out, const UINT8 *in, int xsize, ImagingPalette palette) {
|
||||||
static void
|
static void
|
||||||
pa2bit(UINT8 *out, const UINT8 *in, int xsize, ImagingPalette palette) {
|
pa2bit(UINT8 *out, const UINT8 *in, int xsize, ImagingPalette palette) {
|
||||||
int x;
|
int x;
|
||||||
/* FIXME: precalculate greyscale palette? */
|
/* FIXME: precalculate grayscale palette? */
|
||||||
for (x = 0; x < xsize; x++, in += 4) {
|
for (x = 0; x < xsize; x++, in += 4) {
|
||||||
*out++ = (L(&palette->palette[in[0] * 4]) >= 128000) ? 255 : 0;
|
*out++ = (L(&palette->palette[in[0] * 4]) >= 128000) ? 255 : 0;
|
||||||
}
|
}
|
||||||
|
@ -1031,7 +1031,7 @@ pa2bit(UINT8 *out, const UINT8 *in, int xsize, ImagingPalette palette) {
|
||||||
static void
|
static void
|
||||||
p2l(UINT8 *out, const UINT8 *in, int xsize, ImagingPalette palette) {
|
p2l(UINT8 *out, const UINT8 *in, int xsize, ImagingPalette palette) {
|
||||||
int x;
|
int x;
|
||||||
/* FIXME: precalculate greyscale palette? */
|
/* FIXME: precalculate grayscale palette? */
|
||||||
for (x = 0; x < xsize; x++) {
|
for (x = 0; x < xsize; x++) {
|
||||||
*out++ = L24(&palette->palette[in[x] * 4]) >> 16;
|
*out++ = L24(&palette->palette[in[x] * 4]) >> 16;
|
||||||
}
|
}
|
||||||
|
@ -1040,7 +1040,7 @@ p2l(UINT8 *out, const UINT8 *in, int xsize, ImagingPalette palette) {
|
||||||
static void
|
static void
|
||||||
pa2l(UINT8 *out, const UINT8 *in, int xsize, ImagingPalette palette) {
|
pa2l(UINT8 *out, const UINT8 *in, int xsize, ImagingPalette palette) {
|
||||||
int x;
|
int x;
|
||||||
/* FIXME: precalculate greyscale palette? */
|
/* FIXME: precalculate grayscale palette? */
|
||||||
for (x = 0; x < xsize; x++, in += 4) {
|
for (x = 0; x < xsize; x++, in += 4) {
|
||||||
*out++ = L24(&palette->palette[in[0] * 4]) >> 16;
|
*out++ = L24(&palette->palette[in[0] * 4]) >> 16;
|
||||||
}
|
}
|
||||||
|
@ -1070,7 +1070,7 @@ p2pa(UINT8 *out, const UINT8 *in, int xsize, ImagingPalette palette) {
|
||||||
static void
|
static void
|
||||||
p2la(UINT8 *out, const UINT8 *in, int xsize, ImagingPalette palette) {
|
p2la(UINT8 *out, const UINT8 *in, int xsize, ImagingPalette palette) {
|
||||||
int x;
|
int x;
|
||||||
/* FIXME: precalculate greyscale palette? */
|
/* FIXME: precalculate grayscale palette? */
|
||||||
for (x = 0; x < xsize; x++, out += 4) {
|
for (x = 0; x < xsize; x++, out += 4) {
|
||||||
const UINT8 *rgba = &palette->palette[*in++ * 4];
|
const UINT8 *rgba = &palette->palette[*in++ * 4];
|
||||||
out[0] = out[1] = out[2] = L24(rgba) >> 16;
|
out[0] = out[1] = out[2] = L24(rgba) >> 16;
|
||||||
|
@ -1081,7 +1081,7 @@ p2la(UINT8 *out, const UINT8 *in, int xsize, ImagingPalette palette) {
|
||||||
static void
|
static void
|
||||||
pa2la(UINT8 *out, const UINT8 *in, int xsize, ImagingPalette palette) {
|
pa2la(UINT8 *out, const UINT8 *in, int xsize, ImagingPalette palette) {
|
||||||
int x;
|
int x;
|
||||||
/* FIXME: precalculate greyscale palette? */
|
/* FIXME: precalculate grayscale palette? */
|
||||||
for (x = 0; x < xsize; x++, in += 4, out += 4) {
|
for (x = 0; x < xsize; x++, in += 4, out += 4) {
|
||||||
out[0] = out[1] = out[2] = L24(&palette->palette[in[0] * 4]) >> 16;
|
out[0] = out[1] = out[2] = L24(&palette->palette[in[0] * 4]) >> 16;
|
||||||
out[3] = in[3];
|
out[3] = in[3];
|
||||||
|
@ -1335,9 +1335,9 @@ topalette(
|
||||||
imOut->palette = ImagingPaletteDuplicate(palette);
|
imOut->palette = ImagingPaletteDuplicate(palette);
|
||||||
|
|
||||||
if (imIn->bands == 1) {
|
if (imIn->bands == 1) {
|
||||||
/* greyscale image */
|
/* grayscale image */
|
||||||
|
|
||||||
/* Greyscale palette: copy data as is */
|
/* Grayscale palette: copy data as is */
|
||||||
ImagingSectionEnter(&cookie);
|
ImagingSectionEnter(&cookie);
|
||||||
for (y = 0; y < imIn->ysize; y++) {
|
for (y = 0; y < imIn->ysize; y++) {
|
||||||
if (alpha) {
|
if (alpha) {
|
||||||
|
|
|
@ -142,9 +142,9 @@ ImagingNewDIB(const char *mode, int xsize, int ysize) {
|
||||||
GetSystemPaletteEntries(dib->dc, 0, 256, pal->palPalEntry);
|
GetSystemPaletteEntries(dib->dc, 0, 256, pal->palPalEntry);
|
||||||
|
|
||||||
if (strcmp(mode, "L") == 0) {
|
if (strcmp(mode, "L") == 0) {
|
||||||
/* Greyscale DIB. Fill all 236 slots with a greyscale ramp
|
/* Grayscale DIB. Fill all 236 slots with a grayscale ramp
|
||||||
* (this is usually overkill on Windows since VGA only offers
|
* (this is usually overkill on Windows since VGA only offers
|
||||||
* 6 bits greyscale resolution). Ignore the slots already
|
* 6 bits grayscale resolution). Ignore the slots already
|
||||||
* allocated by Windows */
|
* allocated by Windows */
|
||||||
|
|
||||||
i = 10;
|
i = 10;
|
||||||
|
@ -160,7 +160,7 @@ ImagingNewDIB(const char *mode, int xsize, int ysize) {
|
||||||
#ifdef CUBE216
|
#ifdef CUBE216
|
||||||
|
|
||||||
/* Colour DIB. Create a 6x6x6 colour cube (216 entries) and
|
/* Colour DIB. Create a 6x6x6 colour cube (216 entries) and
|
||||||
* add 20 extra greylevels for best result with greyscale
|
* add 20 extra graylevels for best result with grayscale
|
||||||
* images. */
|
* images. */
|
||||||
|
|
||||||
i = 10;
|
i = 10;
|
||||||
|
|
|
@ -549,16 +549,16 @@ static struct {
|
||||||
{"1", "1;IR", 1, pack1IR},
|
{"1", "1;IR", 1, pack1IR},
|
||||||
{"1", "L", 8, pack1L},
|
{"1", "L", 8, pack1L},
|
||||||
|
|
||||||
/* greyscale */
|
/* grayscale */
|
||||||
{"L", "L", 8, copy1},
|
{"L", "L", 8, copy1},
|
||||||
{"L", "L;16", 16, packL16},
|
{"L", "L;16", 16, packL16},
|
||||||
{"L", "L;16B", 16, packL16B},
|
{"L", "L;16B", 16, packL16B},
|
||||||
|
|
||||||
/* greyscale w. alpha */
|
/* grayscale w. alpha */
|
||||||
{"LA", "LA", 16, packLA},
|
{"LA", "LA", 16, packLA},
|
||||||
{"LA", "LA;L", 16, packLAL},
|
{"LA", "LA;L", 16, packLAL},
|
||||||
|
|
||||||
/* greyscale w. alpha premultiplied */
|
/* grayscale w. alpha premultiplied */
|
||||||
{"La", "La", 16, packLA},
|
{"La", "La", 16, packLA},
|
||||||
|
|
||||||
/* palette */
|
/* palette */
|
||||||
|
|
|
@ -75,7 +75,7 @@ ImagingPaletteNewBrowser(void) {
|
||||||
}
|
}
|
||||||
palette->size = i;
|
palette->size = i;
|
||||||
|
|
||||||
/* FIXME: add 30-level greyscale wedge here? */
|
/* FIXME: add 30-level grayscale wedge here? */
|
||||||
|
|
||||||
return palette;
|
return palette;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1697,7 +1697,7 @@ ImagingQuantize(Imaging im, int colors, int mode, int kmeans) {
|
||||||
image data? */
|
image data? */
|
||||||
|
|
||||||
if (!strcmp(im->mode, "L")) {
|
if (!strcmp(im->mode, "L")) {
|
||||||
/* greyscale */
|
/* grayscale */
|
||||||
|
|
||||||
/* FIXME: converting a "L" image to "P" with 256 colors
|
/* FIXME: converting a "L" image to "P" with 256 colors
|
||||||
should be done by a simple copy... */
|
should be done by a simple copy... */
|
||||||
|
|
|
@ -80,18 +80,18 @@ ImagingNewPrologueSubtype(const char *mode, int xsize, int ysize, int size) {
|
||||||
im->palette = ImagingPaletteNew("RGB");
|
im->palette = ImagingPaletteNew("RGB");
|
||||||
|
|
||||||
} else if (strcmp(mode, "L") == 0) {
|
} else if (strcmp(mode, "L") == 0) {
|
||||||
/* 8-bit greyscale (luminance) images */
|
/* 8-bit grayscale (luminance) images */
|
||||||
im->bands = im->pixelsize = 1;
|
im->bands = im->pixelsize = 1;
|
||||||
im->linesize = xsize;
|
im->linesize = xsize;
|
||||||
|
|
||||||
} else if (strcmp(mode, "LA") == 0) {
|
} else if (strcmp(mode, "LA") == 0) {
|
||||||
/* 8-bit greyscale (luminance) with alpha */
|
/* 8-bit grayscale (luminance) with alpha */
|
||||||
im->bands = 2;
|
im->bands = 2;
|
||||||
im->pixelsize = 4; /* store in image32 memory */
|
im->pixelsize = 4; /* store in image32 memory */
|
||||||
im->linesize = xsize * 4;
|
im->linesize = xsize * 4;
|
||||||
|
|
||||||
} else if (strcmp(mode, "La") == 0) {
|
} else if (strcmp(mode, "La") == 0) {
|
||||||
/* 8-bit greyscale (luminance) with premultiplied alpha */
|
/* 8-bit grayscale (luminance) with premultiplied alpha */
|
||||||
im->bands = 2;
|
im->bands = 2;
|
||||||
im->pixelsize = 4; /* store in image32 memory */
|
im->pixelsize = 4; /* store in image32 memory */
|
||||||
im->linesize = xsize * 4;
|
im->linesize = xsize * 4;
|
||||||
|
|
|
@ -819,7 +819,7 @@ ImagingUnpackXBGR(UINT8 *_out, const UINT8 *in, int pixels) {
|
||||||
static void
|
static void
|
||||||
unpackRGBALA(UINT8 *_out, const UINT8 *in, int pixels) {
|
unpackRGBALA(UINT8 *_out, const UINT8 *in, int pixels) {
|
||||||
int i;
|
int i;
|
||||||
/* greyscale with alpha */
|
/* grayscale with alpha */
|
||||||
for (i = 0; i < pixels; i++) {
|
for (i = 0; i < pixels; i++) {
|
||||||
UINT32 iv = MAKE_UINT32(in[0], in[0], in[0], in[1]);
|
UINT32 iv = MAKE_UINT32(in[0], in[0], in[0], in[1]);
|
||||||
memcpy(_out, &iv, sizeof(iv));
|
memcpy(_out, &iv, sizeof(iv));
|
||||||
|
@ -831,7 +831,7 @@ unpackRGBALA(UINT8 *_out, const UINT8 *in, int pixels) {
|
||||||
static void
|
static void
|
||||||
unpackRGBALA16B(UINT8 *_out, const UINT8 *in, int pixels) {
|
unpackRGBALA16B(UINT8 *_out, const UINT8 *in, int pixels) {
|
||||||
int i;
|
int i;
|
||||||
/* 16-bit greyscale with alpha, big-endian */
|
/* 16-bit grayscale with alpha, big-endian */
|
||||||
for (i = 0; i < pixels; i++) {
|
for (i = 0; i < pixels; i++) {
|
||||||
UINT32 iv = MAKE_UINT32(in[0], in[0], in[0], in[2]);
|
UINT32 iv = MAKE_UINT32(in[0], in[0], in[0], in[2]);
|
||||||
memcpy(_out, &iv, sizeof(iv));
|
memcpy(_out, &iv, sizeof(iv));
|
||||||
|
@ -1108,7 +1108,7 @@ unpackCMYKI(UINT8 *_out, const UINT8 *in, int pixels) {
|
||||||
/* There are two representations of LAB images for whatever precision:
|
/* There are two representations of LAB images for whatever precision:
|
||||||
L: Uint (in PS, it's 0-100)
|
L: Uint (in PS, it's 0-100)
|
||||||
A: Int (in ps, -128 .. 128, or elsewhere 0..255, with 128 as middle.
|
A: Int (in ps, -128 .. 128, or elsewhere 0..255, with 128 as middle.
|
||||||
Channels in PS display a 0 value as middle grey,
|
Channels in PS display a 0 value as middle gray,
|
||||||
LCMS appears to use 128 as the 0 value for these channels)
|
LCMS appears to use 128 as the 0 value for these channels)
|
||||||
B: Int (as above)
|
B: Int (as above)
|
||||||
|
|
||||||
|
@ -1172,7 +1172,7 @@ unpackI16R_I16(UINT8 *out, const UINT8 *in, int pixels) {
|
||||||
|
|
||||||
static void
|
static void
|
||||||
unpackI12_I16(UINT8 *out, const UINT8 *in, int pixels) {
|
unpackI12_I16(UINT8 *out, const UINT8 *in, int pixels) {
|
||||||
/* Fillorder 1/MSB -> LittleEndian, for 12bit integer greyscale tiffs.
|
/* Fillorder 1/MSB -> LittleEndian, for 12bit integer grayscale tiffs.
|
||||||
|
|
||||||
According to the TIFF spec:
|
According to the TIFF spec:
|
||||||
|
|
||||||
|
@ -1527,7 +1527,7 @@ static struct {
|
||||||
{"1", "1;IR", 1, unpack1IR},
|
{"1", "1;IR", 1, unpack1IR},
|
||||||
{"1", "1;8", 8, unpack18},
|
{"1", "1;8", 8, unpack18},
|
||||||
|
|
||||||
/* greyscale */
|
/* grayscale */
|
||||||
{"L", "L;2", 2, unpackL2},
|
{"L", "L;2", 2, unpackL2},
|
||||||
{"L", "L;2I", 2, unpackL2I},
|
{"L", "L;2I", 2, unpackL2I},
|
||||||
{"L", "L;2R", 2, unpackL2R},
|
{"L", "L;2R", 2, unpackL2R},
|
||||||
|
@ -1544,11 +1544,11 @@ static struct {
|
||||||
{"L", "L;16", 16, unpackL16},
|
{"L", "L;16", 16, unpackL16},
|
||||||
{"L", "L;16B", 16, unpackL16B},
|
{"L", "L;16B", 16, unpackL16B},
|
||||||
|
|
||||||
/* greyscale w. alpha */
|
/* grayscale w. alpha */
|
||||||
{"LA", "LA", 16, unpackLA},
|
{"LA", "LA", 16, unpackLA},
|
||||||
{"LA", "LA;L", 16, unpackLAL},
|
{"LA", "LA;L", 16, unpackLAL},
|
||||||
|
|
||||||
/* greyscale w. alpha premultiplied */
|
/* grayscale w. alpha premultiplied */
|
||||||
{"La", "La", 16, unpackLA},
|
{"La", "La", 16, unpackLA},
|
||||||
|
|
||||||
/* palette */
|
/* palette */
|
||||||
|
|
|
@ -7,7 +7,7 @@ ARCHIVE_SDIR=pillow-depends-main
|
||||||
FREETYPE_VERSION=2.13.2
|
FREETYPE_VERSION=2.13.2
|
||||||
HARFBUZZ_VERSION=8.2.1
|
HARFBUZZ_VERSION=8.2.1
|
||||||
LIBPNG_VERSION=1.6.40
|
LIBPNG_VERSION=1.6.40
|
||||||
JPEGTURBO_VERSION=3.0.0
|
JPEGTURBO_VERSION=3.0.1
|
||||||
OPENJPEG_VERSION=2.5.0
|
OPENJPEG_VERSION=2.5.0
|
||||||
XZ_VERSION=5.4.4
|
XZ_VERSION=5.4.4
|
||||||
TIFF_VERSION=4.6.0
|
TIFF_VERSION=4.6.0
|
||||||
|
|
|
@ -110,9 +110,9 @@ ARCHITECTURES = {
|
||||||
DEPS = {
|
DEPS = {
|
||||||
"libjpeg": {
|
"libjpeg": {
|
||||||
"url": SF_PROJECTS
|
"url": SF_PROJECTS
|
||||||
+ "/libjpeg-turbo/files/3.0.0/libjpeg-turbo-3.0.0.tar.gz/download",
|
+ "/libjpeg-turbo/files/3.0.1/libjpeg-turbo-3.0.1.tar.gz/download",
|
||||||
"filename": "libjpeg-turbo-3.0.0.tar.gz",
|
"filename": "libjpeg-turbo-3.0.1.tar.gz",
|
||||||
"dir": "libjpeg-turbo-3.0.0",
|
"dir": "libjpeg-turbo-3.0.1",
|
||||||
"license": ["README.ijg", "LICENSE.md"],
|
"license": ["README.ijg", "LICENSE.md"],
|
||||||
"license_pattern": (
|
"license_pattern": (
|
||||||
"(LEGAL ISSUES\n============\n\n.+?)\n\nREFERENCES\n=========="
|
"(LEGAL ISSUES\n============\n\n.+?)\n\nREFERENCES\n=========="
|
||||||
|
|