Is it possible to turn Dynamic Content Scaling off / on

General question

The display object implements automatic scaling / dynamic content scaling, according to the config.lua setup.

Generally this is what you want, but is it possible for this scaling be turned off, for a bit of code, then later turned on again?

No I’m afraid that is not how it works.  Auto-scaling is an all-the-time deal.

That said, you can handle it all yourself if you want by choosing “none” as the scaling style in config.lua.

Having answered above, perhaps you can give us an example of a specific thing you’re trying to achieve.  We may still be able to help you achieve it.

i.e. In what specific way is auto-scaling foiling you.

Sure.

I’m cropping an image. I make a newSnapshot that is smaller than the image, add the image to it, use display.save to write snapshot contents to file.

The output file looks correct in terms of what has been cropped.

However by looking in the sandbox, I can see the dimensions of the output file vary depending on the device.

I attach a main.lua and an image a.jpg - when you run the code it makes b.jpg - the cropped output file.

a.jpg is 2448x2448, I am cropping 2048x2048 out of it.

I would expect the output file to be 2048x2048 but it is not.

On smaller devices the output file is smaller. For example on a Nexus One it is 1228x1228

I can live with that.

On larger devices, the output file is very large, on an iPad Air it is 3495x3495

That’s no good…

I suspect that display.save is autoscaling the output file.

I wish it didn’t.

Code attached - and also below;

local function cropImageOnDevice(filename, newFileName, cropX, cropY, cropW, cropH) local photo=display.newImage( filename, system.TemporaryDirectory ) -- set the masking container local tempGroup = display.newSnapshot(cropW, cropH ) tempGroup.x = 0 tempGroup.y = 0 tempGroup.anchorX = 0 tempGroup.anchorY = 0 tempGroup.group:insert(photo) local x0 = cropW \* -0.5 local y0 = cropH \* -0.5 local x = x0 + ( cropX \* -1 ) local y = y0 + ( cropY \* -1 ) photo.x = x photo.y = y photo.anchorX = 0 photo.anchorY = 0 -- save the cropped image display.save( tempGroup, { filename = newFileName, baseDir = system.TemporaryDirectory, isFullResolution = true } ) tempGroup:removeSelf() tempGroup = nil end -- crop image 2448x2448 to 2048x2048 cropImageOnDevice("a.jpg", "b.jpg", 200, 200, 2048, 2048) -- on a Nexus One image is 1228x1228 -- on an iPad Air image is 3495x3495

Close, but not quite.  As I understand it, if you are using any kind of scaling (i.e. not ‘none’), the save will vary based on the true resolution of your device.  i.e. It saves at full resolution (for the displayed rectangle).

Thus, lower resolution devices produce smaller images, and higher resolution devices produce larger ones.

This of course has the drawback of creating massive images on iPad Air and even worse on iPad Pro.

So, what is the solution?

  1. Decide on an ‘ideal’ resolution.

Ex: 200 x 300

  1. Detect the true resolution of the device and the current scaling factor. (Tip: Assuming you are using leterbox scaling, both x and y factors will be the same, so just examine one or the other).

Ex: Let’s make up a scaling factor of 2.5 for this talk.

  1. Calculate a true scale factor based on ideal width (or height), content width, and display scaling factor in use.

  2. If the true scaling factor is > 1.0 do no more ‘special steps’ and skip to the save.

  3. If the true scaling factor is <  1.0 then just before saving, downscale the group:

    local idealWidth = 200 local scaleFactor = idealWidth / (tempGroup.contentWidth * display.contentScaleX) if( scaleFactor < 1 ) then tempGroup:scale( scaleFactor, scaleFactor ) end display.save( tempGroup, { filename = newFileName, baseDir = system.TemporaryDirectory } ) – (optionally) Put scaling back if you need it to be reset for future use. tempGroup.xScale = 1 tempGroup.yScale = 1

Note: isFullResolution is deprecated and since you’re downscaling, you can probably leave that off.

Note: I updated my example above to account for the ‘ideal’ width/height factor.

I did the above code in my head so hopefully I didn’t flip any calculations.   I did need to correct it a few times before posting this comment.

In any case, in a nutshell, you need to be aware of the true pixel size of your image and adjust it via scaling before saving.  This will get you close to the ideal size you want.

I see what you are saying - and it’s correct. unfortunately my bit isn’t - when I tested on more devices, there were always problems (i think) to do with scaling. On some x,y was true x,y on others they seemed to shift.

I don’t think corona can do cropping.

really there should be an option to manipulate images “in memory”, without the scaling. just plain straight forward image manipulations.

With cameras taking images much bigger than the screen - tying all image manipulations to screen does not make sense.

No I’m afraid that is not how it works.  Auto-scaling is an all-the-time deal.

That said, you can handle it all yourself if you want by choosing “none” as the scaling style in config.lua.

Having answered above, perhaps you can give us an example of a specific thing you’re trying to achieve.  We may still be able to help you achieve it.

i.e. In what specific way is auto-scaling foiling you.

Sure.

I’m cropping an image. I make a newSnapshot that is smaller than the image, add the image to it, use display.save to write snapshot contents to file.

The output file looks correct in terms of what has been cropped.

However by looking in the sandbox, I can see the dimensions of the output file vary depending on the device.

I attach a main.lua and an image a.jpg - when you run the code it makes b.jpg - the cropped output file.

a.jpg is 2448x2448, I am cropping 2048x2048 out of it.

I would expect the output file to be 2048x2048 but it is not.

On smaller devices the output file is smaller. For example on a Nexus One it is 1228x1228

I can live with that.

On larger devices, the output file is very large, on an iPad Air it is 3495x3495

That’s no good…

I suspect that display.save is autoscaling the output file.

I wish it didn’t.

Code attached - and also below;

local function cropImageOnDevice(filename, newFileName, cropX, cropY, cropW, cropH) local photo=display.newImage( filename, system.TemporaryDirectory ) -- set the masking container local tempGroup = display.newSnapshot(cropW, cropH ) tempGroup.x = 0 tempGroup.y = 0 tempGroup.anchorX = 0 tempGroup.anchorY = 0 tempGroup.group:insert(photo) local x0 = cropW \* -0.5 local y0 = cropH \* -0.5 local x = x0 + ( cropX \* -1 ) local y = y0 + ( cropY \* -1 ) photo.x = x photo.y = y photo.anchorX = 0 photo.anchorY = 0 -- save the cropped image display.save( tempGroup, { filename = newFileName, baseDir = system.TemporaryDirectory, isFullResolution = true } ) tempGroup:removeSelf() tempGroup = nil end -- crop image 2448x2448 to 2048x2048 cropImageOnDevice("a.jpg", "b.jpg", 200, 200, 2048, 2048) -- on a Nexus One image is 1228x1228 -- on an iPad Air image is 3495x3495

Close, but not quite.  As I understand it, if you are using any kind of scaling (i.e. not ‘none’), the save will vary based on the true resolution of your device.  i.e. It saves at full resolution (for the displayed rectangle).

Thus, lower resolution devices produce smaller images, and higher resolution devices produce larger ones.

This of course has the drawback of creating massive images on iPad Air and even worse on iPad Pro.

So, what is the solution?

  1. Decide on an ‘ideal’ resolution.

Ex: 200 x 300

  1. Detect the true resolution of the device and the current scaling factor. (Tip: Assuming you are using leterbox scaling, both x and y factors will be the same, so just examine one or the other).

Ex: Let’s make up a scaling factor of 2.5 for this talk.

  1. Calculate a true scale factor based on ideal width (or height), content width, and display scaling factor in use.

  2. If the true scaling factor is > 1.0 do no more ‘special steps’ and skip to the save.

  3. If the true scaling factor is <  1.0 then just before saving, downscale the group:

    local idealWidth = 200 local scaleFactor = idealWidth / (tempGroup.contentWidth * display.contentScaleX) if( scaleFactor < 1 ) then tempGroup:scale( scaleFactor, scaleFactor ) end display.save( tempGroup, { filename = newFileName, baseDir = system.TemporaryDirectory } ) – (optionally) Put scaling back if you need it to be reset for future use. tempGroup.xScale = 1 tempGroup.yScale = 1

Note: isFullResolution is deprecated and since you’re downscaling, you can probably leave that off.

Note: I updated my example above to account for the ‘ideal’ width/height factor.

I did the above code in my head so hopefully I didn’t flip any calculations.   I did need to correct it a few times before posting this comment.

In any case, in a nutshell, you need to be aware of the true pixel size of your image and adjust it via scaling before saving.  This will get you close to the ideal size you want.

I see what you are saying - and it’s correct. unfortunately my bit isn’t - when I tested on more devices, there were always problems (i think) to do with scaling. On some x,y was true x,y on others they seemed to shift.

I don’t think corona can do cropping.

really there should be an option to manipulate images “in memory”, without the scaling. just plain straight forward image manipulations.

With cameras taking images much bigger than the screen - tying all image manipulations to screen does not make sense.