diff --git a/Tests/32bit_segfault_check.py b/Tests/32bit_segfault_check.py
new file mode 100755
index 000000000..2ff7f908f
--- /dev/null
+++ b/Tests/32bit_segfault_check.py
@@ -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)
diff --git a/Tests/check_large_memory.py b/Tests/check_large_memory.py
index 219788d7b..d98f4a694 100644
--- a/Tests/check_large_memory.py
+++ b/Tests/check_large_memory.py
@@ -1,3 +1,5 @@
+import sys
+
import pytest
from PIL import Image
@@ -21,6 +23,9 @@ YDIM = 32769
XDIM = 48000
+pytestmark = pytest.mark.skipif(sys.maxsize <= 2**32, reason="requires 64-bit system")
+
+
def _write_png(tmp_path, xdim, ydim):
f = str(tmp_path / "temp.png")
im = Image.new("L", (xdim, ydim), 0)
diff --git a/Tests/check_large_memory_numpy.py b/Tests/check_large_memory_numpy.py
index c54894721..24cb1f722 100644
--- a/Tests/check_large_memory_numpy.py
+++ b/Tests/check_large_memory_numpy.py
@@ -1,3 +1,5 @@
+import sys
+
import pytest
from PIL import Image
@@ -17,6 +19,9 @@ YDIM = 32769
XDIM = 48000
+pytestmark = pytest.mark.skipif(sys.maxsize <= 2**32, reason="requires 64-bit system")
+
+
def _write_png(tmp_path, xdim, ydim):
dtype = np.uint8
a = np.zeros((xdim, ydim), dtype=dtype)
diff --git a/Tests/test_core_resources.py b/Tests/test_core_resources.py
index f2105d6ca..9021a9fb3 100644
--- a/Tests/test_core_resources.py
+++ b/Tests/test_core_resources.py
@@ -1,3 +1,5 @@
+import sys
+
import pytest
from PIL import Image
@@ -108,6 +110,9 @@ class TestCoreMemory:
with pytest.raises(ValueError):
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")
def test_set_blocks_max_stats(self):
diff --git a/Tests/test_file_webp.py b/Tests/test_file_webp.py
index 01b11447a..a7b6c735a 100644
--- a/Tests/test_file_webp.py
+++ b/Tests/test_file_webp.py
@@ -1,5 +1,6 @@
import io
import re
+import sys
import warnings
import pytest
@@ -144,6 +145,7 @@ class TestFileWebp:
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):
temp_file = str(tmp_path / "temp.webp")
im = Image.new("RGB", (15000, 15000))
diff --git a/Tests/test_image_putdata.py b/Tests/test_image_putdata.py
index db5307d2c..0e6293349 100644
--- a/Tests/test_image_putdata.py
+++ b/Tests/test_image_putdata.py
@@ -38,7 +38,10 @@ def test_long_integers():
assert put(0xFFFFFFFF) == (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():
diff --git a/Tests/test_map.py b/Tests/test_map.py
index 42b6f7cdd..d816bddaf 100644
--- a/Tests/test_map.py
+++ b/Tests/test_map.py
@@ -1,3 +1,5 @@
+import sys
+
import pytest
from PIL import Image
@@ -34,6 +36,7 @@ def test_tobytes():
Image.MAX_IMAGE_PIXELS = max_pixels
+@pytest.mark.skipif(sys.maxsize <= 2**32, reason="Requires 64-bit system")
def test_ysize():
numpy = pytest.importorskip("numpy", reason="NumPy not installed")
diff --git a/codecov.yml b/codecov.yml
index 40419979f..1ea7974eb 100644
--- a/codecov.yml
+++ b/codecov.yml
@@ -16,6 +16,7 @@ coverage:
# Matches 'omit:' in .coveragerc
ignore:
+ - "Tests/32bit_segfault_check.py"
- "Tests/bench_cffi_access.py"
- "Tests/check_*.py"
- "Tests/createfontdatachunk.py"
diff --git a/docs/installation.rst b/docs/installation.rst
index e29709bff..ed74dc147 100644
--- a/docs/installation.rst
+++ b/docs/installation.rst
@@ -285,8 +285,11 @@ Many of Pillow's features require external libraries:
.. tab:: Windows using MSYS2/MinGW
- To build Pillow using MSYS2, make sure you run the **MSYS2 MinGW 64-bit** console,
- *not* **MSYS2** directly.
+ To build Pillow using MSYS2, make sure you run the **MSYS2 MinGW 32-bit** or
+ **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::
@@ -336,6 +339,8 @@ Many of Pillow's features require external libraries:
pkg install -y python ndk-sysroot clang make \
libjpeg-turbo
+ This has been tested within the Termux app on ChromeOS, on x86.
+
Installing
^^^^^^^^^^
diff --git a/docs/releasenotes/10.0.0.rst b/docs/releasenotes/10.0.0.rst
index d33b75e4d..b5edd0e36 100644
--- a/docs/releasenotes/10.0.0.rst
+++ b/docs/releasenotes/10.0.0.rst
@@ -4,11 +4,6 @@
Backwards Incompatible Changes
==============================
-32-bit support
-^^^^^^^^^^^^^^
-
-32-bit architecture is no longer supported and 32-bit wheels are no longer provided.
-
Categories
^^^^^^^^^^
@@ -129,14 +124,6 @@ Image.coerce_e
This undocumented method has been removed.
-Deprecations
-============
-
-TODO
-^^^^
-
-TODO
-
API Changes
===========
@@ -165,6 +152,11 @@ TODO
Other Changes
=============
+32-bit wheels
+^^^^^^^^^^^^^
+
+32-bit wheels are no longer provided.
+
Support display_jpeg() in IPython
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/setup.py b/setup.py
index b647944d3..7c1ad6dc5 100755
--- a/setup.py
+++ b/setup.py
@@ -153,13 +153,16 @@ def _find_library_dirs_ldconfig():
ldconfig = "ldconfig" if shutil.which("ldconfig") else "/sbin/ldconfig"
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 = {
- "x86_64": "libc6,x86-64",
- "ppc64": "libc6,64bit",
- "sparc64": "libc6,64bit",
- "s390x": "libc6,64bit",
- "ia64": "libc6,IA-64",
+ "x86_64-64": "libc6,x86-64",
+ "ppc64-64": "libc6,64bit",
+ "sparc64-64": "libc6,64bit",
+ "s390x-64": "libc6,64bit",
+ "ia64-64": "libc6,IA-64",
}
abi_type = mach_map.get(machine, "libc6")
@@ -581,7 +584,10 @@ class pil_build_ext(build_ext):
# user libs are at $PREFIX/lib
_add_directory(
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"):
diff --git a/src/libImaging/ImagingUtils.h b/src/libImaging/ImagingUtils.h
index f2acabeac..0c0c1eda9 100644
--- a/src/libImaging/ImagingUtils.h
+++ b/src/libImaging/ImagingUtils.h
@@ -30,7 +30,7 @@
/* 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.
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)
static float __attribute__((always_inline)) inline _i2f(int v) {
float x;
diff --git a/winbuild/build.rst b/winbuild/build.rst
index 97df950b3..99dfad301 100644
--- a/winbuild/build.rst
+++ b/winbuild/build.rst
@@ -27,7 +27,7 @@ Download and install:
* `Ninja `_
(optional, use ``--nmake`` if not available; bundled in Visual Studio CMake component)
-* x64: `Netwide Assembler (NASM) `_
+* x86/x64: `Netwide Assembler (NASM) `_
Any version of Visual Studio 2017 or newer should be supported,
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]
[--depends PILLOW_DEPS]
- [--architecture {x64,ARM64}]
+ [--architecture {x86,x64,ARM64}]
[--python PYTHON] [--executable EXECUTABLE]
[--nmake] [--no-imagequant] [--no-fribidi]
@@ -56,7 +56,7 @@ Run ``build_prepare.py`` to configure the build::
--depends PILLOW_DEPS
directory used to store cached dependencies (default:
'winbuild\depends')
- --architecture {x64,ARM64}
+ --architecture {x86,x64,ARM64}
build architecture (default: same as host Python)
--python PYTHON Python install directory (default: use host Python)
--executable EXECUTABLE
diff --git a/winbuild/build_prepare.py b/winbuild/build_prepare.py
index 9984eb1bc..b9de071a0 100644
--- a/winbuild/build_prepare.py
+++ b/winbuild/build_prepare.py
@@ -3,6 +3,7 @@ import os
import platform
import re
import shutil
+import struct
import subprocess
import sys
@@ -97,6 +98,7 @@ def cmd_msbuild(
SF_PROJECTS = "https://sourceforge.net/projects"
architectures = {
+ "x86": {"vcvars_arch": "x86", "msbuild_arch": "Win32"},
"x64": {"vcvars_arch": "x86_amd64", "msbuild_arch": "x64"},
"ARM64": {"vcvars_arch": "x86_arm64", "msbuild_arch": "ARM64"},
}
@@ -609,7 +611,11 @@ if __name__ == "__main__":
choices=architectures,
default=os.environ.get(
"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)",
)