Glide: how do solve Bitmap too large to be uploaded into a texture (4208x3120, max=4096x4096)

Created on 20 Jul 2015  路  14Comments  路  Source: bumptech/glide

how do solve Bitmap too large to be uploaded into a texture (4208x3120, max=4096x4096) when i open local image

question

Most helpful comment

@blinkmacalahan as far as I know if you set a smaller size the downsampling will happen to the nearest sampleSize just above the requested size, because that's done by the decoder, not transformation. From there a UnitTransformation doesn't do any more, but you can always explicitly request .fitCenter()/.centerCrop()/.transform() to reach the final target size exactly, even if your scaleType is one of those.

All 14 comments

Do you really want that big image? Please explain how you use the image and why?

If you search on Google you'll see that most of the time they advise to scale down or cut part of the image you want.

In case you just did a Glide.load("/path/to/file").into(imageView), then the problem is likely that your image view's size is wrap_content in xml on both sides. Modify the layout so that the ImageView have exact sizing (x dp) or match_parent at least on one side.

The texture limit is unfortunately an Android system limit. Since 4096x4096 is larger than most device screens, you probably won't see any drop in quality by decreasing it (which Glide will do by default if you don't use override and you load the image into an ImageView).

If you're trying to maximize quality when zooming, you will want some form of tiling, which Glide doesn't currently provide. There are a couple of other open source projects that do I believe and you can certainly use Glide to retrieve the data that you then pass to those other projects.

Let us know if you have further questions.

thack you very much;I have slove this problem

Could you please write a few sentences about your solution? Just in case someone in the future finds this issue?

it's not the Glide bug;It's only my worry write;

Glide.with(this).load("").into(new GlideDrawableImageViewTarget(img));

This is my worry code before;
only change to this : into(img);
the large picture diplay

01-14 04:08:59.726 6191-6223/com.example.android.justjava W/OpenGLRenderer: Bitmap too large to be uploaded into a texture (6432x4893, max=4096x4096)

how to resolve than ???

@Francesco80 do not load full-sized images.

  • Don't use .override(SIZE_ORIGINAL) or wrap_content on both sides of the view.
  • Load the image into an ImageView for efficient sizing.
  • If you're loading into SimpleTarget, notice that the implicit size in the default constructor is SIZE_ORIGINAL, try a more reasonable size in the overloaded constructor.

If you want a zoomable or scrollable image, try to find a lib that supports that. Glide deals with full images only by default.

@TWiStErRob thanks a lot ,, ill follow your instructions and see how it goes !! :D

@TWiStErRob, I wanted to add a point to your comment about how to avoid the "bitmap too large" error. Currently with 3.7, if the ImageView's scaleType is set to CENTER, CENTER_INSIDE, FIT_XY, or MATRIX it will result in the request builder using a UnitTransformation which per the docs says is a type of the resource that will always be returned unmodified.

Regardless of what size the View is, a UnitTransformation will never down sample the image. If the image is greater than Canvas.getMaxBitmapWidth/Height() then you'll get the "bitmap too large error".

Looking at the current state of the repo, I don't believe this has been fixed/addressed (or perhaps it is intended).

Hopefully this will save someone else a few hours!

@blinkmacalahan as far as I know if you set a smaller size the downsampling will happen to the nearest sampleSize just above the requested size, because that's done by the decoder, not transformation. From there a UnitTransformation doesn't do any more, but you can always explicitly request .fitCenter()/.centerCrop()/.transform() to reach the final target size exactly, even if your scaleType is one of those.

@TWiStErRob when you say, "if you set a smaller size the downsampling.." what are you referring to? Setting a size on the ImageView, calling .override(width, height) when loading the image via Glide, or something else?

In the scenario where I encountered issues, all I had was an ImageView with match_parent for width and height and MATRIX for scaleType. Looking at the Glide logs, the DecodeJob says it's decoding a dimension matching the size of the ImageView (1080x1536). However, when the Drawable is applied to the ImageView, it is the original image size (5312x2988). Looking at the DownSampler class, I see how it computed a sampleSize of 1 in getRoundedSampleSize() using the formula Math.min(inWidth(5312) / outWidth(1080), inHeight(2988) / outHeight(1536)).

My Glide request is extremely simple:
Glide.with(this).load("https://i.redditmedia.com/4o1C1p0lXbxB3hQEhuULe3_D5Hfn1cAW9IXXOY2_12I.jpg?s=328cf5be7ad605301f88b540a9d9868d").into((ImageView)findViewById(R.id.img));

Anyways, I was just looking for clarity on your response.

@blinkmacalahan

what are you referring to?

All of them, set a smaller target size (whichever way) than half of the source image's resolution.

Decoding 5312x2988 into 1080x1536

(_Wow, dat url crashed my desktop Chrome :open_mouth:_)
If you look at the sizes downsampling is just not possible. If Glide were to set inSampleSize = 2 it would immediately undershoot the target size: compare 2656x1494 VS 1080x1536. This undershooting is not allowed by default (Downsampler.AT_LEAST), so this huge image would be decoded as a whole and then downsized via the transformation you implicitly have disabled. Try to rotate your device to observe the downsampling behavior I'm talking about. Notice how it will load 2656x1494 into 1536x1080 (give or take surrounding UI).

You can have better results via:

  • .override(something smaller than half the image size)
  • .sizeMultiplier(.5f) which will make the target size smaller enabling downsampling at decode time. In the above specific case 0.95f would be sufficient.
  • using AT_MOST downsampler instead of AT_LEAST (default): .asBitmap().atMost().
  • using AT_MOST without asBitmap, however that's a little more complicated advanced usage:

java GifBitmapWrapperResourceDecoder decoder = new GifBitmapWrapperResourceDecoder( new ImageVideoBitmapDecoder( new StreamBitmapDecoder( Downsampler.AT_MOST, // rebuild all the defaults, except this one Glide.get(context).getBitmapPool(), DecodeFormat.DEFAULT), new FileDescriptorBitmapDecoder(context) ), new GifResourceDecoder(context), Glide.get(context).getBitmapPool() ); Glide .with(this) .load(url) .decoder(decoder) .cacheDecoder(new FileToStreamDecoder<>(new GifBitmapWrapperStreamResourceDecoder(decoder))) .into(imageView)

Tried to apply sizeMultiplier(0.5f) on image slightly bigger than max texture size and still get error

W/OpenGLRenderer: Bitmap too large to be uploaded into a texture (9128x1596, max=8192x8192)

AT_MOST downsampler not suitable for pinch zoom

.override() works well if supply size with multiplier 0.5, but fail if multiplier is 0.6
so seems values passed must be multiplied by 1 / (power of 2) to allow use bitmap sampling

How to do this in Glide 4.0? If my image is modify by a user in CMS, he makes a very long image.

  1. I want to do it with an network image
  2. I can't prohibit user input a long image from CMS
  3. I support API level 17, Samsung Google Galaxy Nexus, max texture = 2048( I know how to get this)
  4. How to do it from decoder? In Glide 4.0, I can't found any tutorial telling about this.

Thank you

Was this page helpful?
0 / 5 - 0 ratings

Related issues

technoir42 picture technoir42  路  3Comments

r4m1n picture r4m1n  路  3Comments

Ncit picture Ncit  路  3Comments

piedpiperlol picture piedpiperlol  路  3Comments

MrFuFuFu picture MrFuFuFu  路  3Comments