display.save() unexpected behavior

Thank you so much Tom for the reply. However, 1) I am more concerned about the device and not much about the simulator. It would be nice if it behaved like the device though, and 2) something is still not right. Please read the following from http://docs.coronalabs.com/api/library/display/save.html:

_ "NOTE: When dynamic content scaling is enabled, display.save() saves the image in the device’s native resolution. For instance, if this method is used to save a 100 x 200 pixel display object, it will be saved as a 100 x 200 image on iPhone3 but it will be a 200 x 400 image on an iPhone4 (which would have the same content dimensions but more actual pixels). This is assuming that the config.lua file specifies the content width/height as 320x480 respectively."_

According to the above, 100 px would be 100px on iphone3, 200 on iphone4, and so on (given that 320x480 width/height and letterbox in config.lua does not change)…  = size / contentScale. But that’s not what we see in our examples above (on device). Please test the code I submitted in bug report or given above to see what it does.

About rounding: It’s hard to get 3 or more pixels added to the result by rounding alone, unless it’s been done more than once or being rounded first and then multiplied with a big number (in one of the tests above it changed 40px to 43)?

Please tell us if we are overlooking something here or better how does corona internally do the conversion math? Any details and specifics here would be a great help.

Tom @ Corona has been helpful in finding out more info on this and here is his reponse:

>>> *********

It turns out what you’re seeing is expected and here’s the reason why.

You are creating a virtual 320 x 480 display. For devices that are the exact ratio of that display (e.g., iPhone and iPhone 4), everything is fine. For the iPad and other devices, the ratio of those screens are not exact multiples. When you try to scale the group to compensate for the scaling factor, it doesn’t align on integer pixel boundaries nor does it scale exactly so it can be plus/minus one pixel in the scaled size. Now when you do a display.save of this object, it tries to capture a few extra pixels on all sides of the object so it doesn’t cut off any part of the object. This plus the inaccurate scaling size, will cause the resulting saved image to be off by a few pixels from the original.

If the intent is to redisplay the saved images on the screen, using display.newImageRect and specifying the expect width and height will correctly show the images.

I hope that explains what you’re seeing. I did test your code out on the simulator and a few devices and everything is working as expected.

****** <<<

I personally do not understand the need to “capturing extra pixel on sides” part, the cause of +3 pixels on iPad I guess, but here it is for any one interested in knowing what goes on under the hood. I’d still be interested in knowing why can’t we save exact sizes ± 1 pixel due to rounding. So if someone knows, please comment. I am not spending any more time on this issue.

Thanks

To help you understand what is going on, here is the output from your test code when running on the iPad Simulator.

dim# 1: 200,93.75 - 93,93 - file1 > 201, 201

dim# 2: 400,187.5 - 187,187 - file2 > 401, 401

dim# 3: 450,210.9375 - 210,210 - file3 > 450, 450

dim# 4: 480,225 - 225,225 - file4 > 480, 480

dim# 5: 500,234.375 - 234,234 - file5 > 499, 499

dim# 6: 1000,468.75 - 468,468 - file6 > 1001, 725

The ratio between the iPad screen and your 320x480 virtual screen is 0.46875. To compensate for this difference (so you can save an image that is the “exact” size of what is seen on the screen), your code adds the display object to a group and scales the group to 0.46875. This comes out to 93.75 pixels on each side. Display objects cannot be positioned on fractional pixel locations so the group is scaled to 93 instead of 93.75. This introduces some error as the result of the scaling process. You then use a display.save which now saves this object with extra pixels that resulted from the rounding process.

In all the cases I’ve seen on the simulator and actual devices, the pixel differences has only been a few pixels. When an object is saved we may error on the side of saving an extra pixel on all sides of the object to avoid cutting off the saved object. When testing with some smaller Android devices, the saved larger images were cropped because it exceeded the screen size. When testing in the simulator, you need to make sure you are zoomed all the way in because the saved image is based on the zoom level. (This may not be possible on the Windows simulator with large device skins.)

The bottom line is we can’t guarantee the size of the saved image down to the last pixel when you’re dealing with devices with dynamic scaling that is not whole integers multiple of the virtual screen that you’re trying to create.