Android 2048x2048 image limit, clarify?

from: http://docs.coronalabs.com/api/library/graphics/newImageSheet.html

“On Android, images are limited (downsized) to 2048×2048, even though the maximum texture memory size is higher on the device. The reason is most Android devices don’t have enough heap memory to load the image.”

Does this statement also apply to dynamic resolution content? Say a 1024x1024 image loaded @4x 4096x4096 resolution would REALLY only load an effective @2x image?

So, I’m using 1024x1024 “@1x” sheets, and have 2048x2048 @2x versions.

The native content size of my app (480x640…480x854) is such that it’s entirely feasible that larger/newer/higher-resolution tablet devices (many 10"-class, but also Samsung 8.4, Kindle 8.9, etc) could benefit from having @4x images kick in at 3.0 or so.

So… is it true that even for these “hefty” devices, with plenty of memory to handle it, and even with largeHeap=true, will the 2K limit downsampling still occur?

It’s not the sort of thing I want to just try on one device and assume I “know” what’s happening. There’s no point working on a “HD” bundle if it just becomes @2x on load.

Thx

I wonder if this is still an issue for Graphics 2.0. As I understood it, OpenGL textures are not counted towards the heap limit and instead are limited by device constraints. But I don’t know exactly how Corona SDK is handling image sheets, so maybe someone from the team could chime in?

The 2048x2048 spritesheet size is more of a guideline.  Let me explain…

What you need to be aware of is that GPUs (ie: the graphics hardware) has a limit to how many pixels wide/tall a texture/image can be.  This is called “max texture size”.  Attempting to load a texture that is larger than this limit will cause the GPU to fail to load the image or other undesirable effects.  And the max texture size varies between different GPUs (ie: some GPUs support larger textures than others) such as 1024x1024, 2048x2048, 4096x4096, etc.  A max texture size of 2048x2048 used to be quite common among Android 2.x devices, which is why we recommend that resolution for spritesheets.  High resolution devices are typically 4096x4096 or higher.

Now, if you load an image that is larger than the max texture size, then Corona will automatically downscale/downsample the image in memory before pushing it to the GPU as a texture.  This way we guarantee that it’ll still be displayed onscreen.  In fact, this typically always happens to photo that you’ve loaded from the photo gallery via Corona, because photos are almost always larger than max texture size that the GPU supports.  This downsampling effect is typically not noticeable with photos, so, no one really notices.  But with spritesheets the downsampling effect is much more noticeable and it may result in kind of an ugly image.  Especially if you’re going for the pixel art look because every other pixel will be skipped when the image gets downsampled to a texture that will fit within the max texture size limitation.

So, all in all… yes, you can use a spritesheet that is larger than 2048x2048, but we don’t recommend it.  Especially if you plan on porting your app to the Android market.  Bottom line, your images may end up looking ugly on low resolution Android devices… and remember that cheap Android devices (along with their cheap low-end GPUs) are popular.

And in case you’re interested, you can fetch the GPUs max textures size in Corona via system.getInfo(“maxTextureSize”).

   http://docs.coronalabs.com/api/library/system/getInfo.html#maxtexturesize

I’m wondering how much of a problem this is. I’d assume Corona’s dynamic loading will solve this nicely.

I don’t think there are any @4x capable Android devices that only has a 2048 texture limit. 

As long as the @2x images don’t exceed 2048px, I think we’ll be fine.

…or am I wrong?

Thanks Joshua. I’ll leave a note to have the documentation changed, because what you’re saying is exactly what I was saying:

  1. Heap size no longer matters as they are OpenGL textures

  2. Look to the device limit instead

I believe some older devices (maybe even the pre-2013 Nexus 7) are 2048 max, but then again that device was 720p. My suspicion is that any device that does limit to 2048 is going to be slow/old enough that lower quality resolution is not going to be a surprise. There are just too many devices out there to police how sharp something looks on an outlier unit. (On iOS, I believe the iPad3 was originally spec’d at 2048x2048, but google seems to indicate that limit was increased with iOS5.1.)

Yeah, I’ve got a Nexus 7 (2012 model) and it reports 2048 max texture size.

However the display resolution is 1280x800 which will only load @2x graphics anyway, which is perfectly fine.

I don’t have any higher-res Android devices, but I assume that devices that have the screen resolution to display @4x graphics will up the max texture size accordingly.

thanks all. sounds like the docs need changing, as they don’t indicate (at all) that it’s merely a “recommended” practice. in general, that’s what i was suspecting – any device of high-enough resolution to warrant the @4x assets probably would support them – i was worried that Corona *itself* was enforcing a 2k limit regardless. now just wish glbench.com (or some other site i’ve not yet found) listed max texture size along w resolution to research further.

Regarding 2048x2048 being the upper limit in Corona in graphics 1.0 regardless of max texture size on Android… that was true in the last “release” version of graphics 1.0, but we changed this behavior in the last graphics 1.0 daily builds.  In those final daily builds, we super optimized image loading on Android to load image faster and use far less heap memory.  This allowed us to load images larger than 2048x2048, up to the max texture size.  This change was ported to our graphics 2.0 version for its first release.

Now, that said, you can still run into the issue where you don’t have enough heap memory to load too many large images.  If this happens, we have a fallback mechanism which downsamples the image down to the next power of 2 (say, 4096x4096 to 2048x2048).  Corona will still load the image, but it may have this ugly scaling effect.  I find that this issue happens much rarer now since we’ve made our image loading optimizations (we load images on the C/C++ side instead of Java now, which has much more heap memory available to it), but this downsampling issue is still possible.  I’ve learned to expect the worst on Android since the hardware varies so wildly… but I suppose the flip side is that it’s okay for this ugly downsampling effect to occur on low-end Android devices and you can blow it off as customer get what they pay for?  I dunno.  It’s up to you.

Also, I find that the max texture size on a device is >= to the screen’s largest dimension in pixels.  This makes sense since it would allow a developer to load an image as a texture fullscreen.  I’ve never seen a max texture size less the screen resolution, and I would hope none exist.

I wonder if this is still an issue for Graphics 2.0. As I understood it, OpenGL textures are not counted towards the heap limit and instead are limited by device constraints. But I don’t know exactly how Corona SDK is handling image sheets, so maybe someone from the team could chime in?

The 2048x2048 spritesheet size is more of a guideline.  Let me explain…

What you need to be aware of is that GPUs (ie: the graphics hardware) has a limit to how many pixels wide/tall a texture/image can be.  This is called “max texture size”.  Attempting to load a texture that is larger than this limit will cause the GPU to fail to load the image or other undesirable effects.  And the max texture size varies between different GPUs (ie: some GPUs support larger textures than others) such as 1024x1024, 2048x2048, 4096x4096, etc.  A max texture size of 2048x2048 used to be quite common among Android 2.x devices, which is why we recommend that resolution for spritesheets.  High resolution devices are typically 4096x4096 or higher.

Now, if you load an image that is larger than the max texture size, then Corona will automatically downscale/downsample the image in memory before pushing it to the GPU as a texture.  This way we guarantee that it’ll still be displayed onscreen.  In fact, this typically always happens to photo that you’ve loaded from the photo gallery via Corona, because photos are almost always larger than max texture size that the GPU supports.  This downsampling effect is typically not noticeable with photos, so, no one really notices.  But with spritesheets the downsampling effect is much more noticeable and it may result in kind of an ugly image.  Especially if you’re going for the pixel art look because every other pixel will be skipped when the image gets downsampled to a texture that will fit within the max texture size limitation.

So, all in all… yes, you can use a spritesheet that is larger than 2048x2048, but we don’t recommend it.  Especially if you plan on porting your app to the Android market.  Bottom line, your images may end up looking ugly on low resolution Android devices… and remember that cheap Android devices (along with their cheap low-end GPUs) are popular.

And in case you’re interested, you can fetch the GPUs max textures size in Corona via system.getInfo(“maxTextureSize”).

   http://docs.coronalabs.com/api/library/system/getInfo.html#maxtexturesize

I’m wondering how much of a problem this is. I’d assume Corona’s dynamic loading will solve this nicely.

I don’t think there are any @4x capable Android devices that only has a 2048 texture limit. 

As long as the @2x images don’t exceed 2048px, I think we’ll be fine.

…or am I wrong?

Thanks Joshua. I’ll leave a note to have the documentation changed, because what you’re saying is exactly what I was saying:

  1. Heap size no longer matters as they are OpenGL textures

  2. Look to the device limit instead

I believe some older devices (maybe even the pre-2013 Nexus 7) are 2048 max, but then again that device was 720p. My suspicion is that any device that does limit to 2048 is going to be slow/old enough that lower quality resolution is not going to be a surprise. There are just too many devices out there to police how sharp something looks on an outlier unit. (On iOS, I believe the iPad3 was originally spec’d at 2048x2048, but google seems to indicate that limit was increased with iOS5.1.)

Yeah, I’ve got a Nexus 7 (2012 model) and it reports 2048 max texture size.

However the display resolution is 1280x800 which will only load @2x graphics anyway, which is perfectly fine.

I don’t have any higher-res Android devices, but I assume that devices that have the screen resolution to display @4x graphics will up the max texture size accordingly.

thanks all. sounds like the docs need changing, as they don’t indicate (at all) that it’s merely a “recommended” practice. in general, that’s what i was suspecting – any device of high-enough resolution to warrant the @4x assets probably would support them – i was worried that Corona *itself* was enforcing a 2k limit regardless. now just wish glbench.com (or some other site i’ve not yet found) listed max texture size along w resolution to research further.

Regarding 2048x2048 being the upper limit in Corona in graphics 1.0 regardless of max texture size on Android… that was true in the last “release” version of graphics 1.0, but we changed this behavior in the last graphics 1.0 daily builds.  In those final daily builds, we super optimized image loading on Android to load image faster and use far less heap memory.  This allowed us to load images larger than 2048x2048, up to the max texture size.  This change was ported to our graphics 2.0 version for its first release.

Now, that said, you can still run into the issue where you don’t have enough heap memory to load too many large images.  If this happens, we have a fallback mechanism which downsamples the image down to the next power of 2 (say, 4096x4096 to 2048x2048).  Corona will still load the image, but it may have this ugly scaling effect.  I find that this issue happens much rarer now since we’ve made our image loading optimizations (we load images on the C/C++ side instead of Java now, which has much more heap memory available to it), but this downsampling issue is still possible.  I’ve learned to expect the worst on Android since the hardware varies so wildly… but I suppose the flip side is that it’s okay for this ugly downsampling effect to occur on low-end Android devices and you can blow it off as customer get what they pay for?  I dunno.  It’s up to you.

Also, I find that the max texture size on a device is >= to the screen’s largest dimension in pixels.  This makes sense since it would allow a developer to load an image as a texture fullscreen.  I’ve never seen a max texture size less the screen resolution, and I would hope none exist.