Madan Mohan
Madan Mohan

Reputation: 8810

How to resize the image programmatically in objective-c in iphone

I have an application where I am displaying large images in a small space. The images are quite large, but I am only displaying them in 100x100 pixel frames. My app is responding slowly because of the size fo the images I am using.

To improve performance, how can I resize the images programmatically using Objective-C?

Upvotes: 50

Views: 82558

Answers (10)

CrazyMind90
CrazyMind90

Reputation: 169

This c method will resize your image with cornerRadius "Without effecting image's quality" :


UIImage *Resize_Image(UIImage *iImage, CGFloat iSize, CGFloat icornerRadius) {

    CGFloat scale = MAX(CGSizeMake(iSize ,iSize).width/iImage.size.width, CGSizeMake(iSize ,iSize).height/iImage.size.height);
    CGFloat width = iImage.size.width * scale;
    CGFloat height = iImage.size.height * scale;
    CGRect imageRect = CGRectMake((CGSizeMake(iSize ,iSize).width - width)/2.0f,(CGSizeMake(iSize ,iSize).height - height)/2.0f,width,height);
    UIGraphicsBeginImageContextWithOptions(CGSizeMake(iSize ,iSize), NO, 0);
    [[UIBezierPath bezierPathWithRoundedRect:imageRect cornerRadius:icornerRadius] addClip];
    [iImage drawInRect:imageRect];
    UIImage *ResizedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return ResizedImage;
}

This is how to use :

UIImage *ResizedImage = Resize_Image([UIImage imageNamed:@"image.png"], 64, 14.4);
  • I do not remember where i took the first 4 lines ..

Upvotes: 0

Kaushik Movaliya
Kaushik Movaliya

Reputation: 857

This code is for just change image scale not for resizing. You have to set CGSize as your image width and hight so the image will not stretch and it arrange at the middle.

- (UIImage *)imageWithImage:(UIImage *)image scaledToFillSize:(CGSize)size
{
    CGFloat scale = MAX(size.width/image.size.width, size.height/image.size.height);
    CGFloat width = image.size.width * scale;
    CGFloat height = image.size.height * scale;
    CGRect imageRect = CGRectMake((size.width - width)/2.0f,
                                  (size.height - height)/2.0f,
                                  width,
                                  height);

    UIGraphicsBeginImageContextWithOptions(size, NO, 0);
    [image drawInRect:imageRect];
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return newImage;
}

Upvotes: 17

serjbirchfield
serjbirchfield

Reputation: 11

Hello from the end of 2018. Solved with next solution (you need only last line, first & second are just for explanation):

NSURL *url = [NSURL URLWithString:response.json[0][@"photo_50"]];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:data scale:customScale];

'customScale' is scale which you want (>1 if image must be smaller, <1 if image must be bigger).

Upvotes: 1

Eric Witherspoon
Eric Witherspoon

Reputation: 16

This thread is old, but it is what I pulled up when trying to solve this problem. Once the image is scaled it was not displaying well in my container even though I turned auto layout off. The easiest way for me to solve this for display in a table row, was to paint the image on a white background that had a fixed size.

Helper function

+(UIImage*)scaleMaintainAspectRatio:(UIImage*)sourceImage :(float)i_width :(float)i_height
{
float newHeight = 0.0;
float newWidth = 0.0;

float oldWidth = sourceImage.size.width;
float widthScaleFactor = i_width / oldWidth;

float oldHeight = sourceImage.size.height;
float heightScaleFactor = i_height / oldHeight;
if (heightScaleFactor > widthScaleFactor) {
    newHeight = oldHeight * widthScaleFactor;
    newWidth = sourceImage.size.width * widthScaleFactor;
} else {
    newHeight = sourceImage.size.height * heightScaleFactor;
    newWidth = oldWidth * heightScaleFactor;
}

// return image in white rect
float cxPad = i_width - newWidth;
float cyPad = i_height - newHeight;
if (cyPad > 0) {
    cyPad = cyPad / 2.0;
}
if (cxPad > 0) {
    cxPad = cxPad / 2.0;
}

CGSize size = CGSizeMake(i_width, i_height);
UIGraphicsBeginImageContextWithOptions(CGSizeMake(size.width, size.height), YES, 0.0);
[[UIColor whiteColor] setFill];
UIRectFill(CGRectMake(0, 0, size.width, size.height));
[sourceImage drawInRect:CGRectMake((int)cxPad, (int)cyPad, newWidth, newHeight)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;

// will return scaled image at actual size, not in white rect
// UIGraphicsBeginImageContext(CGSizeMake(newWidth, newHeight));
// [sourceImage drawInRect:CGRectMake(0, 0, newWidth, newHeight)];
// UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
// UIGraphicsEndImageContext();
// return newImage;
}

I called this like this from my table view cellForRowAtIndexPath

    PFFile *childsPicture = [object objectForKey:@"picture"];
[childsPicture getDataInBackgroundWithBlock:^(NSData *imageData, NSError *error) {
    if (!error) {
        UIImage *largePicture = [UIImage imageWithData:imageData];
        UIImage *scaledPicture = [Utility scaleMaintainAspectRatio:largePicture :70.0 :70.0 ];
        PFImageView *thumbnailImageView = (PFImageView*)[cell viewWithTag:100];
        thumbnailImageView.image = scaledPicture;
        [self.tableView reloadData];
    }
}];

Upvotes: 0

Satya
Satya

Reputation: 3330

Please find the following code.

- (UIImage *)imageWithImage:(UIImage *)image convertToSize:(CGSize)size {
    UIGraphicsBeginImageContext(size);
    [image drawInRect:CGRectMake(0, 0, size.width, size.height)];
    UIImage *destImage = UIGraphicsGetImageFromCurrentImageContext();    
    UIGraphicsEndImageContext();
    return destImage;
}

Upvotes: 103

user8115970
user8115970

Reputation:

   -(UIImage *)scaleImage:(UIImage *)image toSize:.     (CGSize)targetSize
   {
//If scaleFactor is not touched, no scaling will occur
   CGFloat scaleFactor = 1.0;

//Deciding which factor to use to scale the image (factor = targetSize / imageSize)
if (image.size.width > targetSize.width || 
   image.size.height > targetSize.height || image.size.width == image.size.height)
    if (!((scaleFactor = (targetSize.width / 
    image.size.width)) > (targetSize.height / 
      image.size.height))) //scale to fit width, or
        scaleFactor = targetSize.height / image.size.height; // scale to fit heigth.

Upvotes: 1

Vijay Sharma
Vijay Sharma

Reputation: 1076

If you are using a image on different sizes and resizing each time it will degrade your app performance. Solution is don't resize them just use button in place of imageview. and just set the image on button it will resize automatically and you will get great performance.

I was also resizing images while setting it on cell but my app got slow So I used Button in place of imageview (not resizing images programatically button is doing this job) and it is working perfectly fine.

Upvotes: 1

Yusuf terzi
Yusuf terzi

Reputation: 186

You can use this.

[m_Image.layer setMinificationFilter:kCAFilterTrilinear];

Upvotes: 0

matt
matt

Reputation: 535178

My favorite way to do this is with CGImageSourceCreateThumbnailAtIndex (in the ImageIO framework). The name is a bit misleading.

Here's an excerpt of some code from a recent app of mine.

CGFloat maxw = // whatever;
CGFloat maxh = // whatever;

CGImageSourceRef src = NULL;
if ([imageSource isKindOfClass:[NSURL class]])
    src = CGImageSourceCreateWithURL((__bridge CFURLRef)imageSource, nil);
else if ([imageSource isKindOfClass:[NSData class]])
    src = CGImageSourceCreateWithData((__bridge CFDataRef)imageSource, nil);

// if at double resolution, double the thumbnail size and use double-resolution image
CGFloat scale = 1;
if ([[UIScreen mainScreen] scale] > 1.0) {
    scale = 2;
    maxw *= 2;
    maxh *= 2;
}

// load the image at the desired size
NSDictionary* d = @{
                    (id)kCGImageSourceShouldAllowFloat: (id)kCFBooleanTrue,
                    (id)kCGImageSourceCreateThumbnailWithTransform: (id)kCFBooleanTrue,
                    (id)kCGImageSourceCreateThumbnailFromImageAlways: (id)kCFBooleanTrue,
                    (id)kCGImageSourceThumbnailMaxPixelSize: @((int)(maxw > maxh ? maxw : maxh))
                    };
CGImageRef imref = CGImageSourceCreateThumbnailAtIndex(src, 0, (__bridge CFDictionaryRef)d);
if (NULL != src)
    CFRelease(src);
UIImage* im = [UIImage imageWithCGImage:imref scale:scale orientation:UIImageOrientationUp];
if (NULL != imref)
    CFRelease(imref);

Upvotes: 7

iAndroid
iAndroid

Reputation: 951

Since the code ran perfectly fine in iOS 4, for backwards compatibility I added a check for OS version and for anything below 5.0 the old code would work.

- (UIImage *)resizedImage:(CGSize)newSize interpolationQuality:(CGInterpolationQuality)quality {
    BOOL drawTransposed;
    CGAffineTransform transform = CGAffineTransformIdentity;

    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 5.0) {
        // Apprently in iOS 5 the image is already correctly rotated, so we don't need to rotate it manually
        drawTransposed = NO;  
    } else {    
        switch (self.imageOrientation) {
            case UIImageOrientationLeft:
            case UIImageOrientationLeftMirrored:
            case UIImageOrientationRight:
            case UIImageOrientationRightMirrored:
                drawTransposed = YES;
                break;

            default:
                drawTransposed = NO;
        }

        transform = [self transformForOrientation:newSize];
    } 

    return [self resizedImage:newSize
                    transform:transform
               drawTransposed:drawTransposed
         interpolationQuality:quality];
}

Upvotes: 0

Related Questions