Restored 32-bit support

This commit is contained in:
Andrew Murray 2023-06-27 14:43:58 +10:00
parent 5c3d93fb2c
commit 45c9dcf123
14 changed files with 69 additions and 28 deletions

8
Tests/32bit_segfault_check.py Executable file
View File

@ -0,0 +1,8 @@
#!/usr/bin/env python3
import sys
from PIL import Image
if sys.maxsize < 2**32:
im = Image.new("L", (999999, 999999), 0)

View File

@ -1,3 +1,5 @@
import sys
import pytest import pytest
from PIL import Image from PIL import Image
@ -21,6 +23,9 @@ YDIM = 32769
XDIM = 48000 XDIM = 48000
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):
f = str(tmp_path / "temp.png") f = str(tmp_path / "temp.png")
im = Image.new("L", (xdim, ydim), 0) im = Image.new("L", (xdim, ydim), 0)

View File

@ -1,3 +1,5 @@
import sys
import pytest import pytest
from PIL import Image from PIL import Image
@ -17,6 +19,9 @@ YDIM = 32769
XDIM = 48000 XDIM = 48000
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):
dtype = np.uint8 dtype = np.uint8
a = np.zeros((xdim, ydim), dtype=dtype) a = np.zeros((xdim, ydim), dtype=dtype)

View File

@ -1,3 +1,5 @@
import sys
import pytest import pytest
from PIL import Image from PIL import Image
@ -108,6 +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:
with pytest.raises(ValueError):
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):

View File

@ -1,5 +1,6 @@
import io import io
import re import re
import sys
import warnings import warnings
import pytest import pytest
@ -144,6 +145,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")
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))

View File

@ -38,7 +38,10 @@ 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)
assert put(sys.maxsize) == (255, 255, 255, 255) if sys.maxsize > 2**32:
assert put(sys.maxsize) == (255, 255, 255, 255)
else:
assert put(sys.maxsize) == (255, 255, 255, 127)
def test_pypy_performance(): def test_pypy_performance():

View File

@ -1,3 +1,5 @@
import sys
import pytest import pytest
from PIL import Image from PIL import Image
@ -34,6 +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")
def test_ysize(): def test_ysize():
numpy = pytest.importorskip("numpy", reason="NumPy not installed") numpy = pytest.importorskip("numpy", reason="NumPy not installed")

View File

@ -16,6 +16,7 @@ coverage:
# Matches 'omit:' in .coveragerc # Matches 'omit:' in .coveragerc
ignore: ignore:
- "Tests/32bit_segfault_check.py"
- "Tests/bench_cffi_access.py" - "Tests/bench_cffi_access.py"
- "Tests/check_*.py" - "Tests/check_*.py"
- "Tests/createfontdatachunk.py" - "Tests/createfontdatachunk.py"

View File

@ -285,8 +285,11 @@ Many of Pillow's features require external libraries:
.. tab:: Windows using MSYS2/MinGW .. tab:: Windows using MSYS2/MinGW
To build Pillow using MSYS2, make sure you run the **MSYS2 MinGW 64-bit** console, To build Pillow using MSYS2, make sure you run the **MSYS2 MinGW 32-bit** or
*not* **MSYS2** directly. **MSYS2 MinGW 64-bit** console, *not* **MSYS2** directly.
The following instructions target the 64-bit build, for 32-bit
replace all occurrences of ``mingw-w64-x86_64-`` with ``mingw-w64-i686-``.
Make sure you have Python and GCC installed:: Make sure you have Python and GCC installed::
@ -336,6 +339,8 @@ Many of Pillow's features require external libraries:
pkg install -y python ndk-sysroot clang make \ pkg install -y python ndk-sysroot clang make \
libjpeg-turbo libjpeg-turbo
This has been tested within the Termux app on ChromeOS, on x86.
Installing Installing
^^^^^^^^^^ ^^^^^^^^^^

View File

@ -4,11 +4,6 @@
Backwards Incompatible Changes Backwards Incompatible Changes
============================== ==============================
32-bit support
^^^^^^^^^^^^^^
32-bit architecture is no longer supported and 32-bit wheels are no longer provided.
Categories Categories
^^^^^^^^^^ ^^^^^^^^^^
@ -129,14 +124,6 @@ Image.coerce_e
This undocumented method has been removed. This undocumented method has been removed.
Deprecations
============
TODO
^^^^
TODO
API Changes API Changes
=========== ===========
@ -165,6 +152,11 @@ TODO
Other Changes Other Changes
============= =============
32-bit wheels
^^^^^^^^^^^^^
32-bit wheels are no longer provided.
Support display_jpeg() in IPython Support display_jpeg() in IPython
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -153,13 +153,16 @@ def _find_library_dirs_ldconfig():
ldconfig = "ldconfig" if shutil.which("ldconfig") else "/sbin/ldconfig" ldconfig = "ldconfig" if shutil.which("ldconfig") else "/sbin/ldconfig"
if sys.platform.startswith("linux") or sys.platform.startswith("gnu"): if sys.platform.startswith("linux") or sys.platform.startswith("gnu"):
machine = os.uname()[4] if struct.calcsize("l") == 4:
machine = os.uname()[4] + "-32"
else:
machine = os.uname()[4] + "-64"
mach_map = { mach_map = {
"x86_64": "libc6,x86-64", "x86_64-64": "libc6,x86-64",
"ppc64": "libc6,64bit", "ppc64-64": "libc6,64bit",
"sparc64": "libc6,64bit", "sparc64-64": "libc6,64bit",
"s390x": "libc6,64bit", "s390x-64": "libc6,64bit",
"ia64": "libc6,IA-64", "ia64-64": "libc6,IA-64",
} }
abi_type = mach_map.get(machine, "libc6") abi_type = mach_map.get(machine, "libc6")
@ -581,7 +584,10 @@ class pil_build_ext(build_ext):
# user libs are at $PREFIX/lib # user libs are at $PREFIX/lib
_add_directory( _add_directory(
library_dirs, library_dirs,
os.path.join(os.environ["ANDROID_ROOT"], "lib64"), os.path.join(
os.environ["ANDROID_ROOT"],
"lib" if struct.calcsize("l") == 4 else "lib64",
),
) )
elif sys.platform.startswith("netbsd"): elif sys.platform.startswith("netbsd"):

View File

@ -30,7 +30,7 @@
/* This is to work around a bug in GCC prior 4.9 in 64 bit mode. /* This is to work around a bug in GCC prior 4.9 in 64 bit mode.
GCC generates code with partial dependency which is 3 times slower. GCC generates code with partial dependency which is 3 times slower.
See: https://stackoverflow.com/a/26588074/253146 */ See: https://stackoverflow.com/a/26588074/253146 */
#if defined(__SSE__) && !defined(__NO_INLINE__) && \ #if defined(__x86_64__) && defined(__SSE__) && !defined(__NO_INLINE__) && \
!defined(__clang__) && defined(GCC_VERSION) && (GCC_VERSION < 40900) !defined(__clang__) && defined(GCC_VERSION) && (GCC_VERSION < 40900)
static float __attribute__((always_inline)) inline _i2f(int v) { static float __attribute__((always_inline)) inline _i2f(int v) {
float x; float x;

View File

@ -27,7 +27,7 @@ Download and install:
* `Ninja <https://ninja-build.org/>`_ * `Ninja <https://ninja-build.org/>`_
(optional, use ``--nmake`` if not available; bundled in Visual Studio CMake component) (optional, use ``--nmake`` if not available; bundled in Visual Studio CMake component)
* x64: `Netwide Assembler (NASM) <https://www.nasm.us/pub/nasm/releasebuilds/?C=M;O=D>`_ * x86/x64: `Netwide Assembler (NASM) <https://www.nasm.us/pub/nasm/releasebuilds/?C=M;O=D>`_
Any version of Visual Studio 2017 or newer should be supported, Any version of Visual Studio 2017 or newer should be supported,
including Visual Studio 2017 Community, or Build Tools for Visual Studio 2019. including Visual Studio 2017 Community, or Build Tools for Visual Studio 2019.
@ -42,7 +42,7 @@ Run ``build_prepare.py`` to configure the build::
usage: winbuild\build_prepare.py [-h] [-v] [-d PILLOW_BUILD] usage: winbuild\build_prepare.py [-h] [-v] [-d PILLOW_BUILD]
[--depends PILLOW_DEPS] [--depends PILLOW_DEPS]
[--architecture {x64,ARM64}] [--architecture {x86,x64,ARM64}]
[--python PYTHON] [--executable EXECUTABLE] [--python PYTHON] [--executable EXECUTABLE]
[--nmake] [--no-imagequant] [--no-fribidi] [--nmake] [--no-imagequant] [--no-fribidi]
@ -56,7 +56,7 @@ Run ``build_prepare.py`` to configure the build::
--depends PILLOW_DEPS --depends PILLOW_DEPS
directory used to store cached dependencies (default: directory used to store cached dependencies (default:
'winbuild\depends') 'winbuild\depends')
--architecture {x64,ARM64} --architecture {x86,x64,ARM64}
build architecture (default: same as host Python) build architecture (default: same as host Python)
--python PYTHON Python install directory (default: use host Python) --python PYTHON Python install directory (default: use host Python)
--executable EXECUTABLE --executable EXECUTABLE

View File

@ -3,6 +3,7 @@ import os
import platform import platform
import re import re
import shutil import shutil
import struct
import subprocess import subprocess
import sys import sys
@ -97,6 +98,7 @@ def cmd_msbuild(
SF_PROJECTS = "https://sourceforge.net/projects" SF_PROJECTS = "https://sourceforge.net/projects"
architectures = { architectures = {
"x86": {"vcvars_arch": "x86", "msbuild_arch": "Win32"},
"x64": {"vcvars_arch": "x86_amd64", "msbuild_arch": "x64"}, "x64": {"vcvars_arch": "x86_amd64", "msbuild_arch": "x64"},
"ARM64": {"vcvars_arch": "x86_arm64", "msbuild_arch": "ARM64"}, "ARM64": {"vcvars_arch": "x86_arm64", "msbuild_arch": "ARM64"},
} }
@ -609,7 +611,11 @@ if __name__ == "__main__":
choices=architectures, choices=architectures,
default=os.environ.get( default=os.environ.get(
"ARCHITECTURE", "ARCHITECTURE",
"ARM64" if platform.machine() == "ARM64" else "x64", (
"ARM64"
if platform.machine() == "ARM64"
else ("x86" if struct.calcsize("P") == 4 else "x64")
),
), ),
help="build architecture (default: same as host Python)", help="build architecture (default: same as host Python)",
) )