Simple way to scale proportionately

sterlingy

Active Member
Licensed User
Longtime User
Folks,

I'm adding a gallery feature to my app.

When a user clicks on a thumbnail of a photo, it should then show the photo Fullscreen or as Fullscreen as possible,

Is there a simple method to keep an image's Height and Width proportionate, but use as much space on the phone's screen as possible, without doing a bunch of calculations?

Just using 100%x and 100%y, won't work, because the image may become distorted, especially if the photo was taken in Landscape mode and you view it in Portrait mode.

Cheers,

Sterling
 

Mudbrbque

New Member
Licensed User
Longtime User
Here is what I came up with:

B4X:
Sub btnImage_Click
Dim phn As Phone   
Dim fd As FileDialog
fd.FastScroll = True
fd.FilePath = File.DirRootExternal
fd.FileFilter = ".jpg,.png,.bmp,.gif"
ret = fd.Show("CHOOSE A BACKGROUND IMAGE", "Save", "Cancel", "", Null)   
phn.HideKeyboard(Activity)
If ret = -1 Then
   Dim bmp As Bitmap
   Dim tmpAspectRatio As Float
   Dim tmpLeft As Int :tmpLeft = 0
   Dim tmpTop As Int :tmpTop = 0
   Dim tmpWidth As Int :tmpWidth = Activity.Width
   Dim tmpHeight As Int :tmpHeight = Activity.Height
   StateManager.SetSetting("stgBackgroundPath", fd.FilePath)
   StateManager.SetSetting("stgBackgroundName", fd.ChosenName)
   bmp.Initialize(fd.FilePath,fd.ChosenName)
   If (Activity.Width / Activity.Height) <> (bmp.Width / bmp.Height) Then
      tmpAspectRatio = bmp.Width / bmp.Height
      tmpHeight = Floor(Activity.Width / tmpAspectRatio)
      If tmpHeight < Activity.Height Then
         tmpHeight = Activity.Height
         tmpWidth = Floor(Activity.Height * tmpAspectRatio)
      End If
      If tmpWidth > Activity.Width Then
         tmpLeft = Floor((Activity.Width - tmpWidth) / 2)
      End If
      If tmpHeight > Activity.Height Then
         tmpTop = Floor((Activity.Height - tmpHeight) / 2)
      End If
   End If
   StateManager.SetSetting("stgBackgroundTop", tmpTop)
   StateManager.SetSetting("stgBackgroundLeft", tmpLeft)
   StateManager.SetSetting("stgBackgroundWidth", tmpWidth)
   StateManager.SetSetting("stgBackgroundHeight", tmpHeight)
   ToastMessageShow("Background Image : " & fd.FilePath & "/" & fd.ChosenName, False)
End If
End Sub

Note: the StateManager.SaveSetting call occurs in the btnDone_Click sub.

My app allows the user to choose a background image. This sub is part of my menu|settings activity. It does not display the image, it calculates the Top, Left, Width and Height needed to display the image accurately and saves those values using StateManager. It also requires the Dialogs library to allow the user to choose the image.

My Main activity then displays the image in an imageview using:

B4X:
stgBackgroundPath = StateManager.GetSetting("stgBackgroundPath")
stgBackgroundName = StateManager.GetSetting("stgBackgroundName")
stgBackgroundLeft = StateManager.GetSetting("stgBackgroundLeft")
stgBackgroundTop = StateManager.GetSetting("stgBackgroundTop")
stgBackgroundWidth = StateManager.GetSetting("stgBackgroundWidth")
stgBackgroundHeight = StateManager.GetSetting("stgBackgroundHeight")
If stgBackgroundName <> "" Then
   If File.Exists(stgBackgroundPath,stgBackgroundName) Then
      ivwBackgroundImage.Bitmap = LoadBitmap(stgBackgroundPath,stgBackgroundName)
      ivwBackgroundImage.SetLayout (stgBackgroundLeft, stgBackgroundTop, stgBackgroundWidth, stgBackgroundHeight)
   Else
      ToastMessageShow("Your custom background was not found."&CRLF&"Background was returned to default image.", True)
   End If
End If

The sub works by fitting the bmp width to the activity width while maintaining the aspect ratio then checking if the bmp is greater than or equal to the activity height. If its not then it fits the bmp to the activity height while maintaining the aspect ratio. Finally it centers the bmp on the activity by using a negative Left or Top, whichever dimension of the bmp is larger than the the activity.

The sub is device and display size independent since it uses the actual device's activity dimensions for its calculations. It also doesn't matter if the bmp is portrait or landscape orientation.

Of course part of the image is not displayed because the sub assumes the most important portion is in the center of the image and either both sides or the top and bottom of the image are outside of the activity, thus not in view.

Hope this helps,
MudBRBque

Edit Add:

My app is locked in portrait mode. If your app allows orientation changes then you will want to call a sub from Activity_Resume that recalcs the bmp settings for the new orientation by modifying this portion of the sub:

B4X:
If (Activity.Width / Activity.Height) <> (bmp.Width / bmp.Height) Then
   tmpAspectRatio = bmp.Width / bmp.Height
   tmpHeight = Floor(Activity.Width / tmpAspectRatio)
   If tmpHeight < Activity.Height Then
      tmpHeight = Activity.Height
      tmpWidth = Floor(Activity.Height * tmpAspectRatio)
   End If
   If tmpWidth > Activity.Width Then
      tmpLeft = Floor((Activity.Width - tmpWidth) / 2)
   End If
   If tmpHeight > Activity.Height Then
      tmpTop = Floor((Activity.Height - tmpHeight) / 2)
   End If
End If
 
Last edited:
Upvote 0

sterlingy

Active Member
Licensed User
Longtime User
Thanks MudBRBque,

I'm going to try and finish my gallery code over the weekend, if not tomorrow. I will try to implement your code. It seems to make sense, so I'm sure it will work.

I'll let you know.

Cheers,

Sterling
 
Upvote 0

sterlingy

Active Member
Licensed User
Longtime User
NJDude,

I thought about just doing the math. It's not a big deal. I was just wondering if there was a Method somewhere that handled this exact problem.

-Sterling

P.S. I think I saw your name on that new game engine. Stick with it, or help out in any way you can.
 
Upvote 0
Top