Skip to content

Drop fallback code for missing extension module #95

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 14, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 7 additions & 52 deletions openslide/lowlevel.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@
import platform
import sys

from . import _convert

if platform.system() == 'Windows':
_lib = cdll.LoadLibrary('libopenslide-0.dll')
elif platform.system() == 'Darwin':
Expand All @@ -57,58 +59,6 @@
else:
_lib = cdll.LoadLibrary('libopenslide.so.0')

try:
from . import _convert
def _load_image(buf, size):
'''buf must be a mutable buffer.'''
_convert.argb2rgba(buf)
return PIL.Image.frombuffer('RGBA', size, buf, 'raw', 'RGBA', 0, 1)
except ImportError:
def _load_image(buf, size):
'''buf must be a buffer.'''

# Load entire buffer at once if possible
MAX_PIXELS_PER_LOAD = (1 << 29) - 1
# Otherwise, use chunks smaller than the maximum to reduce memory
# requirements
PIXELS_PER_LOAD = 1 << 26

def do_load(buf, size):
'''buf can be a string, but should be a ctypes buffer to avoid an
extra copy in the caller.'''
# First reorder the bytes in a pixel from native-endian aRGB to
# big-endian RGBa to work around limitations in RGBa loader
rawmode = (sys.byteorder == 'little') and 'BGRA' or 'ARGB'
buf = PIL.Image.frombuffer('RGBA', size, buf, 'raw', rawmode, 0, 1)
# Image.tobytes() is named tostring() in Pillow 1.x and PIL
buf = (getattr(buf, 'tobytes', None) or buf.tostring)()
# Now load the image as RGBA, undoing premultiplication
return PIL.Image.frombuffer('RGBA', size, buf, 'raw', 'RGBa', 0, 1)

# Fast path for small buffers
w, h = size
if w * h <= MAX_PIXELS_PER_LOAD:
return do_load(buf, size)

# Load in chunks to avoid OverflowError in PIL.Image.frombuffer()
# https://github.com/python-pillow/Pillow/issues/1475
if w > PIXELS_PER_LOAD:
# We could support this, but it seems like overkill
raise ValueError('Width %d is too large (maximum %d)' %
(w, PIXELS_PER_LOAD))
rows_per_load = PIXELS_PER_LOAD // w
img = PIL.Image.new('RGBA', (w, h))
for y in range(0, h, rows_per_load):
rows = min(h - y, rows_per_load)
if sys.version[0] == '2':
chunk = buffer(buf, 4 * y * w, 4 * rows * w)
else:
# PIL.Image.frombuffer() won't take a memoryview or
# bytearray, so we can't avoid copying
chunk = memoryview(buf)[y * w:(y + rows) * w].tobytes()
img.paste(do_load(chunk, (w, rows)), (0, y))
return img

class OpenSlideError(Exception):
"""An error produced by the OpenSlide library.

Expand Down Expand Up @@ -167,6 +117,11 @@ def from_param(cls, obj):
else:
raise TypeError('Incorrect type')

def _load_image(buf, size):
'''buf must be a mutable buffer.'''
_convert.argb2rgba(buf)
return PIL.Image.frombuffer('RGBA', size, buf, 'raw', 'RGBA', 0, 1)

# check for errors opening an image file and wrap the resulting handle
def _check_open(result, _func, _args):
if result is None:
Expand Down
7 changes: 0 additions & 7 deletions tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,6 @@
from PIL import Image
import unittest

try:
import openslide._convert as _
have_optimizations = True
except ImportError:
have_optimizations = False


# PIL.Image cannot have zero width or height on Pillow 3.4.0 - 3.4.2
# https://github.com/python-pillow/Pillow/issues/2259
try:
Expand Down
12 changes: 2 additions & 10 deletions tests/test_openslide.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@
import sys
import unittest

from . import (file_path, have_optimizations, image_dimensions_cannot_be_zero,
skip_if)
from . import file_path, image_dimensions_cannot_be_zero, skip_if

# Tests should be written to be compatible with Python 2.6 unittest.

Expand Down Expand Up @@ -127,8 +126,7 @@ def test_read_region_bad_size(self):
@skip_if(sys.maxsize < 1 << 32, '32-bit Python')
# Broken on PIL and on Pillow >= 3.4.0, < 6.2.0.
# https://github.com/python-pillow/Pillow/issues/3963
@skip_if(have_optimizations and
[int(i) for i in getattr(Image, '__version__', '0').split('.')] < [6,2,0],
@skip_if([int(i) for i in getattr(Image, '__version__', '0').split('.')] < [6,2,0],
'broken on PIL and Pillow < 6.2.0')
# Disabled to avoid OOM killer on small systems, since the stdlib
# doesn't provide a way to find out how much RAM we have
Expand All @@ -137,12 +135,6 @@ def _test_read_region_2GB(self):
self.osr.read_region((1000, 1000), 0, (32768, 16384)).size,
(32768, 16384))

@skip_if(have_optimizations, 'only relevant --without-performance')
@skip_if(sys.maxsize < 1 << 32, '32-bit Python')
def test_read_region_2GB_width(self):
self.assertRaises(ValueError,
lambda: self.osr.read_region((1000, 1000), 0, (1 << 29, 1)))

def test_thumbnail(self):
self.assertEqual(self.osr.get_thumbnail((100, 100)).size, (100, 83))

Expand Down