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
MemoryError: Integer overflow in ysize
reading ndpi image
#31
Comments
Same issue :/ @rcasero were you able to resolve it? |
I've had the same problem. It appears to be independent of slide level and region location. Regions with less than 2^29 pixels work fine. Regions with 2^29 or more pixels give the integer overflow error. This runs fine:
But this gives the same error:
So this is still a Pillow issue. But this is pretty similar to #17, which was supposedly fixed by reading from the slide in smaller chunks. Maybe that patch isn't working? |
I am encountering this issue as well. |
There are two definitions for lowlevel._load_image(). The solution to #17 was only applied to the fallback function, which is there in case the openslide._convert import fails. If the import succeeds, the old code executes and the overflow occurs. I was able to test this:
|
After further testing I can confirm that this method works, but is pretty slow- it takes ~15 minutes to load a large WSI into memory. This might be because of the aBGR -> RGBa conversion, or it might be because of the pasting; maybe we could multithread it and speed things up. But it does work. When I get a chance I'll submit a PR, would that be alright? @bgilbert |
what about reading it as mosaic and then compose it back?
|
@Borda it does read them as tiles, but it only uses one core at the moment. |
Same issue here. Trying to read a patch of size According to what I've read, it is a Pillow issue. Any pointers? Thanks! openslide-python: 1.1.1 EDIT: Version 1.1.1, 2016-06-11
I am not sure if I did something wrong during the installation, since they have already fixed this issue! I installed openslide-python using: See here about a fix. @bgilbert @markemus is this the fix that was mentioned in link about the issue 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 This way seems strange to me, since the function My current fix,that seems to work, following link:
...
import openslide
from openslide_python_fix import _load_image_lessthan_2_29, _load_image_morethan_2_29
...
# The function that reads the patches from a WSI.
def func_read_patch():
...
# Check which _load_image() function to use depending on the size of the region.
if (h_rec * w_rec) >= 2**29:
openslide.lowlevel._load_image = _load_image_morethan_2_29
else:
openslide.lowlevel._load_image = _load_image_lessthan_2_29
region = slide.read_region((upper_left[0], upper_left[1]), 0, (w_rec, h_rec)).convert('RGB') Unless I am mistaken, the issue of reading patches Content of from openslide.lowlevel import *
from openslide.lowlevel import _convert
def _load_image_lessthan_2_29(buf, size):
'''buf must be a mutable buffer.'''
_convert.argb2rgba(buf)
return PIL.Image.frombuffer('RGBA', size, buf, 'raw', 'RGBA', 0, 1)
def _load_image_morethan_2_29(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 Here is the running time of the function
|
@sbelharbi
my code:
but it still showed
it seems that it didn't call the function from openslide_python_fix.py |
Let me know how it goes. Thanks! |
@sbelharbi I fixed the problem by modifying lowlevel.py from here |
@lunasdejavu which parts I have commented? If I remember correctly, I copy-pasted the content of |
just changed the code from line 60 to 110, you have commented in another thread before. |
The merge you linked is not mine. |
@lunasdejavu It looks like you got a memory error trying to initialize the buffer for the image. Keep in mind that WSI images in memory decompress to be much larger than they are on disk (they're very sparse so they compress well). You can use my PR if you don't mind messing with your openslide install, or @sbelharbi 's code if you prefer not to. Either approach should work. Regardless, I'm glad you were able to resolve the problem. |
We also have exact same problem, is there any workarounds for this? |
Loading an entire WS (especially with high resolution, i.e., level 0) into memory depends on the size of the memory you have. I don't think that Openslide can do anything about it. Your options are: either loading entire WS with low resolution, or split the WS into large patches and process them sequentially. As @markemus mentioned, when decompressed into memory, WS takes a lot of space (way larger than the size on disc). |
Update the PIL to 6.2.0 dev solve this for me. |
how to ? pip3 install Pillow, the newest version is 6.1.0 |
Thanks for the report. This is fixed by python-pillow/Pillow#3964, which is in Pillow ≥ 6.2.0. I'll close. |
Context
Issue type: bug report
Operating system: Ubuntu 17.10 (Artful Aardvark)
Platform: 64-bit x86
OpenSlide Python version (
openslide.__version__
): 1.1.1OpenSlide version (
openslide.__library_version__
): 3.4.1Slide format (e.g. SVS, NDPI, MRXS): NDPI
Details
When trying to read this NDPI image, size (51200, 38144) ~ 1.82 Gpixels,
http://openslide.cs.cmu.edu/download/openslide-testdata/Hamamatsu/CMU-1.ndpi
with OpenSlide, the code
gives the error
Package versions:
The text was updated successfully, but these errors were encountered: