# Proportionally resizing a Picture

1. 4 years ago

### Garry P

23 May 2014 Pre-Release Testers, Xojo Pro Europe (Torquay, UK)

I am trying to figure out how to proportionally resize a Picture object if it is greater than a certain width or height.

For instance, given a Picture object, p, how would I scale this if its width is > maxWidth or its height > maxHeight such that is fits these dimensions but maintains its aspect ration (i.e. is not distorted)?

Does anybody have a working code example to achieve this?

2. ### Michel B

23 May 2014 Pre-Release Testers RubberViews.com

@Garry P I am trying to figure out how to proportionally resize a Picture object if it is greater than a certain width or height.

For instance, given a Picture object, p, how would I scale this if its width is > maxWidth or its height > maxHeight such that is fits these dimensions but maintains its aspect ration (i.e. is not distorted)?

Does anybody have a working code example to achieve this?

```Sub Paint(g As Graphics, areas() As REALbasic.Rect)
if MyImage = Nil then return
Dim ratio as double
dim largeur as integer
if MyImage.Width > MyImage.Height then
ratio = me.width / MyImage.width
largeur = me.width
else
ratio = me.Height / MyImage.height
largeur = me.Height * (MyImage.Width / MyImage.Height)
end if

dim destheight as integer = MyImage.height * ratio
dim large as integer = MyImage.Width
dim haut as integer = MyImage.Height
g.DrawPicture(MyImage,(Me.width-largeur)/2,0,largeur,destheight,0,0,large,haut)

End Sub```

Whatever the proportions of the picture, it will be sized to the smaller dimension. For instance a portrait image in a landscape canvas will occupy the total height and be reduced accordingly to preserve its aspect ratio.

3. ### Kem T

23 May 2014 Pre-Release Testers, Xojo Pro, XDC Speakers New York

Here's the code I came up with:

```Function ResizeToFit(Extends p As Picture, maxWidth As Integer, maxHeight As Integer) As Picture
dim ratio as double = p.Width / p.Height

dim w1 as Integer = maxWidth
dim h1 as Integer = w1 / ratio

dim h2 as Integer = maxHeight
dim w2 as Integer = h2 * ratio

dim useWidth, useHeight as Integer

if h1 > maxHeight then
useWidth = w2
useHeight = h2

elseif w2 > maxWidth then
useWidth = w1
useHeight = h1

elseif ( maxHeight - h1 ) < ( maxWidth - w2 ) then
useWidth = w1
useHeight = h1

else
useWidth = w2
useHeight = h2

end if

dim newPict as new Picture( useWidth, useHeight, p.Depth )
newPict.Graphics.DrawPicture( p, 0, 0, newPict.Width, newPict.Height, 0, 0, p.Width, p.Height )

return newPict

End Function```
4. ### Garry P

23 May 2014 Pre-Release Testers, Xojo Pro Europe (Torquay, UK)

Both these methods work. Thanks for the inspiration.

I've distilled them into as few lines as code and am using it as class extension:

```Function ResizeToFit(Extends p as Picture, maxWidth as Integer, maxHeight as Integer) As Picture
' Calculate the scale ratio

dim ratio as Double = min( maxHeight/p.height, maxWidth/p.width)

' Calculate new size
dim w as integer = p.width * ratio
dim h as integer = p.height * ratio

' Create a new picture to return
dim newPic as new Picture(w, h, 32)

' Draw picture in the new size
newPic.graphics.DrawPicture(p, 0, 0, w, h, 0, 0, p.width, p.height)

return newPic
End Function```
5. ### Sam R

23 May 2014 Pre-Release Testers, Xojo Pro Hengchun, Pingtung, Taiwan

Nice,
For many years I was using code very similar to what Garry posted, just no where near as elegant!

If I may, I can squeeze out a few more lines from your code.

```  Function ResizeToFit(Extends p as Picture, maxWidth as Integer, maxHeight as Integer) As Picture
' Calculate the scale ratio

dim ratio as Double = min( maxHeight/p.height, maxWidth/p.width)

' Create a new picture to return
dim newPic as new Picture( p.width * ratio, p.height * ratio )

' Draw picture in the new size
newPic.graphics.DrawPicture( p, 0, 0, newPic.width, newPic.height, 0, 0, p.width, p.height)

return newPic
End Function```
6. ### Christian S

24 May 2014 Pre-Release Testers, Xojo Pro, XDC Speakers Germany

it's normally a good idea to put calculation results into local variables. that way you can look at them in debugger.

e.g. if picture constructor raises exception, you may want to see what values you have for width and height.

PS: Your resize doesn't handle mask. But may work for alpha channel images.

7. 2 years ago

### Tim T

21 Apr 2017 Atlanta, GA

Hey for these routines maxWidth and maxHeight passed in are those in PIXELS???
Or inches? Or does it matter?

8. ### Sam R

21 Apr 2017 Pre-Release Testers, Xojo Pro Hengchun, Pingtung, Taiwan

@Tim T Hey for these routines maxWidth and maxHeight passed in are those in PIXELS???

pictures are pixel based.

22 Apr 2017
10. ### Dave K

22 Apr 2017
Edited 2 years ago

@Sam R Nice,
For many years I was using code very similar to what Garry posted, just no where near as elegant!

If I may, I can squeeze out a few more lines from your code.

``` <snip> dim ratio as Double = min( maxHeight/p.height, maxWidth/p.width) </snip>```

I think "min" here can be replaced with "max". Min will "fit to size" the entire image and max will "fill to size", giving a bit of cropping. I use pretty much the above code, adding a FillOrFit parameter, "0" to fit "1" to fill

```If FillOrFit = 0 Then
dim ratio as Double = min( maxHeight/p.height, maxWidth/p.width)
Else
dim ratio as Double = max( maxHeight/p.height, maxWidth/p.width)
End```
11. ### Sam R

22 Apr 2017 Pre-Release Testers, Xojo Pro Hengchun, Pingtung, Taiwan

If it helps... Here's what I currently use to resize images, it allows for fitting, filling (with cropping) and stretching. Also importantly you can prevent small images from resized up, which I needed for something.

```Public Function resizeToFit(extends p as picture, maxWidth as integer, maxHeight as integer, scaleMode as pictureScaleMode = pictureScaleMode.toFit, onlyShrink as boolean = false) as picture
Dim nSize as xojo.core.size

select case scaleMode
case picturescaleMode.toFit, picturescaleMode.toFill // -- Scale to fit & Scale to fill
dim scale as Double = if( scaleMode = picturescaleMode.toFit, _
min( maxHeight / p.height, maxWidth / p.width ), _
max( maxHeight / p.height, maxWidth / p.width ) )

if onlyShrink then scale = min( scale, 1.0 )

nSize = new xojo.core.size( floor( p.width * scale ), floor( p.height * scale ) )

case picturescaleMode.stretchToFill // --- Stretch to fill.
nSize = new xojo.Core.size( maxWidth, maxHeight )

end select

// --- Now create the target image and draw our image into the center.
Dim rvalue as new picture( min( nSize.width, maxWidth ), min( nSize.height, maxHeight ) )
rvalue.graphics.drawPicture( p, ( rvalue.width - nSize.width ) * 0.5, ( rvalue.height - nSize.height ) * 0.5, _
nSize.width, nSize.height, 0, 0, p.width, p.height )

return rvalue
End Function```

You also need the enum

```Public Enum pictureScaleMode
toFit
toFill
stretchToFill
End Enum```