How to get the size of a scaled UIImage in UIImageView?
Asked Answered
A

9

53

The image.size attribute of UIImageView gives the size of the original UIImage. I would like to find out the size of the autoscaled image when it is put in the UIImageView (typically smaller than the original).

For example, I have the image set to Aspect Fit. Now I want to know its new height and width on the screen so I can draw accurately on the new scaled image.

Is there any way to do this without figuring it out myself based on the UIImageView size & UIImage original size (basically reverse engineering its scaling)?

Armor answered 23/12, 2008 at 16:27 Comment(1)
got the same problem, perhaps I'll need to calculate the size by myself...Curt
B
89

Objective-C:

-(CGRect)frameForImage:(UIImage*)image inImageViewAspectFit:(UIImageView*)imageView
{
    float imageRatio = image.size.width / image.size.height;
    float viewRatio = imageView.frame.size.width / imageView.frame.size.height;
    if(imageRatio < viewRatio)
    {
        float scale = imageView.frame.size.height / image.size.height;
        float width = scale * image.size.width;
        float topLeftX = (imageView.frame.size.width - width) * 0.5;
        return CGRectMake(topLeftX, 0, width, imageView.frame.size.height);
    }
    else
    {
        float scale = imageView.frame.size.width / image.size.width;
        float height = scale * image.size.height;
        float topLeftY = (imageView.frame.size.height - height) * 0.5;

        return CGRectMake(0, topLeftY, imageView.frame.size.width, height);
    }
}

Swift 4:

func frame(for image: UIImage, inImageViewAspectFit imageView: UIImageView) -> CGRect {
  let imageRatio = (image.size.width / image.size.height)
  let viewRatio = imageView.frame.size.width / imageView.frame.size.height
  if imageRatio < viewRatio {
    let scale = imageView.frame.size.height / image.size.height
    let width = scale * image.size.width
    let topLeftX = (imageView.frame.size.width - width) * 0.5
    return CGRect(x: topLeftX, y: 0, width: width, height: imageView.frame.size.height)
  } else {
    let scale = imageView.frame.size.width / image.size.width
    let height = scale * image.size.height
    let topLeftY = (imageView.frame.size.height - height) * 0.5
    return CGRect(x: 0.0, y: topLeftY, width: imageView.frame.size.width, height: height)
  }
}
Bankable answered 13/2, 2011 at 23:10 Comment(5)
If the image passed in could coontain 0 heigh or 0 width, the generated CGRect could contain NaN. Be careful if this happens.Underline
This answer just made me happy. Thanks! :-DMm
This is the perfect solution... excellent thinking..!! all the best and thank you.Shear
you are savior of my day . Thanks ! :)Spearwort
Working exactly I expected. ThanksCummine
S
27

This simple function will calculate size of image:-

[imageView setFrame:AVMakeRectWithAspectRatioInsideRect(image.size, imageView.frame)];

For more details, You can refer AVMakeRectWithAspectRatioInsideRect - AVFoundation.

Sipper answered 27/1, 2016 at 8:16 Comment(1)
this is definitely the best answer ! I wasn't aware of this function, thanks a lot ;)Beefcake
B
10

This simple function will calculate size of image after aspect fit:

-(CGSize)imageSizeAfterAspectFit:(UIImageView*)imgview{


    float newwidth;
    float newheight;

    UIImage *image=imgview.image;

    if (image.size.height>=image.size.width){
        newheight=imgview.frame.size.height;
        newwidth=(image.size.width/image.size.height)*newheight;

        if(newwidth>imgview.frame.size.width){
            float diff=imgview.frame.size.width-newwidth;
            newheight=newheight+diff/newheight*newheight;
            newwidth=imgview.frame.size.width;
        }

    }
    else{
        newwidth=imgview.frame.size.width;
        newheight=(image.size.height/image.size.width)*newwidth;

        if(newheight>imgview.frame.size.height){
            float diff=imgview.frame.size.height-newheight;
            newwidth=newwidth+diff/newwidth*newwidth;
            newheight=imgview.frame.size.height;
        }
    }

    NSLog(@"image after aspect fit: width=%f height=%f",newwidth,newheight);


    //adapt UIImageView size to image size
    //imgview.frame=CGRectMake(imgview.frame.origin.x+(imgview.frame.size.width-newwidth)/2,imgview.frame.origin.y+(imgview.frame.size.height-newheight)/2,newwidth,newheight);

    return CGSizeMake(newwidth, newheight);

}
Barber answered 24/1, 2013 at 10:31 Comment(0)
Y
9

An adaptation of cncool answer, in swift as a UIImageView extension, perhaps it could be useful to someone:

extension UIImageView{
    func frameForImageInImageViewAspectFit() -> CGRect
    {
        if  let img = self.image {
            let imageRatio = img.size.width / img.size.height;

            let viewRatio = self.frame.size.width / self.frame.size.height;

            if(imageRatio < viewRatio)
            {
                let scale = self.frame.size.height / img.size.height;

                let width = scale * img.size.width;

                let topLeftX = (self.frame.size.width - width) * 0.5;

                return CGRectMake(topLeftX, 0, width, self.frame.size.height);
            }
            else
            {
                let scale = self.frame.size.width / img.size.width;

                let height = scale * img.size.height;

                let topLeftY = (self.frame.size.height - height) * 0.5;

                return CGRectMake(0, topLeftY, self.frame.size.width, height);
            }
        }

        return CGRectMake(0, 0, 0, 0)
    }
}
Yarak answered 5/4, 2016 at 14:7 Comment(0)
B
4

Since you've got the image view set to Aspect Fit, you can simply take the height and width of the image view along with the height and width of the original image and calculate the height and width of the scaled image.

That said, the better way of doing this is to have a custom view instead of a UIImageView. Then, draw the image yourself in the custom view. That way you can control every aspect of it.

Bejarano answered 30/12, 2008 at 2:42 Comment(1)
thanks for saying 'the better way'. I was trying to put up with doing it the storyboard way with aspect fit but it is just so painful trying to get everything right that way, doing it manually is way better in every way.Chon
D
1

Following up on @MeetDoshi, here is an extension that should accommodate this.

extension UIImageView {
    /// Retrieve the scaled size of the image within this ImageView.
    /// - Returns: A CGRect representing the size of the image after scaling or nil if no image is set.
    func getScaledImageSize() -> CGRect? {
        if let image = self.image {
            return AVMakeRect(aspectRatio: image.size, insideRect: self.frame);
        }

        return nil;
    }
}
Denney answered 26/10, 2018 at 14:44 Comment(0)
D
1

I wrote a useful extension that includes this in it's set of additions, might be worth checking out.

Included Functions

func getScaledImageSize() -> CGRect?
func getScaledImageSizeWithPadding() -> CGRect?
func getPaddingTop() -> CGFloat? {
func getPaddingBottom() -> CGFloat? {
func getPaddingLeft() -> CGFloat? {
func getPaddingRight() -> CGFloat?
func getScaledCoordinate(forX x: CGFloat, andY y: CGFloat, multiplier:CGFloat = 100.0) -> CGPoint?
func getScaledCoordinateWithPadding(forX x: CGFloat, andY y: CGFloat, multiplier:CGFloat = 100.0) -> CGPoint?

https://gist.github.com/nathan-fiscaletti/e1b85f68559f305db7342bfff9574563

Denney answered 12/11, 2018 at 17:21 Comment(0)
A
0

If the frame is filled maintaining the image aspect ratio, the imageview frame will not be the same as the image size.

Armor answered 23/12, 2008 at 17:23 Comment(0)
A
-1

How about just get the UIImageView size from its frame? i.e. imageView.frame?

Antoniaantonie answered 23/12, 2008 at 17:21 Comment(1)
image.frame.size is the current size of that view in it's superview's coordinate system, which is probably measured in pixels.Chretien

© 2022 - 2024 — McMap. All rights reserved.