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

Hi guys,

I’ve been searching around google and I haven’t found the answer to my question so I am posting this.

Goal: Make a basic photo editing app which includes cropping.

Potential problem: If the device I’m using has a camera that takes photos at a higher resolution than my device screen, how can I save the photo back to storage at the original resolution of the photo?

For example:

Device: iPhone 5

Device resolution: 640x1136

Photo resolution: 2448x3264 

  1. Import a new photo from the camera using the media.capturePhoto()

  2. Do various photo editing tasks…

  3. Save photo to external storage.

How can I do number 3? All the solutions I’ve seen for saving out images involve using display.save() or some sort. If I were to use this then the resolution of the saved photo would be greatly reduced because in order to display all of the photo on the device screen I would have to scale it way down.

Is it too far of a stretch to use corona for a photo editing app or am I missing something obvious?

Thanks!

Hi @spacewolf,

I just tested using display.save() on a display group containing an image that extended far outside the content area, and it worked fine (at least in the Mac Simulator). The entire image was saved, in its full resolution, when using the example code that we show in the docs:

http://docs.coronalabs.com/api/library/display/save.html

This should allow you to do what you need. Of course, if you want the user to see the entire photo while they’re “editing” it, then yes, you’ll need to scale it down and then scale it back up immediately before it gets saved.

Take care,

Brent

Thanks for you reply Brent! 

Would you be able to confirm this on a device? According to the documentation in the link you sent me:

 If the object is a display group, all children are also rendered. The object to be saved must be on the screen and fully within the screen boundaries.

I’m a little bit wary since the documentation says contrary! :slight_smile:

Hi @spacewolf,

It appears to work fine when I test on my iPhone5 using the following simple code:

[lua]

local bigGroup = display.newGroup()

local testimg = display.newImageRect( bigGroup, “big-logo.png”, 2963, 958 )

testimg.x, testimg.y = display.contentCenterX, display.contentCenterY

local function test()

   local t2 = display.newImage( “entireGroup.png”, system.DocumentsDirectory, 0, 0, true )

end

local function saveWithDelay()

   print(“SAVED!”)

   display.save( bigGroup, { filename=“entireGroup.png”, baseDir=system.DocumentsDirectory, isFullResolution=true } )

   display.remove( bigGroup )

   timer.performWithDelay( 500, test )

end

timer.performWithDelay( 1000, saveWithDelay )

[/lua]

As you can see, the image added to the group is much larger than the screen, and when I load it from the directory where I saved it and place it on screen, it’s the same huge size as when I saved it. If you find otherwise in your tests, let me know.

In the meantime, I’m going to edit the docs on that point. I think that note may be a legacy reference from G1.0.

Thanks,

Brent

This is great! I will give it a try :slight_smile:

Hi @spacewolf,

Just FYI, there may be some inconsistency on this with certain Android devices. We’re still doing a bit of testing. Not sure if your target platform is iOS-only or both iOS and Android, but in any case, it may be worth holding off until we can complete our testing.

Thanks,

Brent

I am first targeting iOS but it would be great if it all worked on android too :slight_smile:

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.

Hi @spacewolf,

I just tested using display.save() on a display group containing an image that extended far outside the content area, and it worked fine (at least in the Mac Simulator). The entire image was saved, in its full resolution, when using the example code that we show in the docs:

http://docs.coronalabs.com/api/library/display/save.html

This should allow you to do what you need. Of course, if you want the user to see the entire photo while they’re “editing” it, then yes, you’ll need to scale it down and then scale it back up immediately before it gets saved.

Take care,

Brent

Thanks for you reply Brent! 

Would you be able to confirm this on a device? According to the documentation in the link you sent me:

 If the object is a display group, all children are also rendered. The object to be saved must be on the screen and fully within the screen boundaries.

I’m a little bit wary since the documentation says contrary! :slight_smile:

Hi @spacewolf,

It appears to work fine when I test on my iPhone5 using the following simple code:

[lua]

local bigGroup = display.newGroup()

local testimg = display.newImageRect( bigGroup, “big-logo.png”, 2963, 958 )

testimg.x, testimg.y = display.contentCenterX, display.contentCenterY

local function test()

   local t2 = display.newImage( “entireGroup.png”, system.DocumentsDirectory, 0, 0, true )

end

local function saveWithDelay()

   print(“SAVED!”)

   display.save( bigGroup, { filename=“entireGroup.png”, baseDir=system.DocumentsDirectory, isFullResolution=true } )

   display.remove( bigGroup )

   timer.performWithDelay( 500, test )

end

timer.performWithDelay( 1000, saveWithDelay )

[/lua]

As you can see, the image added to the group is much larger than the screen, and when I load it from the directory where I saved it and place it on screen, it’s the same huge size as when I saved it. If you find otherwise in your tests, let me know.

In the meantime, I’m going to edit the docs on that point. I think that note may be a legacy reference from G1.0.

Thanks,

Brent

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.

This is great! I will give it a try :slight_smile:

Hi @spacewolf,

Just FYI, there may be some inconsistency on this with certain Android devices. We’re still doing a bit of testing. Not sure if your target platform is iOS-only or both iOS and Android, but in any case, it may be worth holding off until we can complete our testing.

Thanks,

Brent

I am first targeting iOS but it would be great if it all worked on android too :slight_smile: