Recommendation for @2x suffix.

Hi everyone in this topic I would like to ask for recommendations for @2x suffix in a 768*1024 letterbox content area.

I am a bit confused with the variety of screens and I would not know if I would assign a 1.25, 1.5 or 2. I would also like to know if it is necessary to use @2x and @4x?

Thanks
DoDi

You can make this decision easily by doing this:
 

  1. Decide on the resolution you want to design for as your primary/best-case resolution and use that as the resolution in config.lua

  2. Design your 1x art to fit that resolution while also considering letterbox scaling.

  3. Provide 2X (and optionally 3x) artwork and use a standard multiple of 2.
      
    Tip: Always make your art at the highest resolution and scale it down to produce the 1X art.ose details.  
     
     
    Example
    I like to design my games using these rules (assuming I must use 1x and 2x images which I rarely do):

  4. I choose my ideal resolution as 640x960 + Letterbox.  My config.lua file looks like this: 

    application = { content = { width = 640, height = 960, scale = “letterbox”, fps = 60, }, – Dynamic Image Selection imageSuffix = { ["@2x"] = 1.5, – Amended after Rob’s excellent post below :slight_smile: was 2.0 }, }

  5. My full-screen background images have these resolutions:

  • 2x - 1440 x 2772;  This is a safe region of 1280 x 1920 surrounded by a bleed area for letterboxing.
  • 1x - I  scale my 2x art down to 720 x 1386  This is a safe region of 640 x 960 surrounded by a bleed area for letterboxing.

I made a free tool for helping you figure out the ideal background image size based on your ideal design resolution:

https://forums.coronalabs.com/topic/73041-ideal-scaling-calculator/

If you can’t figure out how to use it and you want to know the right size, just post back your ideal resolution and I’ll get back to you later.

Actually, I had a video attached to that thread and I tested the tool with the 768 x 1024 target you mentioned.

The 1x ideal full screen image size for that resolution is: 768 x 1664. 

ideal.png

I failed to answer one of your questions.  

You asked if 2X and 4X are necessary.

The answer is, “it depends”.

If you are designing at a low resolution 768 x 1024 and if you expect folks to run your app on iPhoneX, iPad Pro and other huge resolution devices, then probably.

However, if you test your app with 1X graphics on those devices (or a few) and you feel it looks OK, then no you don’t need all that extra art.

Also, you can be selective.  You don’t need to provide 2X++ art for every image.  Maybe just some of the images look terrible when scaled up.  Just provide 2X++ for them.

I know… you may be thinking… you called my resolution low but you are using 640 x 960 and that is lower!  It is, it is.  I do this because:

  • 640 x 960 is the same aspect ratio as 320x480 which I have used for years (the aspect ratio).
  • 640 x 960 is still easily divisible into meaningful block sizes of 80 x 80 pixels and I design a lot of apps that use blocks and grids.
  • All my artwork is actually 2X.  i.e. I display my backgrounds at 720 x 1386 but the images are 1440 x 2772
    • I can get away with this because I know that 640x960 will be upscaled on most devices to 2X or more.
    • This is a nice middle ground that simplifies my design and saves me binary space for 1x images I probably wouldn’t even use.

Wow, that’s a lot of responses. :smiley:

The number associated with those image suffixes (@2x, @4x, etc.) is the scale factor. You can find out the current scale factor and image suffix that your device is using via:

print( "scale factor: "..(display.pixelWidth/display.contentHeight) ) print( "display.imageSuffix = "..display.imageSuffix )

(Unless I am mistaken, the documentation has the wrong formula for calculating the scale factor and the formula that I just used is the correct one.)

The number that you assign to each image suffix simply means at which scale factor you want Corona to start using images with that specific image suffix. If you assign 1.25 to @2x, it means that Corona will load images with @2x suffix if the display’s scale factor is 1.25 or higher. Corona will automatically select the highest suffix.

In my projects, I’ve usually assigned 1.5 and 3 to @2x and @4x. I do this in order to change to higher resolution images sooner rather than later. For instance, if you have a large image that is 1024x1024px and you use a scale factor of 2 for @2x, it means that once the image reaches the size of 2048x2048px, then Corona would swap in the higher resolution image. This would, however, mean that the image would be 4 times larger than the @1x variant and it would likely become blurry when it is scaled too large. By substituting it already at 1.5 instead of 2, the resulting images are more likely to be crisp.

Now it becomes a question about balance and design. The more image suffixes you include in your project, the crisper your images will look (as long as you’ve scaled them properly in your image editing software). However, more images means more work and they require more hard drive space. I use the same content area that @roaminggamer mentioned paired with @2x and @4x image suffixes at 1.5 & 3 and I feel they work the best for me, but you need to determine what works the best for you.

Let me take us all on a little bit of a historical journey. It’s a great example to explain what all those numbers in config.lua mean.

In the beginning, there was the iPhone 3s., It was 320x480. Early Android devices were that size, but it didn’t take long for Android makers to start the pixel size competition. I believe the Motorola Droid was a 480x854 px device. But lets hold off on that for a moment. Apple came along with the iPhone 4/4s family which doubled the screen from 320x480 to 640x960.  If you look at this config.lua:

 width = 320, height = 480, scale = "letterbox", imageSuffix = { ["@2x"] = 2.0, },

Then your 1x images would show on the iPhone 3 family, your @2x suffixed images would show on the iPhone 4 family. But on the Droid, it’s 1.5x bigger in width. Since 480 is less than 2.0 X 320 (640), the Droid would use the 1x images and not the @2x images. With digital images any time you size up images they become soft and blurry. The more you size up the worse it gets. Sizing down tends to maintain sharpness. So with the Droid in this example, the image gets sized up 50%.  Let’s look at another example. The first couple of versions of the Kindle Fire, were 600px x 1024px. With that config.lua, the Kindle Fire would still use the 1x image which would be scaled up 93%. This would lead to blurry displays. Given that 600 is almost 640 wouldn’t it be better to use the @2x image and scale it down 7%?

The fix for this is to not use 2.0, but instead something like 1.5.

 width = 320, height = 480, scale = "letterbox", imageSuffix = { ["@2x"] = 1.5, },

Now any screen that’s 480px or wider will pick up the @2x image and for the 480px motorola it’s scaled down 50% which is sharper than scaling up the 1x image 50%. For the 600px Kindle fire, it needs the higher res image, so it will properly pick up the @2x image and produce a better display.

Enter the early iPads at 768px wide. Using the above config.lua code, you’re going to scale up the image about 20%, which isn’t the greatest, but still it’s not too bad. Now consider the retina iPads at 1536px. Those @2x images are now going to be scaled up over 200% which is really bad. This is why most people now include @4x images. Using this config.lua:
 

 width = 320, height = 480, scale = "letterbox", imageSuffix = { ["@2x"] = 1.5, ["@4x"] = 3.0, },

Now any screen that’s 960px or wider will use the @4x images, sizing up and down as necessary. This means your retina iPads will get the @4x images, your 1080p devices will get the @4x images. 

Now if you tweak the width/height to be 768 and 1024, and you use @2x, you’re likely not going to need @4x images (though more device’s are becoming higher resolution). If you change the suffix to ["@2x"] = 2.0, then on your retina iPads, you will get the 2x images, but on a 1080p device like the iPhone 8 plus, you’re going to get the 1x image that has to be scaled up. To make the 1080p devices get the @2x image, you would actually use ["@2x"] = 1.4.

There is no “right” way to do this. There is what works best for you. But the basic premise that the more detail an image has, scaling images up is bad. Providing extra resolutions (@2x, @3x, @4x etc.) makes your upload size larger. Only you can figure out this balancing act. But when creating your artwork, you should always start with a large resolution and then resize them down to your other needs (even in Photoshop you don’t want to scale up images).

Rob

Wao! Thanks to everyone for your replies. I need to read everything well to be able to comment.

application = { content = { width = 768, height = 1024, scale = "letterbox", fps = 60, imageSuffix = { ["@2x"] = 1.2, ["@4x"] = 2.4, }, }, }

After reading I have decided to use this config.lua. I’m going to do several tests on several devices.

Oh man, thanks a million times!

I spent a whole day trying to figure out why the scale factor formula from the corona docs does not match the dynamic image selection and now I see that this is indeed the correct formula.

But it’s important to note that this bug only occurs when the default orientation is set to landscape. 

If it’s portrait then the corona docs formula is correct (display.pixelWidth / display.contentWidth), but in landscape mode you need to use this one (display.pixelWidth/display.contentHeight).

Can somebody from Corona confirm that this is indeed a bug in the docs?

Update: actually for me this one gives slightly more accurate results, after trying a bunch of devices: (display.pixelWidth / display.actualContentHeight)

1 Like

You can make this decision easily by doing this:
 

  1. Decide on the resolution you want to design for as your primary/best-case resolution and use that as the resolution in config.lua

  2. Design your 1x art to fit that resolution while also considering letterbox scaling.

  3. Provide 2X (and optionally 3x) artwork and use a standard multiple of 2.
      
    Tip: Always make your art at the highest resolution and scale it down to produce the 1X art.ose details.  
     
     
    Example
    I like to design my games using these rules (assuming I must use 1x and 2x images which I rarely do):

  4. I choose my ideal resolution as 640x960 + Letterbox.  My config.lua file looks like this: 

    application = { content = { width = 640, height = 960, scale = “letterbox”, fps = 60, }, – Dynamic Image Selection imageSuffix = { ["@2x"] = 1.5, – Amended after Rob’s excellent post below :slight_smile: was 2.0 }, }

  5. My full-screen background images have these resolutions:

  • 2x - 1440 x 2772;  This is a safe region of 1280 x 1920 surrounded by a bleed area for letterboxing.
  • 1x - I  scale my 2x art down to 720 x 1386  This is a safe region of 640 x 960 surrounded by a bleed area for letterboxing.

I made a free tool for helping you figure out the ideal background image size based on your ideal design resolution:

https://forums.coronalabs.com/topic/73041-ideal-scaling-calculator/

If you can’t figure out how to use it and you want to know the right size, just post back your ideal resolution and I’ll get back to you later.

Actually, I had a video attached to that thread and I tested the tool with the 768 x 1024 target you mentioned.

The 1x ideal full screen image size for that resolution is: 768 x 1664. 

ideal.png

I failed to answer one of your questions.  

You asked if 2X and 4X are necessary.

The answer is, “it depends”.

If you are designing at a low resolution 768 x 1024 and if you expect folks to run your app on iPhoneX, iPad Pro and other huge resolution devices, then probably.

However, if you test your app with 1X graphics on those devices (or a few) and you feel it looks OK, then no you don’t need all that extra art.

Also, you can be selective.  You don’t need to provide 2X++ art for every image.  Maybe just some of the images look terrible when scaled up.  Just provide 2X++ for them.

I know… you may be thinking… you called my resolution low but you are using 640 x 960 and that is lower!  It is, it is.  I do this because:

  • 640 x 960 is the same aspect ratio as 320x480 which I have used for years (the aspect ratio).
  • 640 x 960 is still easily divisible into meaningful block sizes of 80 x 80 pixels and I design a lot of apps that use blocks and grids.
  • All my artwork is actually 2X.  i.e. I display my backgrounds at 720 x 1386 but the images are 1440 x 2772
    • I can get away with this because I know that 640x960 will be upscaled on most devices to 2X or more.
    • This is a nice middle ground that simplifies my design and saves me binary space for 1x images I probably wouldn’t even use.

Wow, that’s a lot of responses. :smiley:

The number associated with those image suffixes (@2x, @4x, etc.) is the scale factor. You can find out the current scale factor and image suffix that your device is using via:

print( "scale factor: "..(display.pixelWidth/display.contentHeight) ) print( "display.imageSuffix = "..display.imageSuffix )

(Unless I am mistaken, the documentation has the wrong formula for calculating the scale factor and the formula that I just used is the correct one.)

The number that you assign to each image suffix simply means at which scale factor you want Corona to start using images with that specific image suffix. If you assign 1.25 to @2x, it means that Corona will load images with @2x suffix if the display’s scale factor is 1.25 or higher. Corona will automatically select the highest suffix.

In my projects, I’ve usually assigned 1.5 and 3 to @2x and @4x. I do this in order to change to higher resolution images sooner rather than later. For instance, if you have a large image that is 1024x1024px and you use a scale factor of 2 for @2x, it means that once the image reaches the size of 2048x2048px, then Corona would swap in the higher resolution image. This would, however, mean that the image would be 4 times larger than the @1x variant and it would likely become blurry when it is scaled too large. By substituting it already at 1.5 instead of 2, the resulting images are more likely to be crisp.

Now it becomes a question about balance and design. The more image suffixes you include in your project, the crisper your images will look (as long as you’ve scaled them properly in your image editing software). However, more images means more work and they require more hard drive space. I use the same content area that @roaminggamer mentioned paired with @2x and @4x image suffixes at 1.5 & 3 and I feel they work the best for me, but you need to determine what works the best for you.

Let me take us all on a little bit of a historical journey. It’s a great example to explain what all those numbers in config.lua mean.

In the beginning, there was the iPhone 3s., It was 320x480. Early Android devices were that size, but it didn’t take long for Android makers to start the pixel size competition. I believe the Motorola Droid was a 480x854 px device. But lets hold off on that for a moment. Apple came along with the iPhone 4/4s family which doubled the screen from 320x480 to 640x960.  If you look at this config.lua:

 width = 320, height = 480, scale = "letterbox", imageSuffix = { ["@2x"] = 2.0, },

Then your 1x images would show on the iPhone 3 family, your @2x suffixed images would show on the iPhone 4 family. But on the Droid, it’s 1.5x bigger in width. Since 480 is less than 2.0 X 320 (640), the Droid would use the 1x images and not the @2x images. With digital images any time you size up images they become soft and blurry. The more you size up the worse it gets. Sizing down tends to maintain sharpness. So with the Droid in this example, the image gets sized up 50%.  Let’s look at another example. The first couple of versions of the Kindle Fire, were 600px x 1024px. With that config.lua, the Kindle Fire would still use the 1x image which would be scaled up 93%. This would lead to blurry displays. Given that 600 is almost 640 wouldn’t it be better to use the @2x image and scale it down 7%?

The fix for this is to not use 2.0, but instead something like 1.5.

 width = 320, height = 480, scale = "letterbox", imageSuffix = { ["@2x"] = 1.5, },

Now any screen that’s 480px or wider will pick up the @2x image and for the 480px motorola it’s scaled down 50% which is sharper than scaling up the 1x image 50%. For the 600px Kindle fire, it needs the higher res image, so it will properly pick up the @2x image and produce a better display.

Enter the early iPads at 768px wide. Using the above config.lua code, you’re going to scale up the image about 20%, which isn’t the greatest, but still it’s not too bad. Now consider the retina iPads at 1536px. Those @2x images are now going to be scaled up over 200% which is really bad. This is why most people now include @4x images. Using this config.lua:
 

 width = 320, height = 480, scale = "letterbox", imageSuffix = { ["@2x"] = 1.5, ["@4x"] = 3.0, },

Now any screen that’s 960px or wider will use the @4x images, sizing up and down as necessary. This means your retina iPads will get the @4x images, your 1080p devices will get the @4x images. 

Now if you tweak the width/height to be 768 and 1024, and you use @2x, you’re likely not going to need @4x images (though more device’s are becoming higher resolution). If you change the suffix to ["@2x"] = 2.0, then on your retina iPads, you will get the 2x images, but on a 1080p device like the iPhone 8 plus, you’re going to get the 1x image that has to be scaled up. To make the 1080p devices get the @2x image, you would actually use ["@2x"] = 1.4.

There is no “right” way to do this. There is what works best for you. But the basic premise that the more detail an image has, scaling images up is bad. Providing extra resolutions (@2x, @3x, @4x etc.) makes your upload size larger. Only you can figure out this balancing act. But when creating your artwork, you should always start with a large resolution and then resize them down to your other needs (even in Photoshop you don’t want to scale up images).

Rob

Wao! Thanks to everyone for your replies. I need to read everything well to be able to comment.

application = { content = { width = 768, height = 1024, scale = "letterbox", fps = 60, imageSuffix = { ["@2x"] = 1.2, ["@4x"] = 2.4, }, }, }

After reading I have decided to use this config.lua. I’m going to do several tests on several devices.

Oh man, thanks a million times!

I spent a whole day trying to figure out why the scale factor formula from the corona docs does not match the dynamic image selection and now I see that this is indeed the correct formula.

But it’s important to note that this bug only occurs when the default orientation is set to landscape. 

If it’s portrait then the corona docs formula is correct (display.pixelWidth / display.contentWidth), but in landscape mode you need to use this one (display.pixelWidth/display.contentHeight).

Can somebody from Corona confirm that this is indeed a bug in the docs?

Update: actually for me this one gives slightly more accurate results, after trying a bunch of devices: (display.pixelWidth / display.actualContentHeight)