People, i need your help.
Need optimizing scaling images on flow. I try two methods for scale image with save proportions, please inspect this code and say, how i can it optimize if you want/can:
// Draw image in rect (PNG 1000ms, JPG 834ms for 8 pictures)
+ (UIImage *)imageWithImage:(UIImage *)sourceImage
scaledToSizeWithSameAspectRatio:(CGSize)targetSize
withInterpolationQuality:(CGInterpolationQuality)quality
{
CGSize imageSize = sourceImage.size;
CGFloat width = imageSize.width;
CGFloat height = imageSize.height;
CGFloat targetWidth = targetSize.width;
CGFloat targetHeight = targetSize.height;
CGFloat scaledWidth = targetWidth;
CGFloat scaledHeight = targetHeight;
CGPoint thumbnailPoint = (CGPoint){0.0, 0.0};
if (CGSizeEqualToSize(imageSize, targetSize) == NO) {
CGFloat widthFactor = targetWidth / width;
CGFloat heightFactor = targetHeight / height;
if (widthFactor > heightFactor) {
scaledWidth = width * widthFactor;
scaledHeight = height * widthFactor;
thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5;
}
else {
scaledWidth = width * heightFactor;
scaledHeight = height * heightFactor;
thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5;
}
}
UIGraphicsBeginImageContextWithOptions(targetSize, YES, 1.0);
dispatch_sync(dispatch_queue_create("pro.idev.itux.projectNameHere", DISPATCH_QUEUE_SERIAL), ^{
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSetInterpolationQuality(ctx, quality);
[sourceImage drawInRect:(CGRect){thumbnailPoint, {scaledWidth, scaledHeight}}];
});
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
// Draw CGImage in rect (PNG 1326ms, JPG 1026ms for 8 pictures)
+ (UIImage *)imageWithCGImage:(CGImageRef)sourceImage
scaledToSizeWithSameAspectRatio:(CGSize)targetSize
withInterpolationQuality:(CGInterpolationQuality)quality
{
CGFloat width = CGImageGetWidth(sourceImage);
CGFloat height = CGImageGetHeight(sourceImage);
CGFloat targetWidth = targetSize.width;
CGFloat targetHeight = targetSize.height;
CGFloat scaledWidth = targetWidth;
CGFloat scaledHeight = targetHeight;
CGPoint thumbnailPoint = (CGPoint){0.0, 0.0};
if (CGSizeEqualToSize((CGSize){width, height}, targetSize) == NO) {
CGFloat widthFactor = targetWidth / width;
CGFloat heightFactor = targetHeight / height;
if (widthFactor > heightFactor) {
scaledWidth = width * widthFactor;
scaledHeight = height * widthFactor;
thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5;
}
else {
scaledWidth = width * heightFactor;
scaledHeight = height * heightFactor;
thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5;
}
}
UIGraphicsBeginImageContextWithOptions(targetSize, YES, 1.0);
dispatch_sync(dispatch_queue_create("pro.idev.itux.projectNameHere", DISPATCH_QUEUE_SERIAL), ^{
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(ctx, 0, targetHeight);
CGContextScaleCTM(ctx, 1.0, -1.0);
CGContextSetInterpolationQuality(ctx, quality);
CGContextDrawImage(ctx, (CGRect){thumbnailPoint, {scaledWidth, scaledHeight}}, sourceImage);
});
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
Related
I am using this code to change size to an image and then create a new file with new dimensions. All is working fine but it changes the image dpi resolution and I don't want that... the initial image dpi res is 328 and after the resizing it becomes 72... how to keep the original dpi resolution?
Here is my code:
- (void)scaleIcons:(NSString *)outputPath :(NSURL *)nomeImmagine
{
NSImage *image = [[NSImage alloc] initWithContentsOfFile:[nomeImmagine path]];
if (!image)
image = [[NSWorkspace sharedWorkspace] iconForFile:[nomeImmagine path]];
NSSize outputSize = NSMakeSize(512.0f,512.0f);
NSImage *anImage = [self scaleImage:image toSize:outputSize];
NSString *finalPath = [outputPath stringByAppendingString:#"/icon_512x512.png"];
NSData *imageData = [anImage TIFFRepresentation];
NSBitmapImageRep *rep = [NSBitmapImageRep imageRepWithData:imageData];
NSData *dataToWrite = [rep representationUsingType:NSPNGFileType properties:nil];
[dataToWrite writeToFile:finalPath atomically:NO];
}
- (NSImage *)scaleImage:(NSImage *)image toSize:(NSSize)targetSize
{
if ([image isValid])
{
NSSize imageSize = [image size];
float width = imageSize.width;
float height = imageSize.height;
float targetWidth = targetSize.width;
float targetHeight = targetSize.height;
float scaleFactor = 0.0;
float scaledWidth = targetWidth;
float scaledHeight = targetHeight;
NSPoint thumbnailPoint = NSZeroPoint;
if (!NSEqualSizes(imageSize, targetSize))
{
float widthFactor = targetWidth / width;
float heightFactor = targetHeight / height;
if (widthFactor < heightFactor)
{
scaleFactor = widthFactor;
}
else
{
scaleFactor = heightFactor;
}
scaledWidth = width * scaleFactor;
scaledHeight = height * scaleFactor;
if (widthFactor < heightFactor)
{
thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5;
}
else if (widthFactor > heightFactor)
{
thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5;
}
newImage = [[NSImage alloc] initWithSize:targetSize];
[newImage lockFocus];
NSRect thumbnailRect;
thumbnailRect.origin = thumbnailPoint;
thumbnailRect.size.width = scaledWidth;
thumbnailRect.size.height = scaledHeight;
[image drawInRect:thumbnailRect
fromRect:NSZeroRect
operation:NSCompositeSourceOver
fraction:1.0];
[newImage unlockFocus];
}
}
return newImage;
}
Any help will be very much appreciated! Thanks... Massy
Finally I've been able to change the res... using the code taken by the post pointed by trojanfoe... I added this to my code before to write the file:
NSSize pointsSize = rep.size;
NSSize pixelSize = NSMakeSize(rep.pixelsWide, rep.pixelsHigh);
CGFloat currentDPI = ceilf((72.0f * pixelSize.width)/pointsSize.width);
NSLog(#"current DPI %f", currentDPI);
NSSize updatedPointsSize = pointsSize;
updatedPointsSize.width = ceilf((72.0f * pixelSize.width)/328);
updatedPointsSize.height = ceilf((72.0f * pixelSize.height)/328);
[rep setSize:updatedPointsSize];
only problem now is that the final resolution is 321,894 and not 328... but it's already something!
Is there any way how to resize UIImage in as few lines as possible? I don't mind of ratio, I just want to set image resolution to 80x60. That's all
This may be overkill but, you can simply take your image, and create a graphics context at that resolution you want, then you can set the tempImage as the UIImageView, overwriting it.
UIImage *image = YourImageView.image;
UIImage *tempImage = nil;
CGSize targetSize = CGSizeMake(80,60);
UIGraphicsBeginImageContext(targetSize);
CGRect thumbnailRect = CGRectMake(0, 0, 0, 0);
thumbnailRect.origin = CGPointMake(0.0,0.0);
thumbnailRect.size.width = targetSize.width;
thumbnailRect.size.height = targetSize.height;
[image drawInRect:thumbnailRect];
tempImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
YourImageView.image = tempImage;
- (void)resizeImage:(UIImage *)image
{
CGSize origImageSize = [image size];
CGRect imageRect = CGRectMake(0, 0, 80, 60);
float ratio = MAX(newRect.size.width / origImageSize.width,
newRect.size.height / origImageSize.height);
UIGraphicsBeginImageContextWithOptions(newRect.size, NO, 0.0);
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:newRect
cornerRadius:5.0];
[path addClip];
CGRect imageRect;
imageRect.size.width = ratio * origImageSize.width;
imageRect.size.height = ratio * origImageSize.height;
imageRect.origin.x = (newRect.size.width - imageRect.size.width) / 2.0;
imageRect.origin.y = (newRect.size.height - imageRect.size.height) / 2.0;
[image drawInRect:imageRect];
UIImage *smallImage = UIGraphicsGetImageFromCurrentImageContext();
NSData *data = UIImagePNGRepresentation(smallImage);
UIGraphicsEndImageContext();
}
Do not forget to add CoreGraphics frameawork.
Use this class (add code to .h file accordingly)
#import "UIImage+Resize.h"
#implementation UIImage (Resize)
- (UIImage *)resizedImage:(CGSize)bounds {
return [self resizedImage:bounds upScale:YES];
}
- (UIImage*)resizedImage:(CGSize)bounds upScale:(BOOL)upScale {
CGSize originalSize = self.size;
float xScale = bounds.width / originalSize.width;
float yScale = bounds.height / originalSize.height;
float scale = MIN(xScale, yScale);
if (!upScale) {
scale = MIN(scale, 1);
}
CGSize newSize = CGSizeMake(originalSize.width * scale, originalSize.height * scale);
UIGraphicsBeginImageContextWithOptions(newSize, NO, [UIScreen mainScreen].scale);
[self drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
UIImage *resultImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return resultImage;
}
I've found the following code on this page:
- (UIImage*)imageWithImage: (UIImage*) sourceImage scaledToWidth: (float) i_width{
if (sourceImage.size.width>sourceImage.size.height) {
sourceImage = [[UIImage alloc] initWithCGImage: sourceImage.CGImage
scale: 1.0
orientation: UIImageOrientationRight];
}
float oldWidth = sourceImage.size.width;
float scaleFactor = i_width / oldWidth;
float newHeight = sourceImage.size.height * scaleFactor;
float newWidth = oldWidth * scaleFactor;
UIGraphicsBeginImageContext(CGSizeMake(newWidth, newHeight)); [sourceImage drawInRect:CGRectMake(0, 0, newWidth, newHeight)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext();
return newImage;
}
All you have to do is provide it with the i_width, and it will scale it accordingly.
I've added a little twist to it, so that if the picture is in landscape mode, it will be rotated to portrait, and then resized. If you want it to be the opposite (portrait to landscape), change this:
if (sourceImage.size.width>sourceImage.size.height) {
sourceImage = [[UIImage alloc] initWithCGImage: sourceImage.CGImage
scale: 1.0
orientation: UIImageOrientationRight];
}
to this:
if (sourceImage.size.height>sourceImage.size.width) {
sourceImage = [[UIImage alloc] initWithCGImage: sourceImage.CGImage
scale: 1.0
orientation: UIImageOrientationRight];
}
CAVEAT: my rotating method doesn't take into consideration if the picture is pointing left or right. In other words, If an image is landscape by upside down, my code can't recognise that. I hope someone else can shed some light on this though :)
I am making a military strategy game. When an army in my game takes over a territory, I want to be able to change the color of the territory on the map so that it shows the new controller of that territory. Here is the code I have that changes a territory's image:
I would write this line for example:
UIImage *newImg = [self imageOfTerritoryWithNewArmy:#"japan" AndOldTerritoryImage:[UIImage imageNamed:#"ireland.gif"]];
Here is the rest of the code:
-(UIImage *)createImageWithRGB:(NSArray *)colorData width:(NSInteger)width height:(NSInteger)height{
unsigned char *rawData = malloc(width*height*4);
for (int i=0; i<width*height; ++i)
{
CGFloat red;
CGFloat green;
CGFloat blue;
CGFloat alpha;
UIColor *color = colorData[i];
if ([color respondsToSelector:#selector(getRed:green:blue:alpha:)]) {
[color getRed:&red green:&green blue:&blue alpha:&alpha];
} else {
const CGFloat *components = CGColorGetComponents(color.CGColor);
red = components[0];
green = components[1];
blue = components[2];
alpha = components[3];
}
if(alpha > 0){
rawData[4*i] = red * 255;
rawData[4*i+1] = green * 255;
rawData[4*i+2] = blue * 255;
rawData[4*i+3] = alpha * 255;
}
else{
rawData[4*i] = 255;
rawData[4*i+1] = 255;
rawData[4*i+2] = 255;
rawData[4*i+3] = 0;
}
}
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL,
rawData,
width*height*4,
NULL);
CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault;
CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
CGImageRef imageRef = CGImageCreate(width,
height,
8,
32,
4*width,colorSpaceRef,
bitmapInfo,
provider,NULL,NO,renderingIntent);
UIImage *newImage = [UIImage imageWithCGImage:imageRef];
return newImage;
}
- (NSArray *)getRGBAsFromImage:(UIImage*)image atX:(int)xx andY:(int)yy count:(int)count{
NSMutableArray *result = [NSMutableArray arrayWithCapacity:count];
// First get the image into your data buffer
CGImageRef imageRef = [image CGImage];
NSUInteger width = CGImageGetWidth(imageRef);
NSUInteger height = CGImageGetHeight(imageRef);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
unsigned char *rawData = (unsigned char*) calloc(height * width * 4, sizeof(unsigned char));
NSUInteger bytesPerPixel = 4;
NSUInteger bytesPerRow = bytesPerPixel * width;
NSUInteger bitsPerComponent = 8;
CGContextRef context = CGBitmapContextCreate(rawData, width, height,
bitsPerComponent, bytesPerRow, colorSpace,
kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
CGColorSpaceRelease(colorSpace);
CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);
CGContextRelease(context);
// Now your rawData contains the image data in the RGBA8888 pixel format.
int byteIndex = (bytesPerRow * yy) + xx * bytesPerPixel;
for (int ii = 0 ; ii < count ; ++ii)
{
CGFloat red = (rawData[byteIndex] * 1.0) / 255.0;
CGFloat green = (rawData[byteIndex + 1] * 1.0) / 255.0;
CGFloat blue = (rawData[byteIndex + 2] * 1.0) / 255.0;
CGFloat alpha = (rawData[byteIndex + 3] * 1.0) / 255.0;
byteIndex += 4;
UIColor *acolor = [UIColor colorWithRed:red green:green blue:blue alpha:alpha];
[result addObject:acolor];
}
free(rawData);
return result;
}
-(UIColor *)colorOfArmy:(NSString *)army{
UIColor *color;
army = [army stringByReplacingOccurrencesOfString:#"\a" withString:#""];
if([army isEqual:#"france"]){
color = [[UIColor alloc] initWithRed:0.3137254 green:0.3686274 blue:0.9058823 alpha:1];
}
if([army isEqual:#"germany"]){
color = [[UIColor alloc] initWithRed:0.6352941 green:0.4313725 blue:0.3372549 alpha:1];
}
if([army isEqual:#"uk"]){
color = [[UIColor alloc] initWithRed:0.8941176 green:0.4235294 blue:0.4941176 alpha:1];
}
if([army isEqual:#"italy"]){
color = [[UIColor alloc] initWithRed:0.5137254 green:0.1215686 blue:0.4745098 alpha:1];
}
if([army isEqual:#"ussr"]){
color = [[UIColor alloc] initWithRed:0.3607843 green:0.0823529 blue:0.1215686 alpha:1];
}
if([army isEqual:#"japan"]){
color = [[UIColor alloc] initWithRed:0.9215686 green:0.6156862 blue:0.3137254 alpha:1];
}
if([army isEqual:#""]){
color = [[UIColor alloc] initWithRed:0.1215686 green:0.2823529 blue:0.1607843 alpha:1];
}
if(color == nil){
NSLog(#"the problem was %#", army);
}
return color;
}
-(UIImage *)imageOfTerritoryWithNewArmy:(NSString *)army AndOldTerritoryImage:(UIImage *)oldImg{
CGImageRef image = oldImg.CGImage;
NSInteger width = CGImageGetWidth(image);
NSInteger height = CGImageGetHeight(image);
NSArray *rgba = [self getRGBAsFromImage:oldImg atX:0 andY:0 count:width * height];
NSMutableArray *fixedRGBA = [[NSMutableArray alloc] init];
UIColor *armyColor = [self colorOfArmy:army];
for(UIColor *pixel in rgba){
CGFloat red;
CGFloat green;
CGFloat blue;
CGFloat alpha;
if ([pixel respondsToSelector:#selector(getRed:green:blue:alpha:)]) {
[pixel getRed:&red green:&green blue:&blue alpha:&alpha];
} else {
const CGFloat *components = CGColorGetComponents(pixel.CGColor);
red = components[0];
green = components[1];
blue = components[2];
alpha = components[3];
}
red = red * 255;
green = green * 255;
blue = blue * 255;
if(alpha > 0){
if(red < 50 && green < 50 && blue < 50){
[fixedRGBA addObject:pixel];
}
else{
[fixedRGBA addObject:armyColor];
}
}
else{
[fixedRGBA addObject:pixel];
}
}
return [self createImageWithRGB:fixedRGBA width:width height:height];
}
The problem that I am having is that when the image is drawn again, all of the pixels that used to be blank because they have an alpha value of 0 are displayed as white. How can I get these pixels to still be displayed as clear pixels?
When creating the image, you should specify that it contains an alpha channel. That is, instead of:
CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault;
use:
CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault | kCGImageAlphaLast;
See the CGImage interface specification for more info.
I believe your else clause here is where you want to set the color to clear
if(alpha > 0){
rawData[4*i] = red * 255;
rawData[4*i+1] = green * 255;
rawData[4*i+2] = blue * 255;
rawData[4*i+3] = alpha * 255;
}
else{
rawData[4*i] = 255;
rawData[4*i+1] = 255;
rawData[4*i+2] = 255;
rawData[4*i+3] = 255;
}
You have to change the last assignment to 0
if(alpha > 0){
rawData[4*i] = red * 255;
rawData[4*i+1] = green * 255;
rawData[4*i+2] = blue * 255;
rawData[4*i+3] = alpha * 255;
}
else{
rawData[4*i] = 255;
rawData[4*i+1] = 255;
rawData[4*i+2] = 255;
rawData[4*i+3] = 0;
}
I've made this below fitImage function which takes an UIImage and a CGSize. In case the input image is larger then the input box, the image would be scaled down to fill into the box. If the box and image does not have the same ratio the image does not fill the box entirely, and there would be some visible background. In this case this background is always white. How can I change this to e.g. a black background?
+ (UIImage*) fitImage:(UIImage*)image inBox:(CGSize)size {
if (image.size.width==size.width && image.size.height==size.height)
return image;
if (image.size.width<size.width && image.size.height<size.height)
return [Util scaleImage:image toSize:size];
float widthFactor = size.width / image.size.width;
float heightFactor = size.height / image.size.height;
CGSize scaledSize = size;
if (widthFactor<heightFactor) {
scaledSize.width = size.width;
scaledSize.height = image.size.height * widthFactor;
} else {
scaledSize.width = image.size.width * heightFactor;
scaledSize.height = size.height;
}
UIGraphicsBeginImageContextWithOptions( size, NO, 0.0 );
float marginX = (size.width-scaledSize.width)/2;
float marginY = (size.height-scaledSize.height)/2;
CGRect scaledImageRect = CGRectMake(marginX, marginY, scaledSize.width, scaledSize.height );
[image drawInRect:scaledImageRect];
UIImage* scaledImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return scaledImage;
}
Please tell me if you need further information.
Solution:
+ (UIImage*) fitImage:(UIImage*)image inBox:(CGSize)size withBackground:(UIColor*)color {
if (image.size.width==size.width && image.size.height==size.height)
return image;
if (image.size.width<size.width && image.size.height<size.height)
return [Util scaleImage:image toSize:size];
float widthFactor = size.width / image.size.width;
float heightFactor = size.height / image.size.height;
CGSize scaledSize = size;
if (widthFactor<heightFactor) {
scaledSize.width = size.width;
scaledSize.height = image.size.height * widthFactor;
} else {
scaledSize.width = image.size.width * heightFactor;
scaledSize.height = size.height;
}
UIGraphicsBeginImageContextWithOptions( size, NO, 0.0 );
float marginX = (size.width-scaledSize.width)/2;
float marginY = (size.height-scaledSize.height)/2;
CGRect scaledImageRect = CGRectMake(marginX, marginY, scaledSize.width, scaledSize.height );
UIImage* temp = UIGraphicsGetImageFromCurrentImageContext();
[color set];
UIRectFill(CGRectMake(0.0, 0.0, temp.size.width, temp.size.height));
[image drawInRect:scaledImageRect];
UIImage* scaledImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return scaledImage;
}
You can use UIRectFill(rect) to fill the background of a bitmap context with the current fill color. To set the fill color you can use [UIColor set].
e.g.
//Get a temp image to determine the size of the bitmap context
UIImage* temp = UIGraphicsGetImageFromCurrentImageContext();
[[UIColor redColor] set]; //set the desired background color
UIRectFill(CGRectMake(0.0, 0.0, temp.size.width, temp.size.height)); //fill the bitmap context
[image drawInRect:scaledImageRect]; //draw your image over the filled background
Is it possible to scale a UIImage to the size of the frame? Take a big image and "force it in" the smaller box.
Please provide an example
If you are actually talking about changing the UIImage and not just changing the display frame, which can be done as described by Mark, by changing the UIViewContentMode of the UIImageView, you can change the size of the actual image with the following UIImage extension (taken from this source)
- (UIImage*)imageByScalingAndCroppingForSize:(CGSize)targetSize
{
UIImage *sourceImage = self;
UIImage *newImage = nil;
CGSize imageSize = sourceImage.size;
CGFloat width = imageSize.width;
CGFloat height = imageSize.height;
CGFloat targetWidth = targetSize.width;
CGFloat targetHeight = targetSize.height;
CGFloat scaleFactor = 0.0;
CGFloat scaledWidth = targetWidth;
CGFloat scaledHeight = targetHeight;
CGPoint thumbnailPoint = CGPointMake(0.0,0.0);
if (CGSizeEqualToSize(imageSize, targetSize) == NO)
{
CGFloat widthFactor = targetWidth / width;
CGFloat heightFactor = targetHeight / height;
if (widthFactor > heightFactor)
scaleFactor = widthFactor; // scale to fit height
else
scaleFactor = heightFactor; // scale to fit width
scaledWidth = width * scaleFactor;
scaledHeight = height * scaleFactor;
// center the image
if (widthFactor > heightFactor)
{
thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5;
}
else
if (widthFactor < heightFactor)
{
thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5;
}
}
UIGraphicsBeginImageContext(targetSize); // this will crop
CGRect thumbnailRect = CGRectZero;
thumbnailRect.origin = thumbnailPoint;
thumbnailRect.size.width = scaledWidth;
thumbnailRect.size.height = scaledHeight;
[sourceImage drawInRect:thumbnailRect];
newImage = UIGraphicsGetImageFromCurrentImageContext();
if(newImage == nil)
NSLog(#"could not scale image");
//pop the context to get back to the default
UIGraphicsEndImageContext();
return newImage;
}
possible dupe of this question:
How to scale a UIImageView proportionally?
I'll copy over the accepted answer text as well. Assuming your frame is a uiview:
imageView.contentMode = UIViewContentModeScaleAspectFit;
will do what you want.
from the docs, here are the other scaling options
UIViewContentMode
Specifies how a view adjusts its content when its size changes.
typedef enum {
UIViewContentModeScaleToFill,
UIViewContentModeScaleAspectFit,
UIViewContentModeScaleAspectFill,
UIViewContentModeRedraw,
UIViewContentModeCenter,
UIViewContentModeTop,
UIViewContentModeBottom,
UIViewContentModeLeft,
UIViewContentModeRight,
UIViewContentModeTopLeft,
UIViewContentModeTopRight,
UIViewContentModeBottomLeft,
UIViewContentModeBottomRight,
} UIViewContentMode;
apple Documentation here:
http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UIImageView_Class/Reference/Reference.html