Desperately need a workaround for loading big photos to newImage

Right now I can’t use Corona to write an app that asks for a photo.

As I’ve fed back to this thread, there’s a problem loading a .jpeg file to a newImage if the image is very wide or high, such as photos coming from pretty much any phone manufactured within the last two years. The solution is to make sure a smaller version of the image is loaded to newImage. One way could be to have an inSampleSize option for newImage so that only every nth pixel is read from disk to memory. The other is to do the same streaming the photo to a temporary image file.

Often, the images are around 3000x4000px, which is a few multiples of the screen resolution on most phones, which means you rarely need the full resolution photo for anything in an app.

On Android (note that the problem is generic, though!), there’s a way to handle this. I have a working InputStream example in Java that takes a big image and scales it coarsely, to write out a temporary scaled down jpeg file. Would that be possible to do in Lua?

Note that just to not crash the phone, you can’t process the image as an object, that the whole problem behind this. It will try to allocate 36MB or more memory and fail. So any solution would have to process parts of the image and write them out, for example a pixel line at a time. It uses InputStream and BitmapFactory.

InputStream is = this.getContentResolver().openInputStream(imageUriOrig); BitmapFactory.Options o = new BitmapFactory.Options(); o.inJustDecodeBounds = true; o.inPreferredConfig = Bitmap.Config.ARGB\_8888; BitmapFactory.decodeStream(is,null,o); is.close(); int w=o.outWidth; int h=o.outHeight; if (bm3!=null) bm3.recycle(); int insamp=w/1000;if (insamp\<2) {insamp=2;} o.inJustDecodeBounds = false; o.inPreferQualityOverSpeed = false; o.inSampleSize=insamp; o.inPreferredConfig = Bitmap.Config.ARGB\_8888; o.inDither=false; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //Disable Dithering mode o.inPurgeable=true; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //Tell to gc that whether it needs free memory, the Bitmap can be cleared o.inInputShareable=true;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //Which kind of reference will be used to recover the Bitmap data after being clear, when it will be used in the future o.inTempStorage=new byte[32 \* 1024];

If you don’t think this is possible in Lua, can you think of some workaround? As long as I can get the image loaded without crashing the device I can take it from there.

For this app, the photos are coming from the camera, and users have to remember to modify the resolution in the camera app to not crash my app. Is there a way to select a resolution or set maximum picture measurements? That would solve it for this app. 

I’m unable to pay for Enterprise I’m afraid, so I can’t use plugins. If it turns out a plugin is required to make this work, could an exception be made so that asking for a photo will function in Corona?

to do it in native lua would require you write your own jpg decode/encode – seems impractical.

i assume you’ve got largeHeap=true, right? (tho that wouldn’t affect iOS)

and have you tried manually setting isFullResolution=false in newImage()? (maybe default has changed?)

have you filed a bug?  the newImage() docs and its ilk all have gotcha sections with stuff like “on android images are downsampled to 2048x2048” so that texture memory fits – the clear implication being that Corona must first be able to at least LOAD the larger-than-2048 image if it’s then to downsample it.  (that is, there’s nothing in the docs for either A/iOS that say >2048 images can’t be loaded at all)   ought to be pretty easy to build a test case with a single known large image that fails.

Yes, I have of course read the gotchas in the documentation. It’s nice that they’ve updated the text on 2048x2048 texture size to read better and added a note on the heap in the last few days. The recommendation that you "don’t load images larger than 2048x2048 doesn’t help anyone to load a photo taken by the camera, though, since almost all camera since a few years ago have larger resolutions than that.

It would have helped if they suggested setting largeHeap=true in build.settings there instead, because this at least gets capturePhoto to file, load file to newImage   working on devices that have lots of RAM! Thanks for the suggestion dave :slight_smile:

Does this help?

http://forums.coronalabs.com/topic/51789-displaysave-is-it-asynchronous/

I’m loading an image from the camera or photo library, then resizing it immediately, saving it, then opening that resized one later in the app.  It seems to work fine on every device I’ve tried so far (iPhone 5S, iPhone 6, iPhone 6 Plus, iPad 3, and several Android devices including a Droid Incredible from several years ago running Android 2.3.4).

Thanks,

Dave

to do it in native lua would require you write your own jpg decode/encode – seems impractical.

i assume you’ve got largeHeap=true, right? (tho that wouldn’t affect iOS)

and have you tried manually setting isFullResolution=false in newImage()? (maybe default has changed?)

have you filed a bug?  the newImage() docs and its ilk all have gotcha sections with stuff like “on android images are downsampled to 2048x2048” so that texture memory fits – the clear implication being that Corona must first be able to at least LOAD the larger-than-2048 image if it’s then to downsample it.  (that is, there’s nothing in the docs for either A/iOS that say >2048 images can’t be loaded at all)   ought to be pretty easy to build a test case with a single known large image that fails.

Yes, I have of course read the gotchas in the documentation. It’s nice that they’ve updated the text on 2048x2048 texture size to read better and added a note on the heap in the last few days. The recommendation that you "don’t load images larger than 2048x2048 doesn’t help anyone to load a photo taken by the camera, though, since almost all camera since a few years ago have larger resolutions than that.

It would have helped if they suggested setting largeHeap=true in build.settings there instead, because this at least gets capturePhoto to file, load file to newImage   working on devices that have lots of RAM! Thanks for the suggestion dave :slight_smile:

Does this help?

http://forums.coronalabs.com/topic/51789-displaysave-is-it-asynchronous/

I’m loading an image from the camera or photo library, then resizing it immediately, saving it, then opening that resized one later in the app.  It seems to work fine on every device I’ve tried so far (iPhone 5S, iPhone 6, iPhone 6 Plus, iPad 3, and several Android devices including a Droid Incredible from several years ago running Android 2.3.4).

Thanks,

Dave