10 June 2014
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.
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:
local function fitImage( displayObject, fitWidth, fitHeight, enlarge ) -- -- first determine which edge is out of bounds -- local scaleFactor = fitHeight / displayObject.height local newWidth = displayObject.width * scaleFactor if newWidth > fitWidth then scaleFactor = fitWidth / displayObject.width end if not enlarge and scaleFactor > 1 then return end displayObject:scale( scaleFactor, scaleFactor ) end
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:
local icon = display.newImage( "Icon.png" ) icon.x = 50 icon.y = 300 fitImage( icon, 200, 200, false )
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:
local moose = display.newImage( "moose.jpg" ) moose.x = display.contentCenterX moose.y = 100 fitImage( moose, 200, 200, false ) local icon2 = display.newImage( "Icon.png" ) icon2.x = display.contentWidth - 100 icon2.y = 300 fitImage( icon2, 200, 200, true ) local world = display.newImage( "world.jpg" ) world.x = 75 world.y = 450 fitImage( world, 200, 200, false )
This should result in something like:
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.
Now you can easily scale arbitrary sized images to fit within a space in your app.