UIGraphicsContext memory leak - iphone

Hi In my app I have a function that takes an Image of the current view and turns it into a blurred image then adds it to the current.view. All though I remove the view using [remove from superview] it the memory still stays high. I am using core graphics and set all of the UI Images to zero.
I do get a memory leak warning
-(void)burImage
{
//Get a screen capture from the current view.
UIGraphicsBeginImageContext(CGSizeMake(320, 450));
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImg = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
//Blur the image
CIImage *blurImg = [CIImage imageWithCGImage:viewImg.CGImage];
CGAffineTransform transform = CGAffineTransformIdentity;
CIFilter *clampFilter = [CIFilter filterWithName:#"CIAffineClamp"];
[clampFilter setValue:blurImg forKey:#"inputImage"];
[clampFilter setValue:[NSValue valueWithBytes:&transform objCType:#encode(CGAffineTransform)] forKey:#"inputTransform"];
CIFilter *gaussianBlurFilter = [CIFilter filterWithName: #"CIGaussianBlur"];
[gaussianBlurFilter setValue:clampFilter.outputImage forKey: #"inputImage"];
[gaussianBlurFilter setValue:[NSNumber numberWithFloat:22.0f] forKey:#"inputRadius"];
CIContext *context = [CIContext contextWithOptions:nil];
CGImageRef cgImg = [context createCGImage:gaussianBlurFilter.outputImage fromRect:[blurImg extent]];
UIImage *outputImg = [UIImage imageWithCGImage:cgImg];
//Add UIImageView to current view.
UIImageView *imgView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 450)];
[imgView setTag:1109];
imgView.image = outputImg;
[imgView setTag:1108];
gaussianBlurFilter = nil;
outputImg = nil;
blurImg = nil;
viewImg = nil;
[self.view addSubview:imgView];
UIGraphicsEndImageContext();
}

The static analyzer ("Analyze" on the Xcode "Product" menu) is informing you that you are missing a needed CGImageRelease(cgImg) at the end of your method. If you have a Core foundation object returned from a method/function with "Create" or "Copy" in the name, you are responsible for releasing it.
By the way, if you tap on the icon (once in the margin, and again on the version that appears in the error message), it will show you more information:
That can be helpful for tracking back to where the problem originated, in this case the call to createCGImage. If you look at the documentation for createCGImage, it confirms this diagnosis, reporting:
Return Value
A Quartz 2D image. You are responsible for releasing the returned image when you no longer need it.
For general counsel about releasing Core Foundation objects, see the Create Rule in the Memory Management Programming Guide for Core Foundation.

Related

Take a snapshot of a PKAddPassesViewController's view

I'm trying to take a snapshot of the view displayed when the user is prompted to add a pass.
The goal is being able to generate an image from a given pkpass
I was hoping something like this could work:
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"columbus" ofType:#"pkpass"];
PKPass *pass = [[PKPass alloc] initWithData:[NSData dataWithContentsOfFile:filePath] error:nil];
PKAddPassesViewController *pkAddPassesViewController = [[PKAddPassesViewController alloc] initWithPass:pass];
[self presentViewController:pkAddPassesViewController animated:YES completion:^(){
UIImage *image = [pkAddPassesViewController.view captureView];
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
[self.view addSubview:imageView];
}];
With captureView being:
- (UIImage *)captureView
{
CGRect screenRect = self.bounds;
UIGraphicsBeginImageContext(self.bounds.size);
CGContextRef ctx = UIGraphicsGetCurrentContext();
[[UIColor clearColor] set];
CGContextFillRect(ctx, screenRect);
[self.layer renderInContext:ctx];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
Guess what? I was wrong:
I tried:
Using the completion callback and the animationFinished callback
Setting the hidden property
Using a timer to make sure the pass was visible on screen when the screenshot was taken
Taking a snapshot of the parent view
I ran out of ideas, so any suggestion is appreciated
Thanks in advance
Oh, I've uploaded a minimal project here:
https://github.com/framp/demo-capturing-passbook
EDIT:
I'm able to take a snapshot of other views and I can load other UIImage just fine with the code above.
The UIImage which is returned is a blank image
Try this, this might work for you.
UIGraphicsBeginImageContext(self.view.frame.size);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *newImage=UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSData *imageData=UIImagePNGRepresentation(reportImage);
The capture image code is good. Try with : [self.view.superview addSubview:imageView]; in the completion block instead of [self.view addSubview:imageView];
You can try this code if that work for you. Give the Coordinates which you want to capture and thats it. It will save your file in image album. It may give a warning but it works.
UIGraphicsBeginImageContext(CGSizeMake(320, 380));
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImageWriteToSavedPhotosAlbum(viewImage, nil, nil, nil);
I think pkAddPassesViewController is not fully loaded when you taken snapshot. So my suggestion is to take screenshot after some delay.
I hope it will work.

Adding Filters to imageview

I am new to ios development and trying to use code filters...
imgAnimation=[[UIImageView alloc]initWithFrame:frame];
imgAnimation.animationImages=_arrimg;
//animationImages=animationImages;
imgAnimation.contentMode=UIViewContentModeScaleAspectFit;
imgAnimation.animationDuration = 2.0f;
imgAnimation.animationRepeatCount = 0;
[imgAnimation startAnimating];
[self.view addSubview:imgAnimation];
My animation is working properly but how can I apply filters like sepia, grey scale I had found many tutorials but they are for single images kindly help ???
Sample Code :
+(UIImage *) applyFilterToImage: (UIImage *)inputImage
{
CIImage *beginImage = [CIImage imageWithCGImage:[inputImage CGImage]];
CIContext *context = [CIContext contextWithOptions:nil];
CIFilter *filter = [CIFilter filterWithName:#"CISepiaTone" keysAndValues: kCIInputImageKey, beginImage, #"inputIntensity", [NSNumber numberWithFloat:0.8], nil];
CIImage *outputImage = [filter outputImage];
CGImageRef cgimg = [context createCGImage:outputImage fromRect:[outputImage extent]];
UIImage *newImg = [UIImage imageWithCGImage:cgimg];
CGImageRelease(cgimg);
return newImg;
}
Basically you have to pre load all the images with the filters. Then load them to an array and set it to animationImages property.
For getting the various filters you can refer this project from github
GPU image open source framework for image effects.
Download the Source Code From Here:-
Hope it Helps to You :)

Applying CIFilter to UIImageView

In UIViewController displaying image in UIImageView. I want to display it with some special effects. Using core image.framework
UIImageView *myImage = [[UIImageView alloc]
initWithImage:[UIImage imageNamed:#"piano.png"]];
myImage.frame = CGRectMake(10, 50, 300, 360);
CIContext *context = [CIContext contextWithOptions:nil];
CIFilter *filter= [CIFilter filterWithName:#"CIVignette"];
CIImage *inputImage = [[CIImage alloc] initWithImage:[UIImage imageNamed:#"piano.png"]];
[filter setValue:inputImage forKey:#"inputImage"];
[filter setValue:[NSNumber numberWithFloat:18] forKey:#"inputIntensity"];
[filter setValue:[NSNumber numberWithFloat:0] forKey:#"inputRadius"];
[baseView addSubview:inputImage];
but looks like I'm missing something or doing something wrong.
As the other post indicates, a CIImage is not a view so it can't be added as one. CIImage is really only used for doing image processing, to display the filtered image you'll need to convert it back to a UIImage. To do this, you need to get the output CIImage from the filter (not the input image). If you have multiple filters chained, use the last filter in the chain. Then you'll need to convert the output CIImage to a CGImage, and from there to a UIImage. This code accomplishes these things:
CIImage *result = [filter valueForKey:kCIOutputImageKey]; //Get the processed image from the filter
CGImageRef cgImage = [context createCGImage:result fromRect:[result extent]; //Create a CGImage from the output CIImage
UIImage* outputImage = [UIImage imageWithCGImage:cgImage]; // Create a UIImage from the CGImage
Also remember that the UIImage will have to go into a UIImageView, as it's not a view itself!
For more information, see the Core Image programming guide: https://developer.apple.com/library/ios/#documentation/GraphicsImaging/Conceptual/CoreImaging/ci_intro/ci_intro.html
CIImage can not be added as subview because it is not a view (UIView subclass). You need a UIImageView with a UIImage attached to its 'image' property (and this UIImage you can create from the CIImage, I believe).

Stuttering when Drawing to Image in GCD Block

I have the following method which takes some CAShapeLayers and converts them into a UIImage. The UIImage is used in a cell for a UITableView (much like the photos app when you select a photo from one of your libraries). This method is called from within a GCD block:
-(UIImage*) imageAtIndex:(NSUInteger)index
{
Graphic *graphic = [[Graphic graphicWithType:index]retain];
CALayer *layer = [[CALayer alloc] init];
layer.bounds = CGRectMake(0,0, graphic.size.width, graphic.size.height);
layer.shouldRasterize = YES;
layer.anchorPoint = CGPointZero;
layer.position = CGPointMake(0, 0);
for (int i = 0; i < [graphic.shapeLayers count]; i++)
{
[layer addSublayer:[graphic.shapeLayers objectAtIndex:i]];
}
CGFloat largestDimension = MAX(graphic.size.width, graphic.size.height);
CGFloat maxDimension = self.thumbnailDimension;
CGFloat multiplicationFactor = maxDimension / largestDimension;
CGSize graphicThumbnailSize = CGSizeMake(multiplicationFactor * graphic.size.width, multiplicationFactor * graphic.size.height);
layer.sublayerTransform = CATransform3DScale(layer.sublayerTransform, graphicThumbnailSize.width / graphic.size.width, graphicThumbnailSize.height / graphic.size.height, 1);
layer.bounds = CGRectMake(0,0, graphicThumbnailSize.width, graphicThumbnailSize.height);
UIGraphicsBeginImageContextWithOptions(layer.bounds.size, NO, 0);
[layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = [UIGraphicsGetImageFromCurrentImageContext() retain];
UIGraphicsEndImageContext();
[layer release];
[graphic release];
return [image autorelease];
}
For whatever reason, when I'm scrolling the UITableView and loading the images in, it is stuttering a little bit. I know the GCD code is fine because it's worked previously so it appears something in this code is causing the stuttering. Does anyone know what that could be? Is CAAnimation not thread safe? Or does anyone know a better way to take a bunch of CAShapeLayers and convert them into a UIImage?
In the end I believe:
[layer renderInContext:UIGraphicsGetCurrentContext()];
Cannot be done on a separate thread, so I had to do the following:
UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0);
CGContextRef context = UIGraphicsGetCurrentContext();
//draw the mutable paths of the CAShapeLayers to the context
UIImage *image = [UIGraphicsGetImageFromCurrentImageContext() retain];
UIGraphicsEndImageContext();
There is a great example of this (where I learned to do it) in the WWDC2012 video "Building Concurrent User Interfaces on iOS"

How to take a screenshot from an video playing through MPMediaPlayerController in iPhone?

Can anybody help me in this? I want to get an screenshot from an video playing through MPMediaPlayerController. What i have tried so far is:-
-(void)viewDidLoad
{
NSURL *tempFilePathURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"LMFao" ofType:#"mp4"]];
player = [[MPMoviePlayerController alloc] initWithContentURL:tempFilePathURL];
[player setControlStyle:MPMovieControlStyleFullscreen];
//Place it in subview, else it won’t work
player.view.frame = CGRectMake(0, 0, 320, 400);
[self.view addSubview:player.view];
}
-(IBAction)screenshot
{
CGRect rect = [player.view bounds];
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
[player.view.layer renderInContext:context];
image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
imgView = [[UIImageView alloc] initWithFrame:CGRectMake(150, 150, 100, 100)];
[imgView setImage:image];
imgView.layer.borderWidth = 2.0;
[self.view addSubview:imgView];
}
And what i ve got now is this:-
what is happening now is my player's button are getting captured in ScreenShot but my video's image is not been getting.I'm using this context method to capture my image because
i have an overlay on my video,using thumbnail method i cant capture video with overlay but i want to get video's image with overlay.
EDIT:
what i want is getting screenshot of both this video and drawing overlay as shown in this image
But what i m getting is by one method i got only video not overlay in my screenshot that method is thumbnail method,i was doing thumbnailing in that which is given by MPMoviePlayerController and by second method i m getting only overlay not an video in ma screenshot,that method is context method.i'm getting context of rect.Now i thought solution for this may be is k i combine both these images.So help me out by giving suggestion is merging images will work for me or not???
Please help.Thanks :)
You just have to call a single method on your mpmovieplayer object:
- (UIImage *)thumbnailImageAtTime:(NSTimeInterval)playbackTime timeOption:(MPMovieTimeOption)option
this method will return a UIImage object. what you have to do is just:
UIImage *thumbnail = [player thumbnailImageAtTime:1.0 timeOption:MPMovieTimeOptionNearestKeyFrame];
for more details look at MPMoviePlayerController
Hope this helps
EDIT: In your method you can first hide player's control and than capture Image after that show controls again. you can achive this using controlStyle property of MPMoviePlayerController.
Not sure this is what you are looking for but it is what I understood. If you are looking for different let me know.
U can merge two image from this way.Please have an look from the below code..
- (UIImage*) maskImage:(UIImage *)image withMask:(UIImage *)maskImage {
MaskView=[[UIView alloc] init];
UIImageView *image1=[[UIImageView alloc]init];
UIImageView *image2=[[UIImageView alloc]init];
MaskView.frame=CGRectMake(0, 0,500,500);
image1.frame=CGRectMake(0,0,160, 160);
image2.frame=CGRectMake(60,54,40,40);
image1.image=image;
image2.image=maskImage;
[MaskView addSubview:image1];
[MaskView addSubview:image2];
UIGraphicsBeginImageContext(CGSizeMake(160,160));
[MaskView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *finishedPic = UIGraphicsGetImageFromCurrentImageContext();
return finishedPic;
}
This may help
- (UIImage *)thumbnailImageAtTime:(NSTimeInterval)playbackTime timeOption:(MPMovieTimeOption)option
Get the thumbnailImage at the given time and scale that image.