25

Real odd one to get stuck on but weirdly I am.

You you have a imageView containing a image. You size that imageView down and then tell it to use UIViewContentModeScaleAspectFit. so your imageView might be 300 by 200 but your scaled image within could be 300 by 118 or 228 by 200 because its aspectfit.

How on earth do you get the size of the actual image?
imageView.image.size is the size of the original image.
imageview.frame is the frame of the imageview not the contained image.
imageview.contentstretch does not work either

rptwsthi
  • 10,094
  • 10
  • 68
  • 109
Burf2000
  • 5,001
  • 14
  • 58
  • 117

4 Answers4

36

I have written a quick category on UIImageView to achieve that:

(.h)

@interface UIImageView (additions)
- (CGSize)imageScale;
@end

(.m)

@implementation UIImageView (additions)
- (CGSize)imageScale {
    CGFloat sx = self.frame.size.width / self.image.size.width;
    CGFloat sy = self.frame.size.height / self.image.size.height;
    CGFloat s = 1.0;
    switch (self.contentMode) {
        case UIViewContentModeScaleAspectFit:
            s = fminf(sx, sy);
            return CGSizeMake(s, s);
            break;

        case UIViewContentModeScaleAspectFill:
            s = fmaxf(sx, sy);
            return CGSizeMake(s, s);
            break;

        case UIViewContentModeScaleToFill:
            return CGSizeMake(sx, sy);

        default:
            return CGSizeMake(s, s);
    }
}
@end

Multiply the original image size by the given scale, and you'll get your actual displayed image size.

Cyrille
  • 25,014
  • 12
  • 67
  • 90
  • 1
    If you're interested, I also have a piece of code on top of that one that'll give you the actual CGRect of the image inside your UIImageView, whatever the contentMode or scale. – Cyrille Jul 28 '11 at 10:00
  • 2
    Warning, this code will break if the image is not set. Add the line `if (self.image == nil) return CGSizeMake(1, 1);` as the first line of the implementation of `imageScale`. – Cyrille Jul 28 '11 at 12:43
  • 9
    I'd be interested in your method for getting the actual CGRect of an image in UIImageView. – Ryan Poolos Jan 30 '13 at 16:16
  • The accepted answer is not actually the answer to the question. The path to the actual answer, I believe, would be in the first comment by @Cyrille. I'm actually seeking the answer to this myself (and, conversely, for aspect fill). – GtotheB Sep 13 '16 at 01:09
11

well .. you have to do some math. you have the size of the original image and you have the size of the image view.. so you can calculate whether it will be resized by the height or the width.

if you image view is 300x200 and the image is 1024x768 you can calculate which is the limiting factor

300/1024 = 0.29296875
200/768 = 0.260416667

so the height is the limiting factor ... the image will be:

267x200

Bastian
  • 10,403
  • 1
  • 31
  • 40
6

The Swift version of the accepted answer:

extension UIImageView {
var imageScale: CGSize {
    let sx = Double(self.frame.size.width / self.image!.size.width)
    let sy = Double(self.frame.size.height / self.image!.size.height)
    var s = 1.0
    switch (self.contentMode) {
    case .scaleAspectFit:
        s = fmin(sx, sy)
        return CGSize (width: s, height: s)

    case .scaleAspectFill:
        s = fmax(sx, sy)
        return CGSize(width:s, height:s)

    case .scaleToFill:
        return CGSize(width:sx, height:sy)

    default:
        return CGSize(width:s, height:s)
    }
  }
}
Masih
  • 1,633
  • 4
  • 19
  • 38
Individual11
  • 374
  • 4
  • 16
4

Just adding a little security on Individual11 code. Calling imageScale on an imageView without an actual image would crash.

extension UIImageView {
    var imageScale: CGSize {

        if let image = self.image {
            let sx = Double(self.frame.size.width / image.size.width)
            let sy = Double(self.frame.size.height / image.size.height)
            var s = 1.0
            switch (self.contentMode) {
            case .scaleAspectFit:
                s = fmin(sx, sy)
                return CGSize (width: s, height: s)

            case .scaleAspectFill:
                s = fmax(sx, sy)
                return CGSize(width:s, height:s)

            case .scaleToFill:
                return CGSize(width:sx, height:sy)

            default:
                return CGSize(width:s, height:s)
            }
        }

        return CGSize.zero
    }
}