Why does my UIImage take up so much memory? - ios

I have a UIImage that I'm loading into one of my app's views. It is a 10.7 MB image, but when it loads in the app, the app's resource usage suddenly jumps by 50 MB. Why does it do this? Shouldn't memory used increase by only about 10.7MB? I am certain that loading the image is what causes the jump in memory usage because I tried commenting these lines out and the memory usage went back to around 8 MB. Here's how I load the image:
UIImage *image = [UIImage imageNamed:#"background.jpg"];
self.backgroundImageView = [[UIImageView alloc] initWithImage:image];
[self.view addSubview:self.backgroundImageView];
If there is no way to decrease the memory used by this image, is there a way to force it to deallocate when I want it to? I'm using ARC.

No, it should not be 10.7MB. The 10.7MB is the compressed size of the image.
The image loaded in to the UIImage object is a decoded image.
For each pixel in the image 4 bytes (R,G,B and Alpha) are used, therefore you can calculate the memory size, height x width x 4 = total bytes in memory.
So the moment you loaded the image into memory it will take up lots of memory, and since a UIImageView is used to present the image and as a subview the images is kept in memory.
You should try and change the size of the image to match the size of the iOS screen size.

As #rckoenes said
Don't show the images with high file size.
You need to resize the image before you display it.
UIImage *image = [UIImage imageNamed:#"background.jpg"];
self.backgroundImageView =[self imageWithImage:display scaledToSize:CGSizeMake(20, 20)];//Give your CGSize of the UIImageView.
[self.view addSubview:self.backgroundImageView];
-(UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize {
//UIGraphicsBeginImageContext(newSize);
// In next line, pass 0.0 to use the current device's pixel scaling factor (and thus account for Retina resolution).
// Pass 1.0 to force exact pixel size.
UIGraphicsBeginImageContextWithOptions(newSize, NO, 0.0);
[image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}

You can do one thing. if you can afford 50 MB for this image. If this image with 10 mb size is that much critical to your application then. you can release it just after its use to keep memory usage in control.
As you are using ARC there is no option for release but you can do this
#autoreleasepool {
UIImage *image = [UIImage imageNamed:#"background.jpg"];
self.backgroundImageView = [[UIImageView alloc] initWithImage:image];
[self.view addSubview:self.backgroundImageView];
}
using autoreleasepool it will be sure that after this autoreleasepool{} block memory for fat image will be deallocated. making your device RAM happy again.
Hope it helps !

Related

Watermark appears bigger on photos taken with the front camera

My app lets the user take photos, and in every photo there is a small watermark. The problem is: The watermark appears bigger when the photo has been taken with the front camera. I want the watermark to have the same size no matter which camera has been used.
Any ideas?
My code:
UIImage *backgroundImage = image;
UIImage *watermarkImage = [UIImage imageNamed:#"Watermark.png"];
UIGraphicsBeginImageContext(backgroundImage.size);
[backgroundImage drawInRect:CGRectMake(0, 0, backgroundImage.size.width, backgroundImage.size.height)];
[watermarkImage drawInRect:CGRectMake(backgroundImage.size.width - watermarkImage.size.width, backgroundImage.size.height - watermarkImage.size.height, watermarkImage.size.width, watermarkImage.size.height)];
UIImage *result = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
self.imageView.image = result;
The watermark is the same size. The image is not, since the two cameras have different resolutions. You need to resize the watermark in proportion to the image size. I believe you can use scaleImage:toSize: for this.
Figured out a weird solution. I turned on edit mode: [picker setAllowsEditing:YES]; and now the watermark is the same size no matter what camera you use.

iOS - Received memory warning for showing an image on Today Extension

I am trying to download an image from a RSS feed and then show it in today extension widget , the problem is even showing a simple image causes Memory Warning !:
_imageView.image = [UIImage imageName:xxx.jpg];
here is my code to download image using UIImageView+AFNetworking:
[_wImage setImageWithURLRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:[item.imagesFromContent objectAtIndex:0]]]
even tried with NSData :
[_wImage setImage:[UIImage imageWithData:[NSData dataWithContentsOfURL:
[NSURL URLWithString:[item.imagesFromContent objectAtIndex:0]]]]];
the result still is Received memory warning.
Extensions have much lower memory limits than a normal iOS app. I suggest rethinking your architecture and doing less work in the extension itself.
Problem solved ! for those who will face with this problem , you must resize your image simply by :
-(UIImage *)resizeImage :(UIImage *)theImage :(CGSize)theNewSize {
UIGraphicsBeginImageContextWithOptions(theNewSize, NO, 1.0);
[theImage drawInRect:CGRectMake(0, 0, theNewSize.width, theNewSize.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
My image was 1024 x 768 and its size was 100 to 200 kb ! so with this code you shrink its size and save a lot memory .

UIImageView stops displaying images after a specific amount of loop iterations

My iOS app utilizes a loop to cycle through images in a folder.
My application is supposed to loop through a total of 2031 images (sized 1200x900) inside a folder. The images were taken at 8fps and each image will be displayed as the loop continues to simulate a video clip. After the 696th picture, the images will cease to be displayed in the UIImageView although the app will continue looping.
I tested to see if the disconnect was because of the picture not existing
I started the loop at picture 200, but after picture 896 the UIImageView stop displaying the pictures.
The Code:
imgName = [NSString stringWithFormat:#"subject_basline_mat k (%d).png",jojo];
jojo++;
imageToCrop.image = [UIImage imageNamed:imgName]; //imageToCrop is the name of the UIImageView image and it is set to the image file here
imageToCrop.image = [self imageWithImage:imageToCrop.image convertToSize:self.imageToCrop.frame.size]; //Here the image is converted to fit the bounds of the simulator which is 320x240
The code loops due to a timer that loops it about once every 0.8 seconds.
I ran my code with instruments to see if there was a memory problem occurring,and instruments is very heavy on my computer. As such, my application ran quite slowly. However, when I arrived at the 696th picture, the pictures kept displaying themselves. It was almost as if my application running too quickly caused the picture to not be displayed... which I don't really understand.
The only memory heavy part of the image switching seems to be the size conversion step which is called by the line imageToCrop.image = [self imageWithImage:imageToCrop.image convertToSize:self.imageToCrop.frame.size];
imageToCrop.image = [self imageWithImage:imageToCrop.image convertToSize:self.imageToCrop.frame.size];
The method "imageWithImage" is here:
- (UIImage *)imageWithImage:(UIImage *)image convertToSize:(CGSize)size {
#autoreleasepool {
UIGraphicsBeginImageContext(size);
[image drawInRect:CGRectMake(0, 0, size.width, size.height)];
UIImage *destImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return destImage;
}
And the line [image drawInRect:CGRectMake(0, 0, size.width, size.height)]; uses around up the most memory out of all the image management in the app.
Any Ideas as to why my app will only display a certain amount of images?
Try loading the full-size images from the app bundle by URL. For example:
#autoreleasepool {
NSString *imgName = [NSString stringWithFormat:#"subject_basline_mat k (%d)",jojo];
NSURL *imageURL = [[NSBundle mainBundle] URLForResource:imgName withExtension:#"png"];
UIImage *image = [UIImage imageWithContentsOfFile:[imageURL path]];
imageToCrop.image = [self imageWithImage:image convertToSize:self.imageToCrop.frame.size];
}
Almost for sure your problem is [UIImage imageNamed:imgName]. There are hundreds of posts here on the pitfalls of using it. The issue is that it caches the images - its real purpose is for some small number of images in your bundle.
If you have oodles of images, get the path to the image, then get the image through a URL or file pointer. That way its not cached. Note that when you do this, you lose the automatic "get-retina-image-automatically", and so you will need to grab the appropriately sized image depending on whether the device is retina or not.

Reduce Resolution UIImage/UIImageView [duplicate]

This question already has answers here:
The simplest way to resize an UIImage?
(34 answers)
Closed 9 years ago.
I've created a UIImageView which contains an image with a high resolution. The problem is that the resolution of that image is too high to put into the imageView. The size of the imageView is 92 x 91 (so it's small). It contains an UIImage, whose resolution is too high so it looks ugly in the UIImageView.
So how can I reduce the resolution of that UIImage?
My code for the UIImageView:
UIImageView *myImageView = [[UIImageView alloc] initWithImage:[UIImage imageWithContentsOfFile:pngFilePath]];
myImageView.frame = CGRectMake(212.0, 27, 92,91);
have a look at this
https://stackoverflow.com/a/2658801
This will help you to resize your image according to your need
Add method to your code and call like this
UIImage *myImage =[UIImage imageWithContentsOfFile:pngFilePath];
UIImage *newImage =[UIImage imageWithImage:myImage scaledToSize:CGSizeMake(92,91)];
You can resize an image using this method that returns a resized image :
-(UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize {
UIGraphicsBeginImageContextWithOptions(newSize, NO, 0.0);
// Here pass new size you need
[image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
Hope it helps you.
try with this
myImageView.contentMode = UIViewContentModeScaleToFill;
You need to downsize the image, which will reduce the resolution, make it easier to store. I actually wrote a class (building on some stuff from SO) that does just that. It's on my github, take a look:
https://github.com/pavlovonline/UIImageResizer
the main method is
-(UIImage*)resizeImage:(UIImage*)image toSize:(CGFloat)size
so you give this method the size to which you want to downsize your image. If the height is greater than the width, it will auto-calculate the middle and give you a perfectly centered square. Same for width being greater than height. If you need an image that is not square, make your own adjustments.
so you'll get back a downsized UIImage which you can then put into your UIImageView. Save some memory too.

IOS : Reduce image size without reducing image quality

I am displaying an image in tableview cell (Image name saved in a plist). Before setting it to the cell, I am resizing the image to
imageSize = CGSizeMake(32, 32);
But, after resizing the image, quality is also getting degraded in retina display.
I have both the images added to the project (i.e. 1x and #2x).
This is how I am reducing the image size to 32x32.
+ (UIImage *)scale:(UIImage *)image toSize:(CGSize)size
{
UIGraphicsBeginImageContext(size);
[image drawInRect:CGRectMake(0, 0, size.width, size.height)];
UIImage *scaledImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return scaledImage;
}
Any pointers on this is very much appreciated.
Thanks
try this : instead of UIGraphicsBeginImageContext(size);use UIGraphicsBeginImageContextWithOptions(size,NO,0.0);
from what i understand what you're doing there is resizing the image to 32x32 (in points) no matter what the resolution. the UIGraphicsBeginImageContextWithOptions scales the image to the scale of the device's screen..so you have the image resized to 32x32 points but the resolution is kept for retina display
(note that this is what i understood from apple's uikit reference..it may not be so..but it should)
read here

Resources