I have a UIScrollView
and inside it i have a UIImage
which i get from my server. Each image will either have its width
greater than the height
or the height
greater than its width
.
I would like to scale the image in such a way that it fits my device screen perfect based on the height
or width
For example:
I get the image from server and check which is greater, the width
or the height
.
if let width = image?.size.width, let height = image?.size.height {
if width > height {
print("Width is greater than height")
}else
print("Height is greater than width")
}
}
Once i do this i would like to scale the image in one of these 2 ways.
Option 1:
If the width
is greater than the height
then i would like the image to be scaled with respect to its height
being fixed to device height and width should be scrollable
in the view.
Option 2:
If the height
is greater than the width
then i would like the image to be scaled with respect to its width
being fixed to device width and height should be scrollable
in the view.
I have managed to get Option 2
to work with this function.
func scaleImageWidth(sourceImage:UIImage, scaledToWidth: CGFloat) -> UIImage {
let oldWidth = sourceImage.size.width
let scaleFactor = scaledToWidth / oldWidth
let newHeight = sourceImage.size.height * scaleFactor
let newWidth = oldWidth * scaleFactor
UIGraphicsBeginImageContext(CGSize(width:newWidth, height:newHeight))
sourceImage.draw(in: CGRect(x:0, y:0, width:newWidth, height:newHeight))
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage!
}
I have modified the function to work for Option 1
like so:
func scaleImageHeight(sourceImage: UIImage, scaledToHeight: CGFloat) -> UIImage {
let oldheight: CGFloat = sourceImage.size.height
let scaleFactor: CGFloat = scaledToHeight / oldheight
let newWidth: CGFloat = sourceImage.size.width * scaleFactor
let newHeight: CGFloat = oldheight * scaleFactor
UIGraphicsBeginImageContext(CGSize(width: newWidth, height: newHeight))
sourceImage.draw(in: CGRect(x: 0, y: 0, width: newWidth, height: newHeight))
let newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
return newImage
}
Now both these functions work fine, but in both cases there are some situations where the scaling causes the image to scale smaller than the width
or height
of the device.
Here are some images of how it looks when the scaling goes wrong.
Actual Result:
Expected Result:
EDITED:
Here are a few images for whose height
and width
these functions work properly.
Case 1: When Height is greater than width
Case 2: When Width is greater than height
Here are a few images for whose height
and width
these function produces the above mentioned problem.
Case 1: When Height is greater than width
Case 2: When Width is greater than height
I have not noticed any issues for when width is greater than height. It always produces the right results in this case.
So after a lot of trying. I solved this problem after i read @DonMag
answer. Where its mentioned that the issue could be due to not considering the aspect ratio
of the image.
In my scenario I had to have a UIScrollView
and have the image fill the scrollView according its width
& height
. And it had to scroll only in one direction either Vertically
or Horizontally
based on the aspect ratio of the image.
To achieve this i used only 1 function from the question above which is OPTION 1
and i modified it as below.
func scaleImageHeight(sourceImage: UIImage, scaledToHeight: CGFloat) -> UIImage {
let oldheight: CGFloat = sourceImage.size.height
let scaleFactor: CGFloat = scaledToHeight / oldheight
let newWidth: CGFloat = sourceImage.size.width * scaleFactor
let newHeight: CGFloat = oldheight * scaleFactor
UIGraphicsBeginImageContext(CGSize(width: newWidth, height: newHeight))
sourceImage.draw(in: CGRect(x: 0, y: 0, width: newWidth, height: newHeight))
//This check is added as the scaling function would scale down an image to a size which was less than the width of the screen.
if newWidth < self.view.frame.width{
let differenceWidth = self.view.frame.width - newWidth
newWidth = self.view.frame.width
newHeight = newHeight+differenceWidth
}
let newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
return newImage
}
So the solution that worked for me, to match the clients requirement was to scale the image always by the height
of the image regardless of whether the height
or width
is greater than the other.
And after scaling if the width of scaled image was less than screen width then I scale the image back up to the width
so that it fits on the screen without any blank spaces. This scaling would result in the height
to be scrollable.
Note:
ImageView
should have a contentMode
of aspectFill
.