Photo Editing and Corona: how can I save a photo at full resolution?

So I’ve made a frightening discovery.

If you have your config.lua width and height set to anything other than 320x480 then you will not get a saved image at the full resolution. 

I discovered this because I always set my project to iphone 4 resolution at 640x960 (which is double the standard iphone resolution) and display.save() saved images at only HALF full resolution. 

Hello @spacewolf,

This doesn’t seem correct, because the test I recently did used a higher w/h setting (768x1024) and I got full-res images saved.

Brent

Okay so I did some more digging and this is what I found:

If you choose a device on the corona simulator that matches the width and height set in your config.lua then display.save() will save the image back at full resolution. However, when you choose a device that has a different width and height, display.save() will save an image that is NOT full resolution. It seems to differ by the scale factor between the device resolution and what you set in your config.lua.

If you define your width and height in config.lua each to be 0, then corona will not use dynamic scaling for your content. This results in a huge mess on different device screen resolutions, but display.save() will work correctly every time regardless of device resolution.

So it seems corona dynamic scaling is interfering with the display.save() being able to save a display object at its full resolution when the width and height defined in config.lua is different than the device resolution.

How can I get around this? Is it a bug?

In our case, we have been able to successfully crop or re-scale image independently of the screen resolution and the width/height defined by the device by using the display.newSnapshop before working on the object itself.

Is there anyway to do this without the snapshot api? I don’t really feel like paying $600 a year (Pro subscription) for one feature :frowning:

You can’t test full resolution image manipulation in a simulator, it has GIGABYTES of memory. You must test it on device, which has 16, 32, 64 MEGABYTES of memory. A standard photo these days will want to alloc 36MB more memory of the memory available from these device maximum memory specs (with other apps having taken their share). So a test in simulator is no test at all.

Setting largeHeap=true in build.settings allows you to load large images with newImage(), for example those saved to file using capturePhoto. The image may have been scaled down to fit inside 2048x2048, which might not be what you want (easy to check with a print statement). Once loaded, you can then manipulate it and hopefully save it properly with display.save or similar.

Can anyone explain to me why the following code is causing my app to crash on device (but not simulator)?

[lua]

local tempGroup = display.newGroup( )
local photo = display.newImage(picName, system.DocumentsDirectory, display.contentWidth/2, display.contentHeight/2)
tempGroup:insert(photo)
display.save(tempGroup, {filename = picName, baseDir = system.DocumentsDirectory, isFullResolution = true})
display.remove(tempGroup)

[/lua]

Without seeing the error or any error messages in the console log, I’m going to guess that the save isn’t complete when you remove it.

Try dropping the display.remove inside of a timer.performWithDelay() of say 100ms

timer.performWtihDelay(100, function() display.remove(tempGroup); end)

Rob

Can anyone explain to me why the following code is causing my app to crash on device (but not simulator)?

[lua]

local tempGroup = display.newGroup( )
local photo = display.newImage(picName, system.DocumentsDirectory, display.contentWidth/2, display.contentHeight/2)
tempGroup:insert(photo)
display.save(tempGroup, {filename = picName, baseDir = system.DocumentsDirectory, isFullResolution = true})
display.remove(tempGroup)

[/lua]

Without seeing the error or any error messages in the console log, I’m going to guess that the save isn’t complete when you remove it.

Try dropping the display.remove inside of a timer.performWithDelay() of say 100ms

timer.performWtihDelay(100, function() display.remove(tempGroup); end)

Rob