Tutorial: Fitting images to a size

Tutorial: Fitting images to a size

While developing an app, you often have to load an image whose dimensions are unknown. The question of how to scale the image is frequently asked, so let’s look at a simple function that will scale any image to fit in an arbitrary box.

For the inspiration for this function, let’s look at Adobe Photoshop’s File->Automate->Fit Image functionality. This action’s dialog box asks for a width, height and if you want to allow smaller images to be enlarged.

fitImage

The method that you will use is to first squeeze the image down until it fits the required height. If the new width fits inside the dimensions, then you are done and can scale the image. However, if the width is still outside the box, you need to recalculate the size based on the width to get it within the desired size.

With digital images, sizing up usually results in bad looking images. Since your image may be smaller than the box you are defining, you have a choice to enlarge, or leave it be (since the smaller image does fit within the bounds!)

The fitImage() function

The code for the fitImage function is:

The parameters that the function will take is a Corona Display object, typically the result of a display.newImage() API call. Next, is the desired width and height of the object after it’s scaled. Your image will fit within this box. The examples fit to a square, but you could select any rectangle that works for your app. The last parameter is a boolean that determines if you want smaller images upsized or not.

Inside the function, the first thing is to calculate the ratio of the image height to the desired height. If the height is larger than the desired height, this value will be less than 1. If the height is already smaller than the desired height, it will be greater than 1.

Next, multiple the width of the object by the new scale factor. If the new width is larger than the desired width, you need to shrink the image some more, so calculate a new scaleFactor based on the width instead of the height.

If the scaleFactor is greater than 1, then the image is actually smaller than the desired box. If you do not want small images enlarged, then simply return and do nothing.

The final step is to use the display:scale() method to actually size the image. Of course the image itself isn’t physically resized, it’s just scaled to fit the area.

Using the fitImage() function

Using the function is fairly straight forward:

Start by creating your display object using display.newImage(). Position the image where you want it. Now simply call the fitImage(), specifying the box size, width first, and finally if you want to allow enlarging.

Some more examples include:

This should result in something like:

screenshot

The first image, the moose, started out as a 2048 x 1638 image and was squeezed down to a 200×160 pixel image. There are two variants of the Icon.png image, a 57×57 image. In the one example, enlarging was not permitted, so it remained it’s original size. The second version, enlarging was allowed and you can see how pixelated the enlarged image is. Finally, the world.jpg image started out as a 320×480 image and was squeezed into a 133×200 image while maintaing the original image’s aspect ratio.

Conclusion

Now you can easily scale arbitrary sized images to fit within a space in your app.

Rob Miracle
[email protected]

Rob is the Developer Relations Manager for Corona Labs. Besides being passionate about helping other developers make great games using Corona, he is also enjoys making games in his spare time. Rob has been coding games since 1979 from personal computers to mainframes. He has over 16 years professional experience in the gaming industry.

10 Comments
  • Kerem
    Posted at 16:24h, 10 June

    What a timely tutorial! Thank you very much. This is most useful.

  • JCH_APPLE
    Posted at 22:03h, 10 June

    of course > should be the > sign

  • JCH_APPLE
    Posted at 22:08h, 10 June

    I mean that in my browser, in the sample, the &gt + semicolon is displayed NOT translated into >. In my first post i has been translated, that’s why my comment is curious

    • Rob Miracle
      Posted at 05:27h, 11 June

      You can thank our blog software for that. It likes to convert > to > even inside of code blocks. I’ve fixed it, but it’s likely to revert again if we make any updates.

      • Rob Miracle
        Posted at 05:28h, 11 June

        Er: > to >

  • gjaman
    Posted at 22:44h, 17 June

    I’d like to fit an image in a box but maintain the aspect ratio by cropping. I’m using a newContainer for each image. Is that the best solution?

    • Rob Miracle
      Posted at 15:12h, 19 June

      Yes, a newContainer would be the best option, or applying a mask manually.

  • Abdulaziz Al Zaabi
    Posted at 22:20h, 18 June

    Thanks Rob for the great tutorials.. this is really helpful one.

    I was trying to see how it will work for remote images but it was not working well. I am not sure if i should them after they load locally or you can do the same function for remote images,

    i got this error :

    File: main.lua
    Line: 10
    Attempt to index local ‘displayObject’ (a nil value)

    stack traceback:
    main.lua:10: in function ‘fitImage’
    main.lua:50: in main chunk

    i tried to do delay but still no luck..
    thanks
    Abdul

    • Rob Miracle
      Posted at 15:12h, 19 June

      It sounds like you’re not passing a valid display object in. We would need to see your code where you are loading the image and trying to call the function. Blog comments don’t handle posted code well. This would be best handled in the forums.

      Rob

  • Abdulaziz Al Zaabi
    Posted at 23:17h, 19 June

    i will post it in the forum ..

    thanks
    Abdul