2

I am developing one application.In that i am getting the images from the server. And I want to use the images as background for UIView. And when I use that images directly as background for uiview then UIView loading very slowly. So before set that image as background to UIView I want to check the image size and want to decrease the size of the image. So Please tell me how find out and change the size of the images. I am using below code to set the image as background for UIView

 UIGraphicsBeginImageContext(self.view.frame.size);
[[UIImage imageNamed:@"image.png"] drawInRect:self.view.bounds];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
 self.view.backgroundColor = [UIColor colorWithPatternImage:image];

drawrect method takes more time to execute.

Cœur
  • 37,241
  • 25
  • 195
  • 267
venkat
  • 93
  • 1
  • 1
  • 6
  • *sidenote:* `[UIImage imageNamed:]` has memory leak problems. Search Google for more details. – Raptor Apr 26 '13 at 09:59
  • 1
    Thats not a matter.This is my example code.Actually i got the image from directory.Whatever i get the images from server i can store in directory. – venkat Apr 26 '13 at 10:01
  • @ShivanRaptor Can you post some links explaining that? To my knowledge UIImage imageNamed: not only does not leak, but also caches the image for subsequent loads. – Javier Quevedo Apr 26 '13 at 10:53
  • both are true. this function causes memory leak as it holds the UIImage in memory until you intentionally clear it. It is suitable for images that stay in screen, but not for images that uses for short time. Reference: http://stackoverflow.com/questions/7201029/avoid-uiimages-imagenamed-memory-management – Raptor Apr 26 '13 at 10:58
  • Additional information: http://akosma.com/2009/01/28/10-iphone-memory-management-tips/ – Raptor Apr 26 '13 at 10:59
  • http://stackoverflow.com/questions/1282830/uiimagepickercontroller-uiimage-memory-and-more This thread shows you how to decrease an image (both resolution and memory size) – Marc Sep 04 '13 at 18:22
  • While imageNamed: might not be your best bet here, the leaking was fixed loooong ago. – Eiko Sep 04 '13 at 20:41

4 Answers4

2

Here is a function that you can put in a category or helper class to resize a UIImage programatically. I found it somewhere here in the site but I can't find the exact post right now.

Keep in mind that this will take some time to process. Ideally you should do this only once if you want to get a performance boost in future uses of the same image.

Here it goes:

+ (UIImage *)imageByScalingProportionallyToSize:(CGSize)targetSize withOriginalImage:(UIImage *)origin {

    UIImage *sourceImage = origin;
    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;
        else
            scaleFactor = heightFactor;

        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;
        }
    }


    // this is actually the interesting part:

    UIGraphicsBeginImageContext(targetSize);

    CGRect thumbnailRect = CGRectZero;
    thumbnailRect.origin = thumbnailPoint;
    thumbnailRect.size.width  = scaledWidth;
    thumbnailRect.size.height = scaledHeight;

    [sourceImage drawInRect:thumbnailRect];

    newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    if(newImage == nil) NSLog(@"could not scale image");

    return newImage ;
}

You can call it the following way:

UIImage *mySmallImage = [ImageHelper imageByScalingProportionallyToSize:CGSizeMake(128,128) withOriginalImage:(UIImage *)myLargeImage];
Pradip Sutariya
  • 257
  • 2
  • 16
Javier Quevedo
  • 2,066
  • 1
  • 17
  • 27
  • I think it is useful to decrese the size(width and height).But i don't want this size.I want to decrease the memory size.For example the size of the image is more than 2mb then i want to decrease that size to 1mb. – venkat Apr 26 '13 at 09:59
  • @Venkat Please check this: http://stackoverflow.com/questions/6141298/how-to-scale-down-a-uiimage-and-make-it-crispy-sharp-at-the-same-time-instead – Amit Apr 26 '13 at 10:04
  • Tha one also did same thing.I used that one.but no result. – venkat Apr 26 '13 at 10:29
  • @venkat its important to understand that the size in memory of a UIImage is directly related to the amount of pixels that the image contains. Reducing the size of an image not by changing its presentation (let's say frame), but by reducing the amount of pixes (as the funcion I posted), will indeed reduce the size in memory. – Javier Quevedo Apr 26 '13 at 10:52
  • What can i send as argument to ur function as targetsize. – venkat Apr 26 '13 at 11:53
  • There is an example in my answer. Essentially you need to provide a size in pixels. For instance for a size of 128x128 pixels, you will need to provide: CGSizeMake(128,128). Here is the complete example: UIImage *mySmallImage = [ImageHelper imageByScalingProportionallyToSize:CGSizeMake(128,128) withOriginalImage:myLargeImage]; – Javier Quevedo Apr 26 '13 at 12:10
  • This answer is irrelevant since the context size needs to be `self.view.frame.size` – Desdenova Apr 26 '13 at 12:29
1

You will have to give up some image quality:

NSData *imageData = UIImageJPEGRepresentation(image, 0.3);   //increase compression by varying the 0.3 the normal is 1.0
image = [UIImage imageWithData:imageData];

Edit: To see what will be the size, you can use:

NSLog(@"%d",imageData.length);
user523234
  • 14,323
  • 10
  • 62
  • 102
  • This is the only valid answer since the context size needs to be `self.view.frame.size` – Desdenova Apr 26 '13 at 12:29
  • Except that creating a UIImage from the JPEG data immediately uncompresses it. You end back up with an image of the same color depth and dimensions, which will use the same amount of memory. – Sixten Otto Apr 26 '13 at 12:48
  • I don't think that reducing quality will necessarily reduce the amount of memory used by the image. In the end, when creating a UIImage again, the pixel buffer will hold the same amount of pixels, as its the same size. – Javier Quevedo Apr 26 '13 at 15:23
0

-(UIImage *)ResizeImage :(CGSize) newsize image:(UIImage *)image {

// UIImage * image = [UIImage imageNamed:@"Lion.jpg"];
float imageHeight = image.size.height;
float imageWidth = image.size.width;

float hfactor = imageWidth / newsize.width;
float vfactor = imageHeight / newsize.height;

float factor = fmax(hfactor, vfactor);
// Divide the size by the greater of the vertical or horizontal shrinkage factor
float newWidth = imageWidth / factor;
float newHeight = imageHeight / factor;

UIGraphicsBeginImageContext(CGSizeMake(newWidth, newHeight));
[image drawInRect:CGRectMake(0, 0, newWidth, newHeight)];
UIImage * newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;

}

Ajay Malviya
  • 131
  • 4
0

I solved this with the code below. Hope it helps you:

CGFloat ratio;  

if (img.size.width > 500 || img.size.height > 500) //Checking for image is higher then 500 or not
{
    if (img.size.width > img.size.height)
    {
        ratio = 500 / img.size.width;

    }
    else
    {
        ratio = 500 / img.size.height;

    }

    CGSize imageSize = CGSizeMake(img.size.width * ratio,img.size.height * ratio);
    UIGraphicsBeginImageContext(imageSize);
    CGRect imageRect = CGRectMake(0.0, 0.0, imageSize.width, imageSize.height);

    [img drawInRect:imageRect];
    img = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext(); 
nhahtdh
  • 55,989
  • 15
  • 126
  • 162
iKambad
  • 351
  • 1
  • 2
  • 13