19

I want to change my UIImageView height/width to match the image i choose from photo album and i found a snippet on here that does that.

-(CGRect)frameForImage:(UIImage *)imgs inImageViewAspectFit:(UIImageView *)imagev
{
  float imageRatio = imgs.size.width / imgs.size.height;
  float viewRatio = imagev.frame.size.width / imagev.frame.size.height;
  if(imageRatio < viewRatio)
  {
    float scale = imagev.frame.size.height / imgs.size.height;
    float width = scale * imgs.size.width;
    float topLeftX = (imagev.frame.size.width - width) * 0.5;
    NSLog(@"image after aspect fit: width=%f",width);
    imagev.frame = CGRectMake(topLeftX, 0, width, imagev.frame.size.height);
    return CGRectMake(topLeftX, 0, width, imagev.frame.size.height);
  }
  else
  {
    float scale = imagev.frame.size.width / imgs.size.width;
    float height = scale * imgs.size.height;
    float topLeftY = (imagev.frame.size.height - height) * 0.5;
    NSLog(@"image after aspect fit: height=%f", height);
    imagev.frame = CGRectMake(0, topLeftY, imagev.frame.size.width, height);
    return CGRectMake(0, topLeftY, imagev.frame.size.width, height);
  }
}

The problem is that it changes the UIImageView height/width when i call it from a button

- (IBAction)changeSize:(id)sender
{
  [self frameForImage:image inImageViewAspectFit:self.imageView];    
}

But i want it to do that as soon as i choose a image from photo album and this is how i have it set up.

-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
  image = [info objectForKey:UIImagePickerControllerOriginalImage];
  [self.imageView setImage:image];
  [self frameForImage:image inImageViewAspectFit:self.imageView];
  [self dismissViewControllerAnimated:YES completion:NULL];
}
JOM
  • 8,139
  • 6
  • 78
  • 111
Mike Tyson
  • 193
  • 1
  • 1
  • 4
  • Only use the [tag:xcode] tag for questions about the IDE itself. Thanks! – Undo Jun 02 '13 at 00:48
  • simply choose **ASPECT FIT** for the UIImageView (in Inspector) - and you're done. That's all there is to it. it is completely automatic. – Fattie Jun 29 '16 at 21:56

2 Answers2

32

Auto Layout solution

Since establishing that you're using Auto Layout in your project, I have made a demo app to show you how you could change the image of the image view and adjust the height. Auto Layout will do this for you automatically, but the catch is that the photo you'll be using is coming from the users gallery and so they're likely to be very big and this.

So check out the app: https://bitbucket.org/danielphillips/auto-layout-imageview

The trick is to create a reference of the NSLayoutConstraint of the height of the image view. When you change your image, you need to adjust it's constant to the correct height given the fixed width.

Your other solution could be to set a contentMode on your image view, by using UIViewContentModeScaleAspectFit your image will always appear in full but will be locked to the bounds of the image view, which can change based on the Auto Layout constraints you have.

Initial reply

It looks like you've really over complicated this, unless I've missed something.

When you get a new image from the image picker, all you need to do is change the frame of the image view according to the UIImage size.

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
  image = [info objectForKey:UIImagePickerControllerOriginalImage];
  [self.imageView setImage:image];
  self.imageView.frame = CGRectMake(self.imageView.frame.origin.x
                                    self.imageView.frame.origin.y
                                    image.size.width
                                    image.size.height);
  [self dismissViewControllerAnimated:YES completion:NULL];
}

Of course this is going to be potentially very large (it's using the original image which may be very large).

So let's lock the width to 280 points... this way we can always have the full image on screen in portrait mode.

So assuming your image size is 1000x800, and our image view perhaps is 280x100. We can calculate the correct height for the image view retaining the image view's width like this:

CGSize imageSize        = CGSizeMake(1000.0, 800.0);
CGSize imageViewSize    = CGSizeMake(280.0, 100.0);

CGFloat correctImageViewHeight = (imageViewSize.width / imageSize.width) * imageSize.height;

self.imageView.frame = CGRectMake(  self.imageView.frame.origin.x,
                                    self.imageView.frame.origin.x,
                                    CGRectGetWidth(self.imageView.bounds),
                                    correctImageViewHeight);
Daniel
  • 23,129
  • 12
  • 109
  • 154
  • 3
    i tried your first snippet and it wont change the width/height unless i add `[self.imageView setTranslatesAutoresizingMaskIntoConstraints:YES]; – Mike Tyson Jun 02 '13 at 01:07
  • 1
    and the console output shows `Will attempt to recover by breaking constraint Break on objc_exception_throw to catch this in the debugger. The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in may also be helpful.` but it still works – Mike Tyson Jun 02 '13 at 01:14
  • 2
    Right you're using AutoLayout. That is a very important detail. – Daniel Jun 02 '13 at 02:44
5

Here is a Swift class that will help return the correct sizing for an image based on a width or height limit that you choose:

class func returnImageSizeForHeightLimit(heightLimit:CGFloat?, orWidthLimit widthLimit:CGFloat?, forImage theImage:UIImage)->CGSize?{

    if let myHeightLimit = heightLimit {

        let theWidth = (myHeightLimit/theImage.size.height) * theImage.size.width

        return CGSizeMake(theWidth, myHeightLimit)
    }

    if let myWidthLimit = widthLimit {

        let theHeight = (myWidthLimit/theImage.size.width) * theImage.size.height

        return CGSizeMake(myWidthLimit, theHeight)
    }

    return nil
}
PJeremyMalouf
  • 613
  • 6
  • 15