question about display.newImageRect()

This API can be used in two ways to handle dynamic scaling:

  1. Display the correct resolution image based on the resolution of the device (using multiple image files).
  2. Resize higher resolution images to fit the existing content width and height. Since this only uses one high resolution image, it uses more texture memory than method 1, but handles the case of sizing an image that will be used on multiple device resolutions.

My question is there is a lot of devices in both Android and iOS with different resolution, so are there any ways to fit the existing content width and height of all devices??? or we have to create a lot of images with different size for each device with its own resolution ??

Resizing the image up or down takes processing power.  Bigger images take more time to resize than smaller images.  Resizing harms the look of the images, in particular when resizing up.

The idea behind Corona SDK’s dynamic scaling is that you have the option of providing images that more closely fit the device you’re building for.

Your typical config.lua might look like:

application = {    content = {       width = 320,       height = 480,       scale = "letterBox",       fps = 60,       imageSuffix = {          ["@2x"] = 1.5,          ["@4x"] = 3.0,       },    }, }

With this in mind you would provide 3 sets of images.  A base image that looks good on small screens, an image with a prefix of @2x which is generally (but doesn’t have to be) 2x the base image and a high resolution set with a prefix of @4x that would look good on the bigger screens, i.e.:  background.png, background@2x.png, background@4x.png.

With the imageSuffix block scaling at 1.5x and 3.0x, you in effect get the following

Devices with a width < 480   use the base image.

Devices with a width of 480 to < 960, use the @2x image.

Devices with a width >=960  use the @4x image.

Old iPhone 3Gs?  Small image

iPhone 4-6, Kindle Fire, Google Nexus 7, iPad 2, iPad Mini, any 720p device etc. use the @2x image

iPhone 6+, iPad 3, 4, Air, and any 1080p device would use the @4x image.

By matching the device to an image size closer to its screen resolution it does several things for you.  First, it will produce a sharper image since you are minimizing the amount of resampling that has to go on.  Second since older devices tend to have less memory and slower CPU/GPU’s, by letting them work on images in the neighborhood of their screens size you will run into less performance problems.  Texture Memory quadrupals with each doubling of the image size.  In other words a 512x512 pixel image uses 1MB of texture memory.  A 1024x1024 pixel image uses 4MB of texture memory.  A 2048x2048 pixel image uses 16MB of texture memory.

If you load that 2048px image which is a great size for a Retina iPad or a 1080x1980 screen on an iPhone 3gs, it’s going to seriouslly struggle.  That one image took an 8th of the total system memory (and you have to remember a bunch of it belongs to the OS and not your app).

The draw backs to this is of course, you have to make 3 versions of every image which takes time on your side and you are making  your app bundle size larger by including all these graphics.  But it’s a good tradeoff.

Rob

thanks for your help but i still have some questions now, can you tell the general size or if possible the exact size of 3 sets of images,

Not with display.newImageRect().  You could use display.newImage() to load in the image at full size, and get the .width and .height parameters from it and then get rid of the image probably before the screen updated.  Kind of a hackish way to do it.

Rob

I also have a  question…

I have hundreds of graphics and my app is at 37MB so far, with one set!

What am I to do? Including @2x and @4x is going to take my app into the hundreds of MB’s

There are a few things you can do.

  1. For any solid image (i.e. no transparent areas, like a background) use JPEG not PNG.  JPEGs compress much better and in particular with the @2x and @4x images, it can save a lot.  But JPEG doesn’t support transparency, which limits its functionality. 

  2. Look at the images and see if you can live without the larger version.  You might find your @2x graphic looks fine on the largest screens you support.  Don’t include the @4x if you don’t need it.

  3. Make sure the images are stripped of any meta data.  Images (JPEGs and PNGs) have blocks of information in them for things like captions (IPTC), camera data (EXIF), color profiles and so on.  These can end up adding 30-50kbytes of information to an image.  It adds up quickly.  when using Photoshop, make sure to “Save for Web” or “Save for Web and Devices” depending on the version of Photoshop you are using.  You can strip out almost all this metadata.

  4. Look for opportunities to combine multiple images into a single image sheet.  In particular if you use something like TexturePacker, it can overlap the transparent areas to maximize the savings.

Thanks for the info Rob, good advice.

Resizing the image up or down takes processing power.  Bigger images take more time to resize than smaller images.  Resizing harms the look of the images, in particular when resizing up.

The idea behind Corona SDK’s dynamic scaling is that you have the option of providing images that more closely fit the device you’re building for.

Your typical config.lua might look like:

application = { &nbsp;&nbsp; content = { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; width = 320, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; height = 480, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; scale = "letterBox", &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fps = 60, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; imageSuffix = { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ["@2x"] = 1.5, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ["@4x"] = 3.0, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }, &nbsp;&nbsp; }, }

With this in mind you would provide 3 sets of images.  A base image that looks good on small screens, an image with a prefix of @2x which is generally (but doesn’t have to be) 2x the base image and a high resolution set with a prefix of @4x that would look good on the bigger screens, i.e.:  background.png, background@2x.png, background@4x.png.

With the imageSuffix block scaling at 1.5x and 3.0x, you in effect get the following

Devices with a width < 480   use the base image.

Devices with a width of 480 to < 960, use the @2x image.

Devices with a width >=960  use the @4x image.

Old iPhone 3Gs?  Small image

iPhone 4-6, Kindle Fire, Google Nexus 7, iPad 2, iPad Mini, any 720p device etc. use the @2x image

iPhone 6+, iPad 3, 4, Air, and any 1080p device would use the @4x image.

By matching the device to an image size closer to its screen resolution it does several things for you.  First, it will produce a sharper image since you are minimizing the amount of resampling that has to go on.  Second since older devices tend to have less memory and slower CPU/GPU’s, by letting them work on images in the neighborhood of their screens size you will run into less performance problems.  Texture Memory quadrupals with each doubling of the image size.  In other words a 512x512 pixel image uses 1MB of texture memory.  A 1024x1024 pixel image uses 4MB of texture memory.  A 2048x2048 pixel image uses 16MB of texture memory.

If you load that 2048px image which is a great size for a Retina iPad or a 1080x1980 screen on an iPhone 3gs, it’s going to seriouslly struggle.  That one image took an 8th of the total system memory (and you have to remember a bunch of it belongs to the OS and not your app).

The draw backs to this is of course, you have to make 3 versions of every image which takes time on your side and you are making  your app bundle size larger by including all these graphics.  But it’s a good tradeoff.

Rob

thanks for your help but i still have some questions now, can you tell the general size or if possible the exact size of 3 sets of images,

Not with display.newImageRect().  You could use display.newImage() to load in the image at full size, and get the .width and .height parameters from it and then get rid of the image probably before the screen updated.  Kind of a hackish way to do it.

Rob

I also have a  question…

I have hundreds of graphics and my app is at 37MB so far, with one set!

What am I to do? Including @2x and @4x is going to take my app into the hundreds of MB’s

There are a few things you can do.

  1. For any solid image (i.e. no transparent areas, like a background) use JPEG not PNG.  JPEGs compress much better and in particular with the @2x and @4x images, it can save a lot.  But JPEG doesn’t support transparency, which limits its functionality. 

  2. Look at the images and see if you can live without the larger version.  You might find your @2x graphic looks fine on the largest screens you support.  Don’t include the @4x if you don’t need it.

  3. Make sure the images are stripped of any meta data.  Images (JPEGs and PNGs) have blocks of information in them for things like captions (IPTC), camera data (EXIF), color profiles and so on.  These can end up adding 30-50kbytes of information to an image.  It adds up quickly.  when using Photoshop, make sure to “Save for Web” or “Save for Web and Devices” depending on the version of Photoshop you are using.  You can strip out almost all this metadata.

  4. Look for opportunities to combine multiple images into a single image sheet.  In particular if you use something like TexturePacker, it can overlap the transparent areas to maximize the savings.

Thanks for the info Rob, good advice.