mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-11-11 12:17:14 +03:00
Merge branch 'main' into plainPPM
This commit is contained in:
commit
d20f39d02e
4
.github/workflows/cifuzz.yml
vendored
4
.github/workflows/cifuzz.yml
vendored
|
@ -31,13 +31,13 @@ jobs:
|
||||||
language: python
|
language: python
|
||||||
dry-run: false
|
dry-run: false
|
||||||
- name: Upload New Crash
|
- name: Upload New Crash
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v3
|
||||||
if: failure() && steps.build.outcome == 'success'
|
if: failure() && steps.build.outcome == 'success'
|
||||||
with:
|
with:
|
||||||
name: artifacts
|
name: artifacts
|
||||||
path: ./out/artifacts
|
path: ./out/artifacts
|
||||||
- name: Upload Legacy Crash
|
- name: Upload Legacy Crash
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v3
|
||||||
if: steps.run.outcome == 'success'
|
if: steps.run.outcome == 'success'
|
||||||
with:
|
with:
|
||||||
name: crash
|
name: crash
|
||||||
|
|
4
.github/workflows/lint.yml
vendored
4
.github/workflows/lint.yml
vendored
|
@ -10,7 +10,7 @@ jobs:
|
||||||
name: Lint
|
name: Lint
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: pre-commit cache
|
- name: pre-commit cache
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v2
|
||||||
|
@ -21,7 +21,7 @@ jobs:
|
||||||
lint-pre-commit-
|
lint-pre-commit-
|
||||||
|
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v2
|
uses: actions/setup-python@v3
|
||||||
with:
|
with:
|
||||||
python-version: "3.10"
|
python-version: "3.10"
|
||||||
cache: pip
|
cache: pip
|
||||||
|
|
2
.github/workflows/test-docker.yml
vendored
2
.github/workflows/test-docker.yml
vendored
|
@ -41,7 +41,7 @@ jobs:
|
||||||
name: ${{ matrix.docker }}
|
name: ${{ matrix.docker }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Build system information
|
- name: Build system information
|
||||||
run: python3 .github/workflows/system-info.py
|
run: python3 .github/workflows/system-info.py
|
||||||
|
|
2
.github/workflows/test-mingw.yml
vendored
2
.github/workflows/test-mingw.yml
vendored
|
@ -29,7 +29,7 @@ jobs:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Pillow
|
- name: Checkout Pillow
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Set up shell
|
- name: Set up shell
|
||||||
run: echo "C:\msys64\usr\bin\" >> $env:GITHUB_PATH
|
run: echo "C:\msys64\usr\bin\" >> $env:GITHUB_PATH
|
||||||
|
|
2
.github/workflows/test-valgrind.yml
vendored
2
.github/workflows/test-valgrind.yml
vendored
|
@ -28,7 +28,7 @@ jobs:
|
||||||
name: ${{ matrix.docker }}
|
name: ${{ matrix.docker }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Build system information
|
- name: Build system information
|
||||||
run: python3 .github/workflows/system-info.py
|
run: python3 .github/workflows/system-info.py
|
||||||
|
|
10
.github/workflows/test-windows.yml
vendored
10
.github/workflows/test-windows.yml
vendored
|
@ -23,17 +23,17 @@ jobs:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Pillow
|
- name: Checkout Pillow
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Checkout cached dependencies
|
- name: Checkout cached dependencies
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
repository: python-pillow/pillow-depends
|
repository: python-pillow/pillow-depends
|
||||||
path: winbuild\depends
|
path: winbuild\depends
|
||||||
|
|
||||||
# sets env: pythonLocation
|
# sets env: pythonLocation
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v2
|
uses: actions/setup-python@v3
|
||||||
with:
|
with:
|
||||||
python-version: ${{ matrix.python-version }}
|
python-version: ${{ matrix.python-version }}
|
||||||
architecture: ${{ matrix.architecture }}
|
architecture: ${{ matrix.architecture }}
|
||||||
|
@ -156,7 +156,7 @@ jobs:
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
||||||
- name: Upload errors
|
- name: Upload errors
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v3
|
||||||
if: failure()
|
if: failure()
|
||||||
with:
|
with:
|
||||||
name: errors
|
name: errors
|
||||||
|
@ -182,7 +182,7 @@ jobs:
|
||||||
winbuild\\build\\build_pillow.cmd --disable-imagequant bdist_wheel
|
winbuild\\build\\build_pillow.cmd --disable-imagequant bdist_wheel
|
||||||
shell: cmd
|
shell: cmd
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v2
|
- uses: actions/upload-artifact@v3
|
||||||
if: "github.event_name != 'pull_request'"
|
if: "github.event_name != 'pull_request'"
|
||||||
with:
|
with:
|
||||||
name: ${{ steps.wheel.outputs.dist }}
|
name: ${{ steps.wheel.outputs.dist }}
|
||||||
|
|
6
.github/workflows/test.yml
vendored
6
.github/workflows/test.yml
vendored
|
@ -36,10 +36,10 @@ jobs:
|
||||||
name: ${{ matrix.os }} Python ${{ matrix.python-version }}
|
name: ${{ matrix.os }} Python ${{ matrix.python-version }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Set up Python ${{ matrix.python-version }}
|
- name: Set up Python ${{ matrix.python-version }}
|
||||||
uses: actions/setup-python@v2
|
uses: actions/setup-python@v3
|
||||||
with:
|
with:
|
||||||
python-version: ${{ matrix.python-version }}
|
python-version: ${{ matrix.python-version }}
|
||||||
cache: pip
|
cache: pip
|
||||||
|
@ -84,7 +84,7 @@ jobs:
|
||||||
mkdir -p Tests/errors
|
mkdir -p Tests/errors
|
||||||
|
|
||||||
- name: Upload errors
|
- name: Upload errors
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v3
|
||||||
if: failure()
|
if: failure()
|
||||||
with:
|
with:
|
||||||
name: errors
|
name: errors
|
||||||
|
|
2
.github/workflows/tidelift.yml
vendored
2
.github/workflows/tidelift.yml
vendored
|
@ -17,7 +17,7 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
- name: Scan
|
- name: Scan
|
||||||
uses: tidelift/alignment-action@main
|
uses: tidelift/alignment-action@main
|
||||||
env:
|
env:
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
repos:
|
repos:
|
||||||
- repo: https://github.com/psf/black
|
- repo: https://github.com/psf/black
|
||||||
rev: f1d4e742c91dd5179d742b0db9293c4472b765f8 # frozen: 21.12b0
|
rev: fc0be6eb1e2a96091e6f64009ee5e9081bf8b6c6 # frozen: 22.1.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: black
|
- id: black
|
||||||
args: ["--target-version", "py37"]
|
args: ["--target-version", "py37"]
|
||||||
|
@ -19,7 +19,7 @@ repos:
|
||||||
- id: yesqa
|
- id: yesqa
|
||||||
|
|
||||||
- repo: https://github.com/Lucas-C/pre-commit-hooks
|
- repo: https://github.com/Lucas-C/pre-commit-hooks
|
||||||
rev: 3592548bbd98528887eeed63486cf6c9bae00b98 # frozen: v1.1.10
|
rev: ca52c4245639abd55c970e6bbbca95cab3de22d8 # frozen: v1.1.13
|
||||||
hooks:
|
hooks:
|
||||||
- id: remove-tabs
|
- id: remove-tabs
|
||||||
exclude: (Makefile$|\.bat$|\.cmake$|\.eps$|\.fits$|\.opt$)
|
exclude: (Makefile$|\.bat$|\.cmake$|\.eps$|\.fits$|\.opt$)
|
||||||
|
|
|
@ -4,5 +4,5 @@ import sys
|
||||||
|
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
|
|
||||||
if sys.maxsize < 2 ** 32:
|
if sys.maxsize < 2**32:
|
||||||
im = Image.new("L", (999999, 999999), 0)
|
im = Image.new("L", (999999, 999999), 0)
|
||||||
|
|
|
@ -23,7 +23,7 @@ YDIM = 32769
|
||||||
XDIM = 48000
|
XDIM = 48000
|
||||||
|
|
||||||
|
|
||||||
pytestmark = pytest.mark.skipif(sys.maxsize <= 2 ** 32, reason="requires 64-bit system")
|
pytestmark = pytest.mark.skipif(sys.maxsize <= 2**32, reason="requires 64-bit system")
|
||||||
|
|
||||||
|
|
||||||
def _write_png(tmp_path, xdim, ydim):
|
def _write_png(tmp_path, xdim, ydim):
|
||||||
|
|
|
@ -19,7 +19,7 @@ YDIM = 32769
|
||||||
XDIM = 48000
|
XDIM = 48000
|
||||||
|
|
||||||
|
|
||||||
pytestmark = pytest.mark.skipif(sys.maxsize <= 2 ** 32, reason="requires 64-bit system")
|
pytestmark = pytest.mark.skipif(sys.maxsize <= 2**32, reason="requires 64-bit system")
|
||||||
|
|
||||||
|
|
||||||
def _write_png(tmp_path, xdim, ydim):
|
def _write_png(tmp_path, xdim, ydim):
|
||||||
|
|
|
@ -110,9 +110,9 @@ class TestCoreMemory:
|
||||||
|
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
Image.core.set_blocks_max(-1)
|
Image.core.set_blocks_max(-1)
|
||||||
if sys.maxsize < 2 ** 32:
|
if sys.maxsize < 2**32:
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
Image.core.set_blocks_max(2 ** 29)
|
Image.core.set_blocks_max(2**29)
|
||||||
|
|
||||||
@pytest.mark.skipif(is_pypy(), reason="Images not collected")
|
@pytest.mark.skipif(is_pypy(), reason="Images not collected")
|
||||||
def test_set_blocks_max_stats(self):
|
def test_set_blocks_max_stats(self):
|
||||||
|
|
|
@ -196,6 +196,13 @@ def test__accept_false():
|
||||||
assert not output
|
assert not output
|
||||||
|
|
||||||
|
|
||||||
|
def test_invalid_file():
|
||||||
|
invalid_file = "Tests/images/flower.jpg"
|
||||||
|
|
||||||
|
with pytest.raises(SyntaxError):
|
||||||
|
DdsImagePlugin.DdsImageFile(invalid_file)
|
||||||
|
|
||||||
|
|
||||||
def test_short_header():
|
def test_short_header():
|
||||||
"""Check a short header"""
|
"""Check a short header"""
|
||||||
with open(TEST_FILE_DXT5, "rb") as f:
|
with open(TEST_FILE_DXT5, "rb") as f:
|
||||||
|
|
|
@ -16,6 +16,13 @@ def test_load_dxt1():
|
||||||
assert_image_similar(im, target.convert("RGBA"), 15)
|
assert_image_similar(im, target.convert("RGBA"), 15)
|
||||||
|
|
||||||
|
|
||||||
|
def test_invalid_file():
|
||||||
|
invalid_file = "Tests/images/flower.jpg"
|
||||||
|
|
||||||
|
with pytest.raises(SyntaxError):
|
||||||
|
FtexImagePlugin.FtexImageFile(invalid_file)
|
||||||
|
|
||||||
|
|
||||||
def test_constants_deprecation():
|
def test_constants_deprecation():
|
||||||
for enum, prefix in {
|
for enum, prefix in {
|
||||||
FtexImagePlugin.Format: "FORMAT_",
|
FtexImagePlugin.Format: "FORMAT_",
|
||||||
|
|
|
@ -218,7 +218,7 @@ class TestFileLibTiff(LibTiffTestCase):
|
||||||
values = {
|
values = {
|
||||||
2: "test",
|
2: "test",
|
||||||
3: 1,
|
3: 1,
|
||||||
4: 2 ** 20,
|
4: 2**20,
|
||||||
5: TiffImagePlugin.IFDRational(100, 1),
|
5: TiffImagePlugin.IFDRational(100, 1),
|
||||||
12: 1.05,
|
12: 1.05,
|
||||||
}
|
}
|
||||||
|
@ -1019,7 +1019,7 @@ class TestFileLibTiff(LibTiffTestCase):
|
||||||
im = hopper("RGB").resize((256, 256))
|
im = hopper("RGB").resize((256, 256))
|
||||||
out = str(tmp_path / "temp.tif")
|
out = str(tmp_path / "temp.tif")
|
||||||
|
|
||||||
TiffImagePlugin.STRIP_SIZE = 2 ** 18
|
TiffImagePlugin.STRIP_SIZE = 2**18
|
||||||
try:
|
try:
|
||||||
|
|
||||||
im.save(out, compression="tiff_adobe_deflate")
|
im.save(out, compression="tiff_adobe_deflate")
|
||||||
|
|
|
@ -258,7 +258,7 @@ def test_ifd_unsigned_rational(tmp_path):
|
||||||
im = hopper()
|
im = hopper()
|
||||||
info = TiffImagePlugin.ImageFileDirectory_v2()
|
info = TiffImagePlugin.ImageFileDirectory_v2()
|
||||||
|
|
||||||
max_long = 2 ** 32 - 1
|
max_long = 2**32 - 1
|
||||||
|
|
||||||
# 4 bytes unsigned long
|
# 4 bytes unsigned long
|
||||||
numerator = max_long
|
numerator = max_long
|
||||||
|
@ -290,8 +290,8 @@ def test_ifd_signed_rational(tmp_path):
|
||||||
info = TiffImagePlugin.ImageFileDirectory_v2()
|
info = TiffImagePlugin.ImageFileDirectory_v2()
|
||||||
|
|
||||||
# pair of 4 byte signed longs
|
# pair of 4 byte signed longs
|
||||||
numerator = 2 ** 31 - 1
|
numerator = 2**31 - 1
|
||||||
denominator = -(2 ** 31)
|
denominator = -(2**31)
|
||||||
|
|
||||||
info[37380] = TiffImagePlugin.IFDRational(numerator, denominator)
|
info[37380] = TiffImagePlugin.IFDRational(numerator, denominator)
|
||||||
|
|
||||||
|
@ -302,8 +302,8 @@ def test_ifd_signed_rational(tmp_path):
|
||||||
assert numerator == reloaded.tag_v2[37380].numerator
|
assert numerator == reloaded.tag_v2[37380].numerator
|
||||||
assert denominator == reloaded.tag_v2[37380].denominator
|
assert denominator == reloaded.tag_v2[37380].denominator
|
||||||
|
|
||||||
numerator = -(2 ** 31)
|
numerator = -(2**31)
|
||||||
denominator = 2 ** 31 - 1
|
denominator = 2**31 - 1
|
||||||
|
|
||||||
info[37380] = TiffImagePlugin.IFDRational(numerator, denominator)
|
info[37380] = TiffImagePlugin.IFDRational(numerator, denominator)
|
||||||
|
|
||||||
|
@ -315,7 +315,7 @@ def test_ifd_signed_rational(tmp_path):
|
||||||
assert denominator == reloaded.tag_v2[37380].denominator
|
assert denominator == reloaded.tag_v2[37380].denominator
|
||||||
|
|
||||||
# out of bounds of 4 byte signed long
|
# out of bounds of 4 byte signed long
|
||||||
numerator = -(2 ** 31) - 1
|
numerator = -(2**31) - 1
|
||||||
denominator = 1
|
denominator = 1
|
||||||
|
|
||||||
info[37380] = TiffImagePlugin.IFDRational(numerator, denominator)
|
info[37380] = TiffImagePlugin.IFDRational(numerator, denominator)
|
||||||
|
@ -324,7 +324,7 @@ def test_ifd_signed_rational(tmp_path):
|
||||||
im.save(out, tiffinfo=info, compression="raw")
|
im.save(out, tiffinfo=info, compression="raw")
|
||||||
|
|
||||||
with Image.open(out) as reloaded:
|
with Image.open(out) as reloaded:
|
||||||
assert 2 ** 31 - 1 == reloaded.tag_v2[37380].numerator
|
assert 2**31 - 1 == reloaded.tag_v2[37380].numerator
|
||||||
assert -1 == reloaded.tag_v2[37380].denominator
|
assert -1 == reloaded.tag_v2[37380].denominator
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -128,7 +128,7 @@ class TestFileWebp:
|
||||||
|
|
||||||
self._roundtrip(tmp_path, "P", 50.0)
|
self._roundtrip(tmp_path, "P", 50.0)
|
||||||
|
|
||||||
@pytest.mark.skipif(sys.maxsize <= 2 ** 32, reason="Requires 64-bit system")
|
@pytest.mark.skipif(sys.maxsize <= 2**32, reason="Requires 64-bit system")
|
||||||
def test_write_encoding_error_message(self, tmp_path):
|
def test_write_encoding_error_message(self, tmp_path):
|
||||||
temp_file = str(tmp_path / "temp.webp")
|
temp_file = str(tmp_path / "temp.webp")
|
||||||
im = Image.new("RGB", (15000, 15000))
|
im = Image.new("RGB", (15000, 15000))
|
||||||
|
|
|
@ -2,7 +2,7 @@ from io import BytesIO
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from PIL import Image
|
from PIL import Image, XbmImagePlugin
|
||||||
|
|
||||||
from .helper import hopper
|
from .helper import hopper
|
||||||
|
|
||||||
|
@ -63,6 +63,13 @@ def test_open_filename_with_underscore():
|
||||||
assert im.size == (128, 128)
|
assert im.size == (128, 128)
|
||||||
|
|
||||||
|
|
||||||
|
def test_invalid_file():
|
||||||
|
invalid_file = "Tests/images/flower.jpg"
|
||||||
|
|
||||||
|
with pytest.raises(SyntaxError):
|
||||||
|
XbmImagePlugin.XbmImageFile(invalid_file)
|
||||||
|
|
||||||
|
|
||||||
def test_save_wrong_mode(tmp_path):
|
def test_save_wrong_mode(tmp_path):
|
||||||
im = hopper()
|
im = hopper()
|
||||||
out = str(tmp_path / "temp.xbm")
|
out = str(tmp_path / "temp.xbm")
|
||||||
|
|
|
@ -205,10 +205,10 @@ class TestImageGetPixel(AccessTest):
|
||||||
# see https://github.com/python-pillow/Pillow/issues/452
|
# see https://github.com/python-pillow/Pillow/issues/452
|
||||||
# pixelaccess is using signed int* instead of uint*
|
# pixelaccess is using signed int* instead of uint*
|
||||||
for mode in ("I;16", "I;16B"):
|
for mode in ("I;16", "I;16B"):
|
||||||
self.check(mode, 2 ** 15 - 1)
|
self.check(mode, 2**15 - 1)
|
||||||
self.check(mode, 2 ** 15)
|
self.check(mode, 2**15)
|
||||||
self.check(mode, 2 ** 15 + 1)
|
self.check(mode, 2**15 + 1)
|
||||||
self.check(mode, 2 ** 16 - 1)
|
self.check(mode, 2**16 - 1)
|
||||||
|
|
||||||
def test_p_putpixel_rgb_rgba(self):
|
def test_p_putpixel_rgb_rgba(self):
|
||||||
for color in [(255, 0, 0), (255, 0, 0, 255)]:
|
for color in [(255, 0, 0), (255, 0, 0, 255)]:
|
||||||
|
@ -386,7 +386,7 @@ class TestImagePutPixelError(AccessTest):
|
||||||
def test_putpixel_overflow_error(self, mode):
|
def test_putpixel_overflow_error(self, mode):
|
||||||
im = hopper(mode)
|
im = hopper(mode)
|
||||||
with pytest.raises(OverflowError):
|
with pytest.raises(OverflowError):
|
||||||
im.putpixel((0, 0), 2 ** 80)
|
im.putpixel((0, 0), 2**80)
|
||||||
|
|
||||||
def test_putpixel_unrecognized_mode(self):
|
def test_putpixel_unrecognized_mode(self):
|
||||||
im = hopper("BGR;15")
|
im = hopper("BGR;15")
|
||||||
|
|
|
@ -38,7 +38,7 @@ def test_long_integers():
|
||||||
assert put(0xFFFFFFFF) == (255, 255, 255, 255)
|
assert put(0xFFFFFFFF) == (255, 255, 255, 255)
|
||||||
assert put(-1) == (255, 255, 255, 255)
|
assert put(-1) == (255, 255, 255, 255)
|
||||||
assert put(-1) == (255, 255, 255, 255)
|
assert put(-1) == (255, 255, 255, 255)
|
||||||
if sys.maxsize > 2 ** 32:
|
if sys.maxsize > 2**32:
|
||||||
assert put(sys.maxsize) == (255, 255, 255, 255)
|
assert put(sys.maxsize) == (255, 255, 255, 255)
|
||||||
else:
|
else:
|
||||||
assert put(sys.maxsize) == (255, 255, 255, 127)
|
assert put(sys.maxsize) == (255, 255, 255, 127)
|
||||||
|
|
|
@ -303,7 +303,7 @@ def test_extended_information():
|
||||||
def assert_truncated_tuple_equal(tup1, tup2, digits=10):
|
def assert_truncated_tuple_equal(tup1, tup2, digits=10):
|
||||||
# Helper function to reduce precision of tuples of floats
|
# Helper function to reduce precision of tuples of floats
|
||||||
# recursively and then check equality.
|
# recursively and then check equality.
|
||||||
power = 10 ** digits
|
power = 10**digits
|
||||||
|
|
||||||
def truncate_tuple(tuple_or_float):
|
def truncate_tuple(tuple_or_float):
|
||||||
return tuple(
|
return tuple(
|
||||||
|
|
|
@ -32,10 +32,10 @@ def test_rgb():
|
||||||
|
|
||||||
def checkrgb(r, g, b):
|
def checkrgb(r, g, b):
|
||||||
val = ImageQt.rgb(r, g, b)
|
val = ImageQt.rgb(r, g, b)
|
||||||
val = val % 2 ** 24 # drop the alpha
|
val = val % 2**24 # drop the alpha
|
||||||
assert val >> 16 == r
|
assert val >> 16 == r
|
||||||
assert ((val >> 8) % 2 ** 8) == g
|
assert ((val >> 8) % 2**8) == g
|
||||||
assert val % 2 ** 8 == b
|
assert val % 2**8 == b
|
||||||
|
|
||||||
checkrgb(0, 0, 0)
|
checkrgb(0, 0, 0)
|
||||||
checkrgb(255, 0, 0)
|
checkrgb(255, 0, 0)
|
||||||
|
|
|
@ -51,8 +51,8 @@ def test_constant():
|
||||||
st = ImageStat.Stat(im)
|
st = ImageStat.Stat(im)
|
||||||
|
|
||||||
assert st.extrema[0] == (128, 128)
|
assert st.extrema[0] == (128, 128)
|
||||||
assert st.sum[0] == 128 ** 3
|
assert st.sum[0] == 128**3
|
||||||
assert st.sum2[0] == 128 ** 4
|
assert st.sum2[0] == 128**4
|
||||||
assert st.mean[0] == 128
|
assert st.mean[0] == 128
|
||||||
assert st.median[0] == 128
|
assert st.median[0] == 128
|
||||||
assert st.rms[0] == 128
|
assert st.rms[0] == 128
|
||||||
|
|
|
@ -36,7 +36,7 @@ def test_tobytes():
|
||||||
Image.MAX_IMAGE_PIXELS = max_pixels
|
Image.MAX_IMAGE_PIXELS = max_pixels
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skipif(sys.maxsize <= 2 ** 32, reason="Requires 64-bit system")
|
@pytest.mark.skipif(sys.maxsize <= 2**32, reason="Requires 64-bit system")
|
||||||
def test_ysize():
|
def test_ysize():
|
||||||
numpy = pytest.importorskip("numpy", reason="NumPy not installed")
|
numpy = pytest.importorskip("numpy", reason="NumPy not installed")
|
||||||
|
|
||||||
|
|
|
@ -115,6 +115,6 @@ def test_pdf_repr():
|
||||||
assert pdf_repr(True) == b"true"
|
assert pdf_repr(True) == b"true"
|
||||||
assert pdf_repr(False) == b"false"
|
assert pdf_repr(False) == b"false"
|
||||||
assert pdf_repr(None) == b"null"
|
assert pdf_repr(None) == b"null"
|
||||||
assert pdf_repr(b"a)/b\\(c") == br"(a\)/b\\\(c)"
|
assert pdf_repr(b"a)/b\\(c") == rb"(a\)/b\\\(c)"
|
||||||
assert pdf_repr([123, True, {"a": PdfName(b"b")}]) == b"[ 123 true <<\n/a /b\n>> ]"
|
assert pdf_repr([123, True, {"a": PdfName(b"b")}]) == b"[ 123 true <<\n/a /b\n>> ]"
|
||||||
assert pdf_repr(PdfBinary(b"\x90\x1F\xA0")) == b"<901FA0>"
|
assert pdf_repr(PdfBinary(b"\x90\x1F\xA0")) == b"<901FA0>"
|
||||||
|
|
|
@ -210,7 +210,9 @@ class DdsImageFile(ImageFile.ImageFile):
|
||||||
format_description = "DirectDraw Surface"
|
format_description = "DirectDraw Surface"
|
||||||
|
|
||||||
def _open(self):
|
def _open(self):
|
||||||
magic, header_size = struct.unpack("<II", self.fp.read(8))
|
if not _accept(self.fp.read(4)):
|
||||||
|
raise SyntaxError("not a DDS file")
|
||||||
|
(header_size,) = struct.unpack("<I", self.fp.read(4))
|
||||||
if header_size != 124:
|
if header_size != 124:
|
||||||
raise OSError(f"Unsupported header size {repr(header_size)}")
|
raise OSError(f"Unsupported header size {repr(header_size)}")
|
||||||
header_bytes = self.fp.read(header_size - 4)
|
header_bytes = self.fp.read(header_size - 4)
|
||||||
|
|
|
@ -14,6 +14,16 @@ for a region of an image.
|
||||||
statistics. You can also pass in a previously calculated histogram.
|
statistics. You can also pass in a previously calculated histogram.
|
||||||
|
|
||||||
:param image: A PIL image, or a precalculated histogram.
|
:param image: A PIL image, or a precalculated histogram.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
For a PIL image, calculations rely on the
|
||||||
|
:py:meth:`~PIL.Image.Image.histogram` method. The pixel counts are
|
||||||
|
grouped into 256 bins, even if the image has more than 8 bits per
|
||||||
|
channel. So ``I`` and ``F`` mode images have a maximum ``mean``,
|
||||||
|
``median`` and ``rms`` of 255, and cannot have an ``extrema`` maximum
|
||||||
|
of more than 255.
|
||||||
|
|
||||||
:param mask: An optional mask.
|
:param mask: An optional mask.
|
||||||
|
|
||||||
.. py:attribute:: extrema
|
.. py:attribute:: extrema
|
||||||
|
|
2
setup.py
2
setup.py
|
@ -167,7 +167,7 @@ def _find_library_dirs_ldconfig():
|
||||||
# Assuming GLIBC's ldconfig (with option -p)
|
# Assuming GLIBC's ldconfig (with option -p)
|
||||||
# Alpine Linux uses musl that can't print cache
|
# Alpine Linux uses musl that can't print cache
|
||||||
args = ["/sbin/ldconfig", "-p"]
|
args = ["/sbin/ldconfig", "-p"]
|
||||||
expr = fr".*\({abi_type}.*\) => (.*)"
|
expr = rf".*\({abi_type}.*\) => (.*)"
|
||||||
env = dict(os.environ)
|
env = dict(os.environ)
|
||||||
env["LC_ALL"] = "C"
|
env["LC_ALL"] = "C"
|
||||||
env["LANG"] = "C"
|
env["LANG"] = "C"
|
||||||
|
|
|
@ -102,7 +102,7 @@ class BmpImageFile(ImageFile.ImageFile):
|
||||||
file_info["height"] = (
|
file_info["height"] = (
|
||||||
i32(header_data, 4)
|
i32(header_data, 4)
|
||||||
if not file_info["y_flip"]
|
if not file_info["y_flip"]
|
||||||
else 2 ** 32 - i32(header_data, 4)
|
else 2**32 - i32(header_data, 4)
|
||||||
)
|
)
|
||||||
file_info["planes"] = i16(header_data, 8)
|
file_info["planes"] = i16(header_data, 8)
|
||||||
file_info["bits"] = i16(header_data, 10)
|
file_info["bits"] = i16(header_data, 10)
|
||||||
|
@ -322,7 +322,7 @@ def _save(im, fp, filename, bitmap_header=True):
|
||||||
if bitmap_header:
|
if bitmap_header:
|
||||||
offset = 14 + header + colors * 4
|
offset = 14 + header + colors * 4
|
||||||
file_size = offset + image
|
file_size = offset + image
|
||||||
if file_size > 2 ** 32 - 1:
|
if file_size > 2**32 - 1:
|
||||||
raise ValueError("File size is too large for the BMP format")
|
raise ValueError("File size is too large for the BMP format")
|
||||||
fp.write(
|
fp.write(
|
||||||
b"BM" # file type (magic)
|
b"BM" # file type (magic)
|
||||||
|
|
|
@ -111,7 +111,9 @@ class DdsImageFile(ImageFile.ImageFile):
|
||||||
format_description = "DirectDraw Surface"
|
format_description = "DirectDraw Surface"
|
||||||
|
|
||||||
def _open(self):
|
def _open(self):
|
||||||
magic, header_size = struct.unpack("<II", self.fp.read(8))
|
if not _accept(self.fp.read(4)):
|
||||||
|
raise SyntaxError("not a DDS file")
|
||||||
|
(header_size,) = struct.unpack("<I", self.fp.read(4))
|
||||||
if header_size != 124:
|
if header_size != 124:
|
||||||
raise OSError(f"Unsupported header size {repr(header_size)}")
|
raise OSError(f"Unsupported header size {repr(header_size)}")
|
||||||
header_bytes = self.fp.read(header_size - 4)
|
header_bytes = self.fp.read(header_size - 4)
|
||||||
|
|
|
@ -26,7 +26,11 @@ from ._binary import o8
|
||||||
|
|
||||||
|
|
||||||
def _accept(prefix):
|
def _accept(prefix):
|
||||||
return len(prefix) >= 6 and i16(prefix, 4) in [0xAF11, 0xAF12]
|
return (
|
||||||
|
len(prefix) >= 6
|
||||||
|
and i16(prefix, 4) in [0xAF11, 0xAF12]
|
||||||
|
and i16(prefix, 14) in [0, 3] # flags
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
##
|
##
|
||||||
|
@ -44,11 +48,7 @@ class FliImageFile(ImageFile.ImageFile):
|
||||||
|
|
||||||
# HEAD
|
# HEAD
|
||||||
s = self.fp.read(128)
|
s = self.fp.read(128)
|
||||||
if not (
|
if not (_accept(s) and s[20:22] == b"\x00\x00"):
|
||||||
_accept(s)
|
|
||||||
and i16(s, 14) in [0, 3] # flags
|
|
||||||
and s[20:22] == b"\x00\x00" # reserved
|
|
||||||
):
|
|
||||||
raise SyntaxError("not an FLI/FLC file")
|
raise SyntaxError("not an FLI/FLC file")
|
||||||
|
|
||||||
# frames
|
# frames
|
||||||
|
|
|
@ -94,7 +94,8 @@ class FtexImageFile(ImageFile.ImageFile):
|
||||||
format_description = "Texture File Format (IW2:EOC)"
|
format_description = "Texture File Format (IW2:EOC)"
|
||||||
|
|
||||||
def _open(self):
|
def _open(self):
|
||||||
struct.unpack("<I", self.fp.read(4)) # magic
|
if not _accept(self.fp.read(4)):
|
||||||
|
raise SyntaxError("not an FTEX file")
|
||||||
struct.unpack("<i", self.fp.read(4)) # version
|
struct.unpack("<i", self.fp.read(4)) # version
|
||||||
self._size = struct.unpack("<2i", self.fp.read(8))
|
self._size = struct.unpack("<2i", self.fp.read(8))
|
||||||
mipmap_count, format_count = struct.unpack("<2i", self.fp.read(8))
|
mipmap_count, format_count = struct.unpack("<2i", self.fp.read(8))
|
||||||
|
|
|
@ -43,9 +43,9 @@ class GbrImageFile(ImageFile.ImageFile):
|
||||||
|
|
||||||
def _open(self):
|
def _open(self):
|
||||||
header_size = i32(self.fp.read(4))
|
header_size = i32(self.fp.read(4))
|
||||||
version = i32(self.fp.read(4))
|
|
||||||
if header_size < 20:
|
if header_size < 20:
|
||||||
raise SyntaxError("not a GIMP brush")
|
raise SyntaxError("not a GIMP brush")
|
||||||
|
version = i32(self.fp.read(4))
|
||||||
if version not in (1, 2):
|
if version not in (1, 2):
|
||||||
raise SyntaxError(f"Unsupported GIMP brush version: {version}")
|
raise SyntaxError(f"Unsupported GIMP brush version: {version}")
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ class GimpPaletteFile:
|
||||||
break
|
break
|
||||||
|
|
||||||
# skip fields and comment lines
|
# skip fields and comment lines
|
||||||
if re.match(br"\w+:|#", s):
|
if re.match(rb"\w+:|#", s):
|
||||||
continue
|
continue
|
||||||
if len(s) > 100:
|
if len(s) > 100:
|
||||||
raise SyntaxError("bad palette file")
|
raise SyntaxError("bad palette file")
|
||||||
|
|
|
@ -167,7 +167,7 @@ class IcnsFile:
|
||||||
self.dct = dct = {}
|
self.dct = dct = {}
|
||||||
self.fobj = fobj
|
self.fobj = fobj
|
||||||
sig, filesize = nextheader(fobj)
|
sig, filesize = nextheader(fobj)
|
||||||
if sig != MAGIC:
|
if not _accept(sig):
|
||||||
raise SyntaxError("not an icns file")
|
raise SyntaxError("not an icns file")
|
||||||
i = HEADERSIZE
|
i = HEADERSIZE
|
||||||
while i < filesize:
|
while i < filesize:
|
||||||
|
|
|
@ -100,7 +100,7 @@ for i in range(2, 33):
|
||||||
# --------------------------------------------------------------------
|
# --------------------------------------------------------------------
|
||||||
# Read IM directory
|
# Read IM directory
|
||||||
|
|
||||||
split = re.compile(br"^([A-Za-z][^:]*):[ \t]*(.*)[ \t]*$")
|
split = re.compile(rb"^([A-Za-z][^:]*):[ \t]*(.*)[ \t]*$")
|
||||||
|
|
||||||
|
|
||||||
def number(s):
|
def number(s):
|
||||||
|
|
|
@ -1492,11 +1492,12 @@ class Image:
|
||||||
|
|
||||||
def histogram(self, mask=None, extrema=None):
|
def histogram(self, mask=None, extrema=None):
|
||||||
"""
|
"""
|
||||||
Returns a histogram for the image. The histogram is returned as
|
Returns a histogram for the image. The histogram is returned as a
|
||||||
a list of pixel counts, one for each pixel value in the source
|
list of pixel counts, one for each pixel value in the source
|
||||||
image. If the image has more than one band, the histograms for
|
image. Counts are grouped into 256 bins for each band, even if
|
||||||
all bands are concatenated (for example, the histogram for an
|
the image has more than 8 bits per band. If the image has more
|
||||||
"RGB" image contains 768 values).
|
than one band, the histograms for all bands are concatenated (for
|
||||||
|
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 greyscale ("L") image
|
||||||
by this method.
|
by this method.
|
||||||
|
|
|
@ -91,7 +91,7 @@ class Stat:
|
||||||
for i in range(0, len(self.h), 256):
|
for i in range(0, len(self.h), 256):
|
||||||
sum2 = 0.0
|
sum2 = 0.0
|
||||||
for j in range(256):
|
for j in range(256):
|
||||||
sum2 += (j ** 2) * float(self.h[i + j])
|
sum2 += (j**2) * float(self.h[i + j])
|
||||||
v.append(sum2)
|
v.append(sum2)
|
||||||
return v
|
return v
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ from . import Image, ImageFile
|
||||||
#
|
#
|
||||||
# --------------------------------------------------------------------
|
# --------------------------------------------------------------------
|
||||||
|
|
||||||
field = re.compile(br"([a-z]*) ([^ \r\n]*)")
|
field = re.compile(rb"([a-z]*) ([^ \r\n]*)")
|
||||||
|
|
||||||
|
|
||||||
##
|
##
|
||||||
|
|
|
@ -132,7 +132,7 @@ def _res_to_dpi(num, denom, exp):
|
||||||
calculated as (num / denom) * 10^exp and stored in dots per meter,
|
calculated as (num / denom) * 10^exp and stored in dots per meter,
|
||||||
to floating-point dots per inch."""
|
to floating-point dots per inch."""
|
||||||
if denom != 0:
|
if denom != 0:
|
||||||
return (254 * num * (10 ** exp)) / (10000 * denom)
|
return (254 * num * (10**exp)) / (10000 * denom)
|
||||||
|
|
||||||
|
|
||||||
def _parse_jp2_header(fp):
|
def _parse_jp2_header(fp):
|
||||||
|
|
|
@ -576,42 +576,42 @@ class PdfParser:
|
||||||
self.xref_table[reference.object_id] = (offset, 0)
|
self.xref_table[reference.object_id] = (offset, 0)
|
||||||
return reference
|
return reference
|
||||||
|
|
||||||
delimiter = br"[][()<>{}/%]"
|
delimiter = rb"[][()<>{}/%]"
|
||||||
delimiter_or_ws = br"[][()<>{}/%\000\011\012\014\015\040]"
|
delimiter_or_ws = rb"[][()<>{}/%\000\011\012\014\015\040]"
|
||||||
whitespace = br"[\000\011\012\014\015\040]"
|
whitespace = rb"[\000\011\012\014\015\040]"
|
||||||
whitespace_or_hex = br"[\000\011\012\014\015\0400-9a-fA-F]"
|
whitespace_or_hex = rb"[\000\011\012\014\015\0400-9a-fA-F]"
|
||||||
whitespace_optional = whitespace + b"*"
|
whitespace_optional = whitespace + b"*"
|
||||||
whitespace_mandatory = whitespace + b"+"
|
whitespace_mandatory = whitespace + b"+"
|
||||||
# No "\012" aka "\n" or "\015" aka "\r":
|
# No "\012" aka "\n" or "\015" aka "\r":
|
||||||
whitespace_optional_no_nl = br"[\000\011\014\040]*"
|
whitespace_optional_no_nl = rb"[\000\011\014\040]*"
|
||||||
newline_only = br"[\r\n]+"
|
newline_only = rb"[\r\n]+"
|
||||||
newline = whitespace_optional_no_nl + newline_only + whitespace_optional_no_nl
|
newline = whitespace_optional_no_nl + newline_only + whitespace_optional_no_nl
|
||||||
re_trailer_end = re.compile(
|
re_trailer_end = re.compile(
|
||||||
whitespace_mandatory
|
whitespace_mandatory
|
||||||
+ br"trailer"
|
+ rb"trailer"
|
||||||
+ whitespace_optional
|
+ whitespace_optional
|
||||||
+ br"\<\<(.*\>\>)"
|
+ rb"\<\<(.*\>\>)"
|
||||||
+ newline
|
+ newline
|
||||||
+ br"startxref"
|
+ rb"startxref"
|
||||||
+ newline
|
+ newline
|
||||||
+ br"([0-9]+)"
|
+ rb"([0-9]+)"
|
||||||
+ newline
|
+ newline
|
||||||
+ br"%%EOF"
|
+ rb"%%EOF"
|
||||||
+ whitespace_optional
|
+ whitespace_optional
|
||||||
+ br"$",
|
+ rb"$",
|
||||||
re.DOTALL,
|
re.DOTALL,
|
||||||
)
|
)
|
||||||
re_trailer_prev = re.compile(
|
re_trailer_prev = re.compile(
|
||||||
whitespace_optional
|
whitespace_optional
|
||||||
+ br"trailer"
|
+ rb"trailer"
|
||||||
+ whitespace_optional
|
+ whitespace_optional
|
||||||
+ br"\<\<(.*?\>\>)"
|
+ rb"\<\<(.*?\>\>)"
|
||||||
+ newline
|
+ newline
|
||||||
+ br"startxref"
|
+ rb"startxref"
|
||||||
+ newline
|
+ newline
|
||||||
+ br"([0-9]+)"
|
+ rb"([0-9]+)"
|
||||||
+ newline
|
+ newline
|
||||||
+ br"%%EOF"
|
+ rb"%%EOF"
|
||||||
+ whitespace_optional,
|
+ whitespace_optional,
|
||||||
re.DOTALL,
|
re.DOTALL,
|
||||||
)
|
)
|
||||||
|
@ -655,12 +655,12 @@ class PdfParser:
|
||||||
re_whitespace_optional = re.compile(whitespace_optional)
|
re_whitespace_optional = re.compile(whitespace_optional)
|
||||||
re_name = re.compile(
|
re_name = re.compile(
|
||||||
whitespace_optional
|
whitespace_optional
|
||||||
+ br"/([!-$&'*-.0-;=?-Z\\^-z|~]+)(?="
|
+ rb"/([!-$&'*-.0-;=?-Z\\^-z|~]+)(?="
|
||||||
+ delimiter_or_ws
|
+ delimiter_or_ws
|
||||||
+ br")"
|
+ rb")"
|
||||||
)
|
)
|
||||||
re_dict_start = re.compile(whitespace_optional + br"\<\<")
|
re_dict_start = re.compile(whitespace_optional + rb"\<\<")
|
||||||
re_dict_end = re.compile(whitespace_optional + br"\>\>" + whitespace_optional)
|
re_dict_end = re.compile(whitespace_optional + rb"\>\>" + whitespace_optional)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def interpret_trailer(cls, trailer_data):
|
def interpret_trailer(cls, trailer_data):
|
||||||
|
@ -689,7 +689,7 @@ class PdfParser:
|
||||||
)
|
)
|
||||||
return trailer
|
return trailer
|
||||||
|
|
||||||
re_hashes_in_name = re.compile(br"([^#]*)(#([0-9a-fA-F]{2}))?")
|
re_hashes_in_name = re.compile(rb"([^#]*)(#([0-9a-fA-F]{2}))?")
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def interpret_name(cls, raw, as_text=False):
|
def interpret_name(cls, raw, as_text=False):
|
||||||
|
@ -704,53 +704,53 @@ class PdfParser:
|
||||||
else:
|
else:
|
||||||
return bytes(name)
|
return bytes(name)
|
||||||
|
|
||||||
re_null = re.compile(whitespace_optional + br"null(?=" + delimiter_or_ws + br")")
|
re_null = re.compile(whitespace_optional + rb"null(?=" + delimiter_or_ws + rb")")
|
||||||
re_true = re.compile(whitespace_optional + br"true(?=" + delimiter_or_ws + br")")
|
re_true = re.compile(whitespace_optional + rb"true(?=" + delimiter_or_ws + rb")")
|
||||||
re_false = re.compile(whitespace_optional + br"false(?=" + delimiter_or_ws + br")")
|
re_false = re.compile(whitespace_optional + rb"false(?=" + delimiter_or_ws + rb")")
|
||||||
re_int = re.compile(
|
re_int = re.compile(
|
||||||
whitespace_optional + br"([-+]?[0-9]+)(?=" + delimiter_or_ws + br")"
|
whitespace_optional + rb"([-+]?[0-9]+)(?=" + delimiter_or_ws + rb")"
|
||||||
)
|
)
|
||||||
re_real = re.compile(
|
re_real = re.compile(
|
||||||
whitespace_optional
|
whitespace_optional
|
||||||
+ br"([-+]?([0-9]+\.[0-9]*|[0-9]*\.[0-9]+))(?="
|
+ rb"([-+]?([0-9]+\.[0-9]*|[0-9]*\.[0-9]+))(?="
|
||||||
+ delimiter_or_ws
|
+ delimiter_or_ws
|
||||||
+ br")"
|
+ rb")"
|
||||||
)
|
)
|
||||||
re_array_start = re.compile(whitespace_optional + br"\[")
|
re_array_start = re.compile(whitespace_optional + rb"\[")
|
||||||
re_array_end = re.compile(whitespace_optional + br"]")
|
re_array_end = re.compile(whitespace_optional + rb"]")
|
||||||
re_string_hex = re.compile(
|
re_string_hex = re.compile(
|
||||||
whitespace_optional + br"\<(" + whitespace_or_hex + br"*)\>"
|
whitespace_optional + rb"\<(" + whitespace_or_hex + rb"*)\>"
|
||||||
)
|
)
|
||||||
re_string_lit = re.compile(whitespace_optional + br"\(")
|
re_string_lit = re.compile(whitespace_optional + rb"\(")
|
||||||
re_indirect_reference = re.compile(
|
re_indirect_reference = re.compile(
|
||||||
whitespace_optional
|
whitespace_optional
|
||||||
+ br"([-+]?[0-9]+)"
|
+ rb"([-+]?[0-9]+)"
|
||||||
+ whitespace_mandatory
|
+ whitespace_mandatory
|
||||||
+ br"([-+]?[0-9]+)"
|
+ rb"([-+]?[0-9]+)"
|
||||||
+ whitespace_mandatory
|
+ whitespace_mandatory
|
||||||
+ br"R(?="
|
+ rb"R(?="
|
||||||
+ delimiter_or_ws
|
+ delimiter_or_ws
|
||||||
+ br")"
|
+ rb")"
|
||||||
)
|
)
|
||||||
re_indirect_def_start = re.compile(
|
re_indirect_def_start = re.compile(
|
||||||
whitespace_optional
|
whitespace_optional
|
||||||
+ br"([-+]?[0-9]+)"
|
+ rb"([-+]?[0-9]+)"
|
||||||
+ whitespace_mandatory
|
+ whitespace_mandatory
|
||||||
+ br"([-+]?[0-9]+)"
|
+ rb"([-+]?[0-9]+)"
|
||||||
+ whitespace_mandatory
|
+ whitespace_mandatory
|
||||||
+ br"obj(?="
|
+ rb"obj(?="
|
||||||
+ delimiter_or_ws
|
+ delimiter_or_ws
|
||||||
+ br")"
|
+ rb")"
|
||||||
)
|
)
|
||||||
re_indirect_def_end = re.compile(
|
re_indirect_def_end = re.compile(
|
||||||
whitespace_optional + br"endobj(?=" + delimiter_or_ws + br")"
|
whitespace_optional + rb"endobj(?=" + delimiter_or_ws + rb")"
|
||||||
)
|
)
|
||||||
re_comment = re.compile(
|
re_comment = re.compile(
|
||||||
br"(" + whitespace_optional + br"%[^\r\n]*" + newline + br")*"
|
rb"(" + whitespace_optional + rb"%[^\r\n]*" + newline + rb")*"
|
||||||
)
|
)
|
||||||
re_stream_start = re.compile(whitespace_optional + br"stream\r?\n")
|
re_stream_start = re.compile(whitespace_optional + rb"stream\r?\n")
|
||||||
re_stream_end = re.compile(
|
re_stream_end = re.compile(
|
||||||
whitespace_optional + br"endstream(?=" + delimiter_or_ws + br")"
|
whitespace_optional + rb"endstream(?=" + delimiter_or_ws + rb")"
|
||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -876,7 +876,7 @@ class PdfParser:
|
||||||
raise PdfFormatError("unrecognized object: " + repr(data[offset : offset + 32]))
|
raise PdfFormatError("unrecognized object: " + repr(data[offset : offset + 32]))
|
||||||
|
|
||||||
re_lit_str_token = re.compile(
|
re_lit_str_token = re.compile(
|
||||||
br"(\\[nrtbf()\\])|(\\[0-9]{1,3})|(\\(\r\n|\r|\n))|(\r\n|\r|\n)|(\()|(\))"
|
rb"(\\[nrtbf()\\])|(\\[0-9]{1,3})|(\\(\r\n|\r|\n))|(\r\n|\r|\n)|(\()|(\))"
|
||||||
)
|
)
|
||||||
escaped_chars = {
|
escaped_chars = {
|
||||||
b"n": b"\n",
|
b"n": b"\n",
|
||||||
|
@ -922,16 +922,16 @@ class PdfParser:
|
||||||
offset = m.end()
|
offset = m.end()
|
||||||
raise PdfFormatError("unfinished literal string")
|
raise PdfFormatError("unfinished literal string")
|
||||||
|
|
||||||
re_xref_section_start = re.compile(whitespace_optional + br"xref" + newline)
|
re_xref_section_start = re.compile(whitespace_optional + rb"xref" + newline)
|
||||||
re_xref_subsection_start = re.compile(
|
re_xref_subsection_start = re.compile(
|
||||||
whitespace_optional
|
whitespace_optional
|
||||||
+ br"([0-9]+)"
|
+ rb"([0-9]+)"
|
||||||
+ whitespace_mandatory
|
+ whitespace_mandatory
|
||||||
+ br"([0-9]+)"
|
+ rb"([0-9]+)"
|
||||||
+ whitespace_optional
|
+ whitespace_optional
|
||||||
+ newline_only
|
+ newline_only
|
||||||
)
|
)
|
||||||
re_xref_entry = re.compile(br"([0-9]{10}) ([0-9]{5}) ([fn])( \r| \n|\r\n)")
|
re_xref_entry = re.compile(rb"([0-9]{10}) ([0-9]{5}) ([fn])( \r| \n|\r\n)")
|
||||||
|
|
||||||
def read_xref_table(self, xref_section_offset):
|
def read_xref_table(self, xref_section_offset):
|
||||||
subsection_found = False
|
subsection_found = False
|
||||||
|
|
|
@ -48,7 +48,7 @@ from ._binary import o32be as o32
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
is_cid = re.compile(br"\w\w\w\w").match
|
is_cid = re.compile(rb"\w\w\w\w").match
|
||||||
|
|
||||||
|
|
||||||
_MAGIC = b"\211PNG\r\n\032\n"
|
_MAGIC = b"\211PNG\r\n\032\n"
|
||||||
|
|
|
@ -120,7 +120,7 @@ class PpmImageFile(ImageFile.ImageFile):
|
||||||
if maxval > 255:
|
if maxval > 255:
|
||||||
if not mode == "L":
|
if not mode == "L":
|
||||||
raise ValueError(f"Too many colors for band: {maxval}")
|
raise ValueError(f"Too many colors for band: {maxval}")
|
||||||
if maxval < 2 ** 16:
|
if maxval < 2**16:
|
||||||
self.mode = "I"
|
self.mode = "I"
|
||||||
rawmode = "I;16B"
|
rawmode = "I;16B"
|
||||||
else:
|
else:
|
||||||
|
@ -310,7 +310,7 @@ def _save(im, fp, filename):
|
||||||
elif im.mode == "L":
|
elif im.mode == "L":
|
||||||
rawmode, head = "L", b"P5"
|
rawmode, head = "L", b"P5"
|
||||||
elif im.mode == "I":
|
elif im.mode == "I":
|
||||||
if im.getextrema()[1] < 2 ** 16:
|
if im.getextrema()[1] < 2**16:
|
||||||
rawmode, head = "I;16B", b"P5"
|
rawmode, head = "I;16B", b"P5"
|
||||||
else:
|
else:
|
||||||
rawmode, head = "I;32B", b"P5"
|
rawmode, head = "I;32B", b"P5"
|
||||||
|
|
|
@ -493,7 +493,7 @@ class ImageFileDirectory_v2(MutableMapping):
|
||||||
endianness.
|
endianness.
|
||||||
:param prefix: Override the endianness of the file.
|
:param prefix: Override the endianness of the file.
|
||||||
"""
|
"""
|
||||||
if ifh[:4] not in PREFIXES:
|
if not _accept(ifh):
|
||||||
raise SyntaxError(f"not a TIFF file (header {repr(ifh)} not valid)")
|
raise SyntaxError(f"not a TIFF file (header {repr(ifh)} not valid)")
|
||||||
self._prefix = prefix if prefix is not None else ifh[:2]
|
self._prefix = prefix if prefix is not None else ifh[:2]
|
||||||
if self._prefix == MM:
|
if self._prefix == MM:
|
||||||
|
@ -577,9 +577,9 @@ class ImageFileDirectory_v2(MutableMapping):
|
||||||
else TiffTags.SIGNED_RATIONAL
|
else TiffTags.SIGNED_RATIONAL
|
||||||
)
|
)
|
||||||
elif all(isinstance(v, int) for v in values):
|
elif all(isinstance(v, int) for v in values):
|
||||||
if all(0 <= v < 2 ** 16 for v in values):
|
if all(0 <= v < 2**16 for v in values):
|
||||||
self.tagtype[tag] = TiffTags.SHORT
|
self.tagtype[tag] = TiffTags.SHORT
|
||||||
elif all(-(2 ** 15) < v < 2 ** 15 for v in values):
|
elif all(-(2**15) < v < 2**15 for v in values):
|
||||||
self.tagtype[tag] = TiffTags.SIGNED_SHORT
|
self.tagtype[tag] = TiffTags.SIGNED_SHORT
|
||||||
else:
|
else:
|
||||||
self.tagtype[tag] = (
|
self.tagtype[tag] = (
|
||||||
|
@ -734,7 +734,7 @@ class ImageFileDirectory_v2(MutableMapping):
|
||||||
@_register_writer(5)
|
@_register_writer(5)
|
||||||
def write_rational(self, *values):
|
def write_rational(self, *values):
|
||||||
return b"".join(
|
return b"".join(
|
||||||
self._pack("2L", *_limit_rational(frac, 2 ** 32 - 1)) for frac in values
|
self._pack("2L", *_limit_rational(frac, 2**32 - 1)) for frac in values
|
||||||
)
|
)
|
||||||
|
|
||||||
@_register_loader(7, 1)
|
@_register_loader(7, 1)
|
||||||
|
@ -757,7 +757,7 @@ class ImageFileDirectory_v2(MutableMapping):
|
||||||
@_register_writer(10)
|
@_register_writer(10)
|
||||||
def write_signed_rational(self, *values):
|
def write_signed_rational(self, *values):
|
||||||
return b"".join(
|
return b"".join(
|
||||||
self._pack("2l", *_limit_signed_rational(frac, 2 ** 31 - 1, -(2 ** 31)))
|
self._pack("2l", *_limit_signed_rational(frac, 2**31 - 1, -(2**31)))
|
||||||
for frac in values
|
for frac in values
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1670,7 +1670,7 @@ def _save(im, fp, filename):
|
||||||
strip_byte_counts = 1 if stride == 0 else stride * rows_per_strip
|
strip_byte_counts = 1 if stride == 0 else stride * rows_per_strip
|
||||||
strips_per_image = (im.size[1] + rows_per_strip - 1) // rows_per_strip
|
strips_per_image = (im.size[1] + rows_per_strip - 1) // rows_per_strip
|
||||||
ifd[ROWSPERSTRIP] = rows_per_strip
|
ifd[ROWSPERSTRIP] = rows_per_strip
|
||||||
if strip_byte_counts >= 2 ** 16:
|
if strip_byte_counts >= 2**16:
|
||||||
ifd.tagtype[STRIPBYTECOUNTS] = TiffTags.LONG
|
ifd.tagtype[STRIPBYTECOUNTS] = TiffTags.LONG
|
||||||
ifd[STRIPBYTECOUNTS] = (strip_byte_counts,) * (strips_per_image - 1) + (
|
ifd[STRIPBYTECOUNTS] = (strip_byte_counts,) * (strips_per_image - 1) + (
|
||||||
stride * im.size[1] - strip_byte_counts * (strips_per_image - 1),
|
stride * im.size[1] - strip_byte_counts * (strips_per_image - 1),
|
||||||
|
|
|
@ -21,7 +21,6 @@
|
||||||
|
|
||||||
from . import Image, ImageFile
|
from . import Image, ImageFile
|
||||||
from ._binary import i16le as word
|
from ._binary import i16le as word
|
||||||
from ._binary import i32le as dword
|
|
||||||
from ._binary import si16le as short
|
from ._binary import si16le as short
|
||||||
from ._binary import si32le as _long
|
from ._binary import si32le as _long
|
||||||
|
|
||||||
|
@ -112,7 +111,7 @@ class WmfStubImageFile(ImageFile.StubImageFile):
|
||||||
if s[22:26] != b"\x01\x00\t\x00":
|
if s[22:26] != b"\x01\x00\t\x00":
|
||||||
raise SyntaxError("Unsupported WMF file format")
|
raise SyntaxError("Unsupported WMF file format")
|
||||||
|
|
||||||
elif dword(s) == 1 and s[40:44] == b" EMF":
|
elif s[:4] == b"\x01\x00\x00\x00" and s[40:44] == b" EMF":
|
||||||
# enhanced metafile
|
# enhanced metafile
|
||||||
|
|
||||||
# get bounding box
|
# get bounding box
|
||||||
|
|
|
@ -25,7 +25,7 @@ from . import Image, ImageFile
|
||||||
|
|
||||||
# XBM header
|
# XBM header
|
||||||
xbm_head = re.compile(
|
xbm_head = re.compile(
|
||||||
br"\s*#define[ \t]+.*_width[ \t]+(?P<width>[0-9]+)[\r\n]+"
|
rb"\s*#define[ \t]+.*_width[ \t]+(?P<width>[0-9]+)[\r\n]+"
|
||||||
b"#define[ \t]+.*_height[ \t]+(?P<height>[0-9]+)[\r\n]+"
|
b"#define[ \t]+.*_height[ \t]+(?P<height>[0-9]+)[\r\n]+"
|
||||||
b"(?P<hotspot>"
|
b"(?P<hotspot>"
|
||||||
b"#define[ \t]+[^_]*_x_hot[ \t]+(?P<xhot>[0-9]+)[\r\n]+"
|
b"#define[ \t]+[^_]*_x_hot[ \t]+(?P<xhot>[0-9]+)[\r\n]+"
|
||||||
|
@ -52,7 +52,8 @@ class XbmImageFile(ImageFile.ImageFile):
|
||||||
|
|
||||||
m = xbm_head.match(self.fp.read(512))
|
m = xbm_head.match(self.fp.read(512))
|
||||||
|
|
||||||
if m:
|
if not m:
|
||||||
|
raise SyntaxError("not a XBM file")
|
||||||
|
|
||||||
xsize = int(m.group("width"))
|
xsize = int(m.group("width"))
|
||||||
ysize = int(m.group("height"))
|
ysize = int(m.group("height"))
|
||||||
|
|
|
@ -464,7 +464,7 @@ def build_dep_all():
|
||||||
if dep_name in disabled:
|
if dep_name in disabled:
|
||||||
continue
|
continue
|
||||||
script = build_dep(dep_name)
|
script = build_dep(dep_name)
|
||||||
lines.append(fr'cmd.exe /c "{{build_dir}}\{script}"')
|
lines.append(rf'cmd.exe /c "{{build_dir}}\{script}"')
|
||||||
lines.append("if errorlevel 1 echo Build failed! && exit /B 1")
|
lines.append("if errorlevel 1 echo Build failed! && exit /B 1")
|
||||||
lines.append("@echo All Pillow dependencies built successfully!")
|
lines.append("@echo All Pillow dependencies built successfully!")
|
||||||
write_script("build_dep_all.cmd", lines)
|
write_script("build_dep_all.cmd", lines)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user