Autoscale Image to Fill Bounds but Maintain Aspect Ratio

I’m developing a login screen that will be viewed on devices of different resolution. There is a photogenic background graphic, and it would look best if we could maintain the aspect ratio while filling the background (i.e., a very tall monitor would make the image fit the height, and the sides would be cropped off. Similarly, a very wide monitor would make the image fit the width, and the top/bottom of the image would be cut off).

The “No Stretch” mode doesn’t work because as you scale between different monitors, you’ll get a lot of cropping or lots of blank space around the edges of the image. The other options don’t work because they’ll wreck the image aspect ratio as screens change aspect ratio.

On the desktop on Windows 10 this is trivially easy, you just choose “Fill” mode for the fit, and it re-sizes and centers the image. How do I accomplish the same with Ignition?

I’m not sure if theres a better way to do what you want, but one solution I can think of is to use a paintable canvas component. There, you can use the Java graphics drawImage() function and do some calculations so you make make the image the right size and then draw it.

I finally got back to this topic and found a solution. The key was finding the ImageLoader function, which lets me find the original aspect ratio of the image regardless of however its currently scaled.

from com.inductiveautomation.ignition.client.images import ImageLoader

#Find Aspect Ratio of Component
imgComponent = system.gui.getWindow("Main Windows/General/Login").rootContainer.getComponent("Image")
imgComponentW = imgComponent.getWidth()
imgComponentH = imgComponent.getHeight()
imgComponentRatio = float(imgComponentW) / float(imgComponentH)

#Find Aspect Ratio of Original Image
filename = imgComponent.getPath()
img = ImageLoader.getInstance().loadImage(filename)
imgW = img.getWidth()
imgH = img.getHeight()
imgRatio = float(imgW) / float(imgH)

##Find Component Image Size in "% Bounds"
#if (imgComponentRatio >= imgRatio):
#	fillW = 100
#	fillH = int(fillW / imgRatio * imgComponentRatio)
#else:
#	fillH = 100
#	fillW = int(fillH * imgRatio / imgComponentRatio)
#
## Set Strech Mode to "% Bounds"
#imgComponent.setStretchMode(3)

#Find Component Image Size in "Pixel Size"
if (imgComponentRatio >= imgRatio):
	fillW = imgComponentW
	fillH = int(fillW / imgRatio )
else:
	fillH = imgComponentH
	fillW = int(fillH * imgRatio )

# Set Strech Mode to "Parameters"
imgComponent.setStretchMode(2)

#Set Component Image Bounds
imgComponent.setStretchHeight(fillH)
imgComponent.setStretchWidth(fillW)
3 Likes

Hi,

Thank you so much for this! It was really helpful but I found it wasn't quite working for me.

if (imgComponentRatio >= imgRatio):

had to be

if (imgComponentRatio <= imgRatio):

instead.

1 Like