Resize UIImage with aspect ratio?

33,881

After you set your screen rect, do something like the following to decide what rect to draw the image in:

float hfactor = value.bounds.size.width / screenRect.size.width;
float vfactor = value.bounds.size.height / screenRect.size.height;

float factor = fmax(hfactor, vfactor);

// Divide the size by the greater of the vertical or horizontal shrinkage factor
float newWidth = value.bounds.size.width / factor;
float newHeight = value.bounds.size.height / factor;

// Then figure out if you need to offset it to center vertically or horizontally
float leftOffset = (screenRect.size.width - newWidth) / 2;
float topOffset = (screenRect.size.height - newHeight) / 2;

CGRect newRect = CGRectMake(leftOffset, topOffset, newWidth, newHeight);

If you don't want to enlarge images smaller than the screenRect, make sure factor is greater than or equal to one (e.g. factor = fmax(factor, 1)).

To get the black background, you would probably just want to set the context color to black and call fillRect before drawing the image.

Share:
33,881
Cory Imdieke
Author by

Cory Imdieke

Updated on September 12, 2020

Comments

  • Cory Imdieke
    Cory Imdieke over 3 years

    I'm using this code to resize an image on the iPhone:

    CGRect screenRect = CGRectMake(0, 0, 320.0, 480.0);
    UIGraphicsBeginImageContext(screenRect.size);
    [value drawInRect:screenRect blendMode:kCGBlendModePlusDarker alpha:1];
    UIImage *tmpValue = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    

    Which is working great, as long as the aspect ratio of the image matches that of the new resized image. I'd like to modify this so that it keeps the correct aspect ratio and just puts a black background anywhere the image doesn't show up. So I would still end up with a 320x480 image but with black on the top and bottom or sides, depending on the original image size.

    Is there an easy way to do this similar to what I'm doing? Thanks!

  • Frank Schmitt
    Frank Schmitt about 13 years
    value is the variable Cory is using to store the source image.
  • Zhen
    Zhen almost 13 years
    @Frank Schmitt, can I check how I can set the context to black for this case?
  • cleverbit
    cleverbit over 12 years
    I was getting "Implicit declaration of function 'max'" thrown by the compiler, even though I remembered to include math.h (I'm using XCode 4.0) Changing: float factor = max( … to float factor = MAX( … all caps) resolved the issue. FWIW the reason I needed to rescale a UIImage (as opposed to UIImageView) was because I was setting the image in a default styled UITableCell. This helped me avoid needing to implement a custom UITableCell. Thanks to Frank for a GREAT solution!
  • Frank Schmitt
    Frank Schmitt over 12 years
    Just made an edit to use fmax, which is already in whatever precompiled headers Apple includes. The difference with MAX() is that it treats everything as an integer, whereas Core Graphics uses CGFloats (doubles) natively for all coordinate values. So on Retina screens your method might be off by half a point :)
  • Ashish P
    Ashish P almost 10 years
    Can you explain the logic as in why we need the factor variable here to get the newWidth and height here
  • Frank Schmitt
    Frank Schmitt almost 10 years
    @AshishPisey In order to preserve the image proportions, you need to divide the width and the height by the same amount. This code picks that amount (factor) based on whether it needs to be shrunk more in the horizontal (hFactor) or vertical (vFactor) direction to fit in the screen rectangle.
  • Frank Schmitt
    Frank Schmitt about 9 years
    @iOS_Ramesh value is the UIImage that you're resizing.