imageWithContentsOfFile memory issue - ios

My project is having image sharing functionality. In this functionality my app asks the user from which library you want to share.
I wrote below code to assign image, retrieved from Default library/Custom library.
Device default library
imgVwMediaFile.image = [UIImage imageWithCGImage:[asset thumbnail]; //(ALAsset *)asset
Custom library (images are at Documents/image/user)
imgVwMediaFile.image = [UIImage imageWithContentsOfFile:path];
//(NSString*)path
App displyas this images in collection view having custom cell.
When i select app custom library then images are retrieves from Documents directory ,but imagewithcontentofFile cosuming around 90 to 100 Mb memory.
In other case when i select app default libray, it is not cosuming more then 8 or 10 Mb memory.
I tried diffrent code from stack Q/A for custom library, but still memory issue is there.
-1-
CGImageRef iref = [[UIImage imageNamed:asset] CGImage] ;
imgVwMediaFile.image=[UIImage imageWithCGImage:iref];
iref=nil
-2-
NSData *imageData = [[NSData alloc] initWithContentsOfFile:path];
imgVwMediaFile.image=[UIImage imageWithData:imageData];
imageData=nil
-3-
imgVwMediaFile.image=[UIImage imageNamed:path];
So please guide me that, how can i load images from document dir ?
What are the best way to load images from document dir without increasing memory load ?

The problem is that yhe images you have saved to disk are large, so loading lots of the, to display in a collection takes a lot of memory. You use thumbnails from the built in library so you see a different result.
Ideally you would save a folder of thumbnails in your custom library and display those, then, when an image is selected, get the corresponding full size image to use (this is the approach basically all photo libraries use). Alternatively you can resize the images on-the-fly, but your scrolling is basically guaranteed to suck.

UIImage *img = [UIImage imageWithContentsOfFile:path];

Related

I have to download a large number of big size images and show in table view?

I am getting memory warning when loading large images, i have to cache the images also so that if the user will scroll up that image should be present. I am using SDWebImage Library.
cell!.productImageView?.sd_setImageWithURL(url)
According to your scenario I have two suggestions:
1. Generally recommended is that we can upload small size images on server so that we can avoid memory problems. A thumbnail or a small dimension sized image is considered if we are showing the images in a UITableView.However we can show larger image when we tap on a certain small image in UITableView and go to a detail view controller.
2. Secondly you can download the images and resize them and then use NSCache class to cache them rather using SDWebImage. As in your case imageWithContentsOfFile can't be used because you are downloading the images from some URL.However after download you can use imageWithContentsOfFile or you can resize images and use your own NSCache.
What are you using for display image on image view .UIImage imageNamed is maintain cache itself.
Please use below code.
[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"imageName" ofType:#"png"]];
This will helpful to you for manage memory consumptions.
Try this code.
NSString *thumbnailImage = objectname.thumbnailUrl;
[cell.productImageView sd_setImageWithURL:[NSURL URLWithString:thumbnailImage]];

Quick way to load images

Right now I'm loading images view a file url and its taking a long time. I've even put it on the main thread as a high priority but its still slow. This is actually in a loop for like 6 images. My question is:
Is there a faster way to load images to a view than this? Like an alternative to a file url?
//check the filetype
if ([fileType isEqual: #"image"])
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
//get image
NSURL *imageFileUrl = [[NSURL alloc] initWithString:file.url];
NSData *imageData = [NSData dataWithContentsOfURL:imageFileUrl];
dispatch_async(dispatch_get_main_queue(), ^{
imageView.image = [UIImage imageWithData:imageData];
});
});
}
My images are at a quality of this preset and the size is the size of the iphone screen whether that be a 5,6,or 6 plus
self.camera = [[LLSimpleCamera alloc] initWithQuality:AVCaptureSessionPreset1280x720
position:CameraPositionBack
videoEnabled:YES];
thanks,
While there isn't any shortcut to loading the images there are things you can do to help.
Initially only load the image that are visible, after that load any that may be visible soon.
If the size of the image is larger than the view create a smaller image, perhaps a couple for different screen resolution devices.
Create a low resolution image versions, load them first to get something up for the user and then load the full resolution images replacing the low resolution version..
Please, Add the sizes of the images and the sizes of the UIImageView and screen resolution to the question.
What can I suggest you that,
Save the duplicate copy of each image in lower resolution/Size on
server.
Load the duplicate image on first load.
When user particularly views an image, load original image then.

iPhone app memory leak with UIImages in NSMutableArray

I have an NSMutableArray that contains images. I then have an image view that displays images from that array. However, I am getting a big memory leak each time it loads the image view. I am not sure how to correct that. I am using ARC in Xcode 5.0.2.
_image1 = [UIImage imageNamed:#"FirstImage.png"];
imagearray = [[NSMutableArray alloc] init];
[imagearray addObject:_image1];
_imageview1 setImage:[imagearray objectAtIndex:0]];
The memory leak issue might be due to the UIImage not getting nil. For that, you have to initialize UIImage with alloc and after adding it to the array, make it nil. You can prevent you memory leak in this way:
UIImage *image1 =[[UIImage alloc]initWithContentsOfFile:[[NSBundle mainBundle]pathForResource:#"FirstImage" ofType:#"png"]];
[imagearray addObject:image1];
_imageview1 setImage:[imagearray objectAtIndex:0]];
image1 =nil;
Please let me kniw if it works. Thanks :)
From apple doc:
+ (UIImage)imageNamed: method looks in the system caches for an image object with the specified name and returns that object if it exists.
If a matching image object is not already in the cache, this method
loads the image data from the specified file, caches it, and then
returns the resulting object.
If you have an image file that will only be displayed once and wish to
ensure that it does not get added to the system’s cache, you should
instead create your image using imageWithContentsOfFile:. This will
keep your single-use image out of the system image cache, potentially
improving the memory use characteristics of your app.
So as a suggestion, if you replace the imageNamed: with imageWithContentsOfFile: to avoid caching, your memory footprint should improve

How to find UIImage Bottleneck

I have an app that uses UIImage objects. Up to this point, I've been using image objects initialized using something like this:
UIImage *image = [UIImage imageNamed:imageName];
using an image in my app bundle. I've been adding functionality to allow users to use imagery from the camera or their library using UIImagePickerController. These images, obviously, can't be in my app bundle, so I initialize the UIImage object a different way:
UIImage *image = [UIImage imageWithContentsOfFile:pathToFile];
This is done after first resizing the image to a size similar to the other files in my app bundle, in both pixel dimensions and total bytes, both using Jpeg format (interestingly, PNG was much slower, even for the same file size). In other words, the file pointed to by pathToFile is a file of similar size as an image in the bundle (pixel dimensions match, and compression was chosen so byte count was similar).
The app goes through a loop making small pieces from the original image, among other things that are not relevant to this post. My issue is that going through the loop using an image created the second way takes much longer than using an image created the first way.
I realize the first method caches the image, but I don't think that's relevant, unless I'm not understanding how the caching works. If it is the relevant factor, how can I add caching to the second method?
The relevant portion of code that is causing the bottleneck is this:
[image drawInRect:self.imageSquare];
Here, self is a subclass of UIImageView. Its property imageSquare is simply a CGRect defining what gets drawn. This portion is the same for both methods. So why is the second method so much slower with similar sized UIImage object?
Is there something I could be doing differently to optimize this process?
EDIT: I change access to the image in the bundle to imageWithContentsOfFile and the time to perform the loop changed from about 4 seconds to just over a minute. So it's looking like I need to find some way to do caching like imageNamed does, but with non-bundled files.
UIImage imageNamed doesn't simply cache the image. It caches an uncompressed image. The extra time spent was not caused by reading from local storage to RAM but by decompressing the image.
The solution was to create a new uncompressed UIImage object and use it for the time sensitive portion of the code. The uncompressed object is discarded when that section of code is complete. For completeness, here is a copy of the class method to return an uncompressed UIImage object from a compressed one, thanks to another thread. Note that this assumes data is in CGImage. That is not always true for UIImage objects.
+(UIImage *)decompressedImage:(UIImage *)compressedImage
{
CGImageRef originalImage = compressedImage.CGImage;
CFDataRef imageData = CGDataProviderCopyData(
CGImageGetDataProvider(originalImage));
CGDataProviderRef imageDataProvider = CGDataProviderCreateWithCFData(imageData);
CFRelease(imageData);
CGImageRef image = CGImageCreate(
CGImageGetWidth(originalImage),
CGImageGetHeight(originalImage),
CGImageGetBitsPerComponent(originalImage),
CGImageGetBitsPerPixel(originalImage),
CGImageGetBytesPerRow(originalImage),
CGImageGetColorSpace(originalImage),
CGImageGetBitmapInfo(originalImage),
imageDataProvider,
CGImageGetDecode(originalImage),
CGImageGetShouldInterpolate(originalImage),
CGImageGetRenderingIntent(originalImage));
CGDataProviderRelease(imageDataProvider);
UIImage *decompressedImage = [UIImage imageWithCGImage:image];
CGImageRelease(image);
return decompressedImage;
}

How to reduce the memory size of the image saved in Document Directory?

I have made an iphone app in which i download the images via FTP & saved in document Directory. These Images are of high memory size (approx. 2-3 MB).
Then I display these images in UITableview with many rows & due to these Images the allocation memory is too big & that's why app crashes.
So, I need to reduce the memory size of these images.
How can I do this?
Thanks,
Make thumbnail of the images before you add them to the UITableView. In this way the size of the images would reduce drastically. Use the following code on the UIImages you are picking from the document directory .
UIImage *originalImage = ...;
CGSize destinationSize = ...;
UIGraphicsBeginImageContext(destinationSize);
[originalImage drawInRect:CGRectMake(0,0,destinationSize.width,destinationSize.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
Also have a look at the following links :-
Thumbnail view of images
http://www.icab.de/blog/2010/10/01/scaling-images-and-creating-thumbnails-from-uiviews/
https://gist.github.com/djbriane/160791

Resources