Reloading UICollectionView With UIImages not Releasing Memory - ios

I use the following code to create borders around images. I loop through the following multiple times to create thumbnail images with borders that are then placed in a UICollectionView.
The problem seems to be that every time I reload the UICollectionView the images are not being released from memory and it seems to build up to the point where it crashes. I don't think it is the UICollectionView code because If I run it with images that don't require a border I don't get any issues.
- (UIImage *)applyFrame:(UIImage *)image selectedFrame:(NSString *)selectedFrame {
UIImage *frame;
NSLog(#"Image Size For Frames: %f, %f",image.size.width,image.size.height);
if(image.size.width == image.size.height){
frame = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:#"%#-Square.png",selectedFrame] ofType:nil]];
}
if(image.size.width > image.size.height){
frame = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:#"%#.png",selectedFrame] ofType:nil]];
}
if(image.size.width < image.size.height){
frame = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:#"%#.png",selectedFrame] ofType:nil]];
frame = [self rotateUIImage:frame clockwise:true];
}
GPUImageAlphaBlendFilter *blendFilter = [[GPUImageAlphaBlendFilter alloc] init];
GPUImagePicture *imageToProcess = [[GPUImagePicture alloc] initWithImage:image];
GPUImagePicture *border = [[GPUImagePicture alloc] initWithImage:frame];
blendFilter.mix = 1.0f;
[imageToProcess addTarget:blendFilter];
[border processImage];
[border addTarget:blendFilter];
[imageToProcess processImage];
return [blendFilter imageFromCurrentlyProcessedOutput];
}
- (UIImage*)rotateUIImage:(UIImage*)sourceImage clockwise:(BOOL)clockwise {
CGSize size = sourceImage.size;
UIGraphicsBeginImageContext(CGSizeMake(size.height, size.width));
[[UIImage imageWithCGImage:[sourceImage CGImage] scale:1.0 orientation:clockwise ? UIImageOrientationRight : UIImageOrientationLeft] drawInRect:CGRectMake(0,0,size.height ,size.width)];
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}

UIImage imageWithContentsOfFile: returns an autorelease object, which will be released only when the app returns to the current run loop. So, might it be that you app loops for a long time executing this code? In this case, the autorelease objects might accumulate, and increase the heap usage.
If so, you could try to insert into the body of the responsible loop an autorelease block:
#autoreleasepool {
...your statements
}

Related

Animated Radar Overlay MKMapView iOS

I am fetching a gif from the NOAA of the current weather radar, I store it in a UIImage and then draw it to an MKMapView, here is some of the code I am using:
image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:#"http://radar.weather.gov/ridge/Conus/RadarImg/latest_radaronly.gif"]]];
MKMapRect theMapRect = [self.overlay boundingMapRect];
CGRect theRect = [self rectForMapRect:theMapRect];
#try {
UIGraphicsBeginImageContext(image.size);
UIGraphicsPushContext(ctx);
[image drawInRect:theRect];
UIGraphicsPopContext();
UIGraphicsEndImageContext();
}
#catch (NSException *exception) {
NSLog(#"Caught an exception while drawing radar on map - %#",[exception description]);
}
#finally {
}
Does anyone know how I can animate this gif repeatedly to achieve a weather like radar you see on the news. I have found several apps that do this and am wondering how I can incorporate it into my own project.
The link you provided doesn't actually show an animated gif. It just retrieves the latest gif. One way you could do it is load the latest 10-20 gif's the NOAA has uploaded here, they seem to update it every 10 minutes, then create a UIImage for each gif and cycle through them in a UIImageview which overlays your map.
For example:
// Set images
radarGIF01 = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:#"http://radar.weather.gov/ridge/Conus/RadarImg/Conus_20150209_0108_N0Ronly.gif"]]];
radarGIF02 = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:#"http://radar.weather.gov/ridge/Conus/RadarImg/Conus_20150209_0118_N0Ronly.gif"]]];
radarGIF03 = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:#"http://radar.weather.gov/ridge/Conus/RadarImg/Conus_20150209_0128_N0Ronly.gif"]]];
radarGIF04 = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:#"http://radar.weather.gov/ridge/Conus/RadarImg/Conus_20150209_0138_N0Ronly.gif"]]];
radarGIF05 = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:#"http://radar.weather.gov/ridge/Conus/RadarImg/Conus_20150209_0148_N0Ronly.gif"]]];
// Add images to array
radarImagesArray = [[NSArray alloc]initWithObjects: radarGIF01, radarGIF02, radarGIF03, radarGIF04, radarGIF05, nil];
// Animate images in UIImageview
_radarImageView.animationImages = radarImagesArray;
_radarImageView.animationDuration = 3.0;
_radarImageView.animationRepeatCount = 0;
[_radarImageView startAnimating];

Merge multiple images into one image in iPhone [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I want to merge multiple images which are of different size & at different points.
I want to merge them all and save it in one copy(image).
so how can i mearge images into one image?
I found the solution which is so simple
you can merge multiple images by creating following method
- (BOOL) mergedImageOnMainImage:(UIImage *)mainImg WithImageArray:(NSArray *)imgArray AndImagePointArray:(NSArray *)imgPointArray
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
UIGraphicsBeginImageContext(mainImg.size);
[mainImg drawInRect:CGRectMake(0, 0, mainImg.size.width, mainImg.size.height)];
int i = 0;
for (UIImage *img in imgArray) {
[img drawInRect:CGRectMake([[imgPointArray objectAtIndex:i] floatValue],
[[imgPointArray objectAtIndex:i+1] floatValue],
img.size.width,
img.size.height)];
i+=2;
}
CGImageRef NewMergeImg = CGImageCreateWithImageInRect(UIGraphicsGetImageFromCurrentImageContext().CGImage,
CGRectMake(0, 0, mainImg.size.width, mainImg.size.height));
UIGraphicsEndImageContext();
[pool release];
if (NewMergeImg == nil) {
return NO;
}
else {
UIImageWriteToSavedPhotosAlbum([UIImage imageWithCGImage:NewMergeImg], self, nil, nil);
return YES;
}
}
now call this method in follwing way
NSArray *imgArray = [[NSArray alloc] initWithObjects:
[UIImage imageNamed:#"image06.png"],
[UIImage imageNamed:#"image07.png"],
[UIImage imageNamed:#"image08.png"],
[UIImage imageNamed:#"image09.png"],
[UIImage imageNamed:#"BackBtn.png"],
[UIImage imageNamed:#"Facebook.png"], nil];
NSArray *imgPointArray = [[NSArray alloc] initWithObjects:
#"10", #"10",
#"10", #"25",
#"30", #"15",
#"30", #"50",
#"20", #"80",
#"25", #"100", nil];
BOOL suc = [self mergedImageOnMainImage:[UIImage imageNamed:#"img001.png"] WithImageArray:imgArray AndImagePointArray:imgPointArray];
if (suc == YES) {
NSLog(#"Images Successfully Mearged & Saved to Album");
}
else {
NSLog(#"Images not Mearged & not Saved to Album");
}
You can use CIImage for this,
-(UIImage *)mergeTwoImage:(UIImage*)image1 andImage2:(UIImage *)image2
{
CIImage *topImage = [[CIImage alloc]initWithImage:image1];
CIImage *backgroundImage = [[CIImage alloc]initWithImage:image2];
CIFilter *darkenFilter = [CIFilter filterWithName:#"CIDarkenBlendMode" keysAndValues:kCIInputImageKey,topImage,
#"inputBackgroundImage",backgroundImage,nil];
CIImage *resultOfFilter = darkenFilter.outputImage;
CIContext *ctx = [CIContext contextWithOptions:nil];
CGImageRef imageToReturn = [ctx createCGImage:resultOfFilter fromRect:resultOfFilter.extent];
UIImage *outputImage = [UIImage imageWithCGImage:imageToReturn];
CGImageRelease(imageToReturn);
imageToReturn = nil;
return outputImage;
}
You can use this code : -
- (IBAction) mergeImage:(id)sender
{
UIImage *framedImage = firstImageView.image;
CGSize size = CGSizeMake(firstImageView.frame.size.width, firstImageView.frame.size.height);
UIGraphicsBeginImageContextWithOptions(size, self.view.alpha, 0.0);
UIImage *imageToPlace = secondImageView.image;
[framedImage drawInRect:CGRectMake(0, 0, firstImageView.frame.size.width, firstImageView.frame.size.height)];
[imageToPlace drawInRect:CGRectMake(18, 25, 242, 243)];
UIImage *imageC = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImageView *newImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, framedImage.size.width,framedImage.size.height)];
newImageView.image = imageC;
newImageView.contentMode = UIViewContentModeScaleAspectFill;
}
This is for 2 images they merge two UIImageViews into one. Same this for multiple images. You have to merge multiple images according to your size.

Memory Warning while playing animated image view

I have the following code to play animation with images:
-(void)playPopAnimation:(void (^)(void))completion{
__block NSMutableArray *images;
float animationDuration = 1.0f;
images = [[NSMutableArray alloc] initWithCapacity:26];
for(int i=1; i<26; i++){
NSString *fileName = [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:#"bulut_pop%d",i] ofType:#"png"];
UIImage *image = [UIImage imageWithContentsOfFile:fileName];
//UIImage* image = [UIImage imageNamed:[NSString stringWithFormat:#"bulut_pop%d.png",i]];
[images addObject:image];
}
[Helper playSound:#"button_pop"];
UIImageView* imageView = [[UIImageView alloc] initWithFrame:self.itemImage.frame];
imageView.animationImages = images;
imageView.animationDuration = animationDuration;
imageView.animationRepeatCount = 1; // 0 = nonStop repeat
[self addSubview:imageView];
[imageView startAnimating];
self.imageButton.userInteractionEnabled = NO;
[[UIApplication sharedApplication] beginIgnoringInteractionEvents];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, animationDuration * NSEC_PER_SEC), dispatch_get_current_queue(), ^{
//[self.delegate myItemCell:self cellDidTappedFor:[self item]];
self.imageButton.userInteractionEnabled = YES;
images = nil;
});
Each time I call this function, memory increases by 10 MB. What is the good way to play animated image views?
Each time you call this method, you add a new image view (with its array of images) to your view. You should refactor your code so that the creation of the array and imageView are inside an if clause testing whether imageView is nil, so that part only runs the first time the method is called (and make imageView a property).

Correctly releasing returned UIImage

I call the following method to get an image which I display in a UIImageView. When I am done with the UIImageView I release myImageView.image. I am happy with how I do this but Instruments is showing a leak of UIImage. How should I be releasing the below instance of UIImage?
-(UIImage *)getImageWithRef:(NSString *)ref {
UIImage *myImage = [[UIImage alloc] initWithContentsOfFile:[NSString stringWithFormat:#"foobar_%#",ref]];
if (myImage == nil) {
myImage = [[UIImage alloc] initWithContentsOfFile:#"foobar_defaultImage"];
}
return myImage;
}
Thanks in advance
Try using auto-release when you return your image.
-(UIImage *)getImageWithRef:(NSString *)ref {
UIImage *myImage = [[UIImage alloc] initWithContentsOfFile:[NSString stringWithFormat:#"foobar_%#",ref]];
if (myImage == nil) {
myImage = [[UIImage alloc] initWithContentsOfFile:#"foobar_defaultImage"];
}
return [myImage autorelease];
}

iOS: cant view downloaded images

I'm a novice in this, so i would like to know what is missing in my code to download/show these images:
self.carView.contentSize = CGSizeMake(280*self.carImages.count-280, 200);
self.carView.pagingEnabled = YES;
CGRect imageRect = CGRectMake(0.0, 0.0,280*self.carImages.count-280, 200);
UIGraphicsBeginImageContext(imageRect.size);
UIImageView *carImg = [[UIImageView alloc] init];
for (int i = 1; i < self.carImages.count; i++) {
NSData *imageData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:[self.carImages objectAtIndex:i]]];
UIImage *carImage = [[UIImage alloc] initWithData:imageData];
[carImage drawAtPoint:CGPointMake(280*(i-1), 0)];
[carImage release];
[imageData release];
NSLog(#"%d",i);
}
carImg.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[self.carView addSubview:carImg];
[carImg release];
carView is my ScrollView.
carImages is a MutableArray with the "URL" of the images.
the pagingEnabled and contentSize are being set, but no images.
I bet i'm missing something very stupid, as i allways do.

Resources