Skip to content
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

Exception occurred when loading large .bmp file #283

Closed
pahmcoung opened this issue Nov 28, 2014 · 12 comments
Closed

Exception occurred when loading large .bmp file #283

pahmcoung opened this issue Nov 28, 2014 · 12 comments
Labels
Milestone

Comments

@pahmcoung
Copy link

I'm use glide-3.4.0.jar to load image in my app. But a exception occurred when loading large .bmp file (~20MB)

The below is my stacktrace.

I/System.out(20594): onException
W/System.err(20594): com.bumptech.glide.load.resource.bitmap.RecyclableBufferedInputStream$InvalidMarkException: Mark has been invalidated
W/System.err(20594):    at com.bumptech.glide.load.resource.bitmap.RecyclableBufferedInputStream.reset(RecyclableBufferedInputStream.java:350)
W/System.err(20594):    at com.bumptech.glide.util.ExceptionCatchingInputStream.reset(ExceptionCatchingInputStream.java:96)
W/System.err(20594):    at com.bumptech.glide.load.resource.bitmap.Downsampler.decodeStream(Downsampler.java:311)
W/System.err(20594):    at com.bumptech.glide.load.resource.bitmap.Downsampler.getDimensions(Downsampler.java:287)
W/System.err(20594):    at com.bumptech.glide.load.resource.bitmap.Downsampler.decode(Downsampler.java:133)
W/System.err(20594):    at com.bumptech.glide.load.resource.bitmap.StreamBitmapDecoder.decode(StreamBitmapDecoder.java:50)
W/System.err(20594):    at com.bumptech.glide.load.resource.bitmap.StreamBitmapDecoder.decode(StreamBitmapDecoder.java:19)
W/System.err(20594):    at com.bumptech.glide.load.resource.bitmap.ImageVideoBitmapDecoder.decode(ImageVideoBitmapDecoder.java:39)
W/System.err(20594):    at com.bumptech.glide.load.resource.bitmap.ImageVideoBitmapDecoder.decode(ImageVideoBitmapDecoder.java:20)
W/System.err(20594):    at com.bumptech.glide.load.resource.gifbitmap.GifBitmapWrapperResourceDecoder.decodeBitmapWrapper(GifBitmapWrapperResourceDecoder.java:121)
W/System.err(20594):    at com.bumptech.glide.load.resource.gifbitmap.GifBitmapWrapperResourceDecoder.decodeStream(GifBitmapWrapperResourceDecoder.java:94)
W/System.err(20594):    at com.bumptech.glide.load.resource.gifbitmap.GifBitmapWrapperResourceDecoder.decode(GifBitmapWrapperResourceDecoder.java:71)
W/System.err(20594):    at com.bumptech.glide.load.resource.gifbitmap.GifBitmapWrapperResourceDecoder.decode(GifBitmapWrapperResourceDecoder.java:61)
W/System.err(20594):    at com.bumptech.glide.load.resource.gifbitmap.GifBitmapWrapperResourceDecoder.decode(GifBitmapWrapperResourceDecoder.java:22)
W/System.err(20594):    at com.bumptech.glide.load.engine.DecodeJob.decodeFromSourceData(DecodeJob.java:189)
W/System.err(20594):    at com.bumptech.glide.load.engine.DecodeJob.decodeSource(DecodeJob.java:176)
W/System.err(20594):    at com.bumptech.glide.load.engine.DecodeJob.decodeFromSource(DecodeJob.java:127)
W/System.err(20594):    at com.bumptech.glide.load.engine.EngineRunnable.decodeFromSource(EngineRunnable.java:122)
W/System.err(20594):    at com.bumptech.glide.load.engine.EngineRunnable.decode(EngineRunnable.java:101)
W/System.err(20594):    at com.bumptech.glide.load.engine.EngineRunnable.run(EngineRunnable.java:58)
W/System.err(20594):    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:422)
W/System.err(20594):    at java.util.concurrent.FutureTask.run(FutureTask.java:237)
W/System.err(20594):    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
W/System.err(20594):    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
W/System.err(20594):    at java.lang.Thread.run(Thread.java:841)
W/System.err(20594):    at com.bumptech.glide.load.engine.executor.FifoPriorityThreadPoolExecutor$DefaultThreadFactory$1.run(FifoPriorityThreadPoolExecutor.java:52)
@sjudd
Copy link
Collaborator

sjudd commented Dec 1, 2014

Any chance you might be willing to attach an image that causes this? Either it's an image with a >5mb header, or we're incorrectly parsing the header for bmps.

@sjudd sjudd added the bug label Dec 1, 2014
@TWiStErRob
Copy link
Collaborator

@sjudd I think Glide doesn't support Windows bitmaps (.bmp), that is no hardcoded type: see how the image file type is determined. I think the reason for this exception is that the decoding is passed to Android which fails here, from the stackstrace (I guess this is what you mean with >5MB header) even though they list BMP as supported without any remarks.

@CuongSmile Apart from all this I highly suggest you rethink using uncompressed images of any form. I think it is really inefficient: battery, processor, bandwidth, space and did I mention battery? :)
See this video

@pahmcoung
Copy link
Author

@sjudd Thanks for supporting. Sorry I can't attach the image that causes this (becase my boss doesn't allow it).But I can load .bmp files have large about 1-2 MB .
@TWiStErRob Thanks for supporting.It it a part of my requirement ,I must do this :(

@pahmcoung
Copy link
Author

I find an .bmp file at here.When i loading it , an exception same above appeared.

@sjudd
Copy link
Collaborator

sjudd commented Dec 2, 2014

@CuongSmile what version of Android are you seeing this on? Unfortunately it looks like BitmapFactory may be trying to read the entire file with inJustDecodeBounds set to true, which isn't going to be trivial to work around.

@pahmcoung
Copy link
Author

@sjudd I run my app on Nexus 5 (Android 5.0) and Nexus 4 (Android 4.4.4)

@TWiStErRob
Copy link
Collaborator

@sjudd would it be too hacky to read the header yourself in case of ImageType.BMP (new) at Downsampler.getDimensions call based on the http://en.m.wikipedia.org/wiki/BMP_file_format and mimic inJustDecodeBounds?

@sjudd
Copy link
Collaborator

sjudd commented Dec 16, 2014

Looks like we will have to do something like that for now. I'll look in to it more, it may be a framework issue we can get fixed.

@pahmcoung
Copy link
Author

@sjudd Thanks for caring my problem. I want to ask you one question. Can I create new an inputstream to image if the exception above occurred ?

@sjudd
Copy link
Collaborator

sjudd commented Dec 21, 2014

Could you re-request the image to avoid this problem in the mark has been invalidated? In theory yes you could. Multiple network requests to decode an image aren't particularly appealing though...

@sjudd
Copy link
Collaborator

sjudd commented Dec 22, 2014

Underlying cause appears to be a BitmapFactory issue, it reads the entire stream when decoding .bmps. Internal bug is b/9484121.

I'll look in to a workaround. There is a generic class of error here which is a more serious bug. We shouldn't fail to decode an image just because we need to read more data than we expect to get the image header. Instead we should just use a sample size of 1 and decode the full image.

Probably the right way to do this would be to open a second InputStream, but since that's both expensive and not practical given the current implementation, I'll look in to some solution where we eagerly throw an exception before the mark is invalidated.

@pahmcoung
Copy link
Author

@sjudd ok.thanks you very much.I think i need changed some point in your library to fix this problem, Hoping you will be fix it early.:)

sjudd added a commit to sjudd/glide that referenced this issue Dec 26, 2014
Fixes bumptech#283.

We use BitmapFactory.Options#inJustDecodeBounds to
decode the width and height of images before
decoding the full image so that we can downsample
large images to avoid memory pressure. To do so,
we use mark/reset on a buffered InputStream. To
handle images with large headers, we set a large
(currently 5mb) mark limit. However, there's
always the chance that that limit is insufficient
even with a well formatted image and a bug
free decoder. Since downsampling is typically an
optimization, if such a failure occurs we still
want to decode the full image, even if we can't
obtain the dimensions. By enforcing we don't read
beyond our limit, we ensure that the header read
fails recoverably, so that the full image can
still be decoded.
@sjudd sjudd added this to the 3.5 milestone Dec 26, 2014
@sjudd sjudd closed this as completed in a84f6d1 Dec 26, 2014
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants