why setting backgroundImage on uiviews slowed down my iOS app? - ios

I'm making an iOS app which includes 2 UITableViewController,
Pressing on the first tableview cell pushes the second tableview, the transition was pretty fast (going back/forth between the two tableviews) until i used this code on each tableviews viewWillAppear method:
UIImageView *imageV = [[UIImageView alloc] init];
UIImage *image = [[UIImage imageNamed:#"un.jpeg"] applyBlurWithRadius:50
tintColor:nil
saturationDeltaFactor:1
maskImage:nil];
imageV.image = image;
self.tableView.backgroundView = imageV;
Now the transition takes about 2-3 seconds to be done how can i improve transition speed ?
Edit 1: using UIImage+ImageEffects.h from Apple to blur the image
Edit 2 (solution):
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
UIImageView *imageV = [[UIImageView alloc] init];
UIImage *image = [[UIImage imageNamed:#"un.jpeg"] applyBlurWithRadius:50
tintColor:nil
saturationDeltaFactor:1
maskImage:nil];
imageV.image = image;
self.tableView.backgroundView = imageV;
});

I would suggest applying the blur on a background thread, so it doesn't slow your interface down. And you might want to look into GPUImage for maximum speed.
Alternatively, in iOS 8, just use the UIBlurEffect that is built in. But of course that is a much less flexible blur.

What slows your application the most is certainly not the image, but rather the blur that you apply to it.

Is not setting the image per se, is applying the blur on it.
The bigger is the image the longer it takes. I don't know which kind of functionalities you are using to make the image blurred, but check if you can use the accelerate framework or Core Image on GPU to perform the operation faster.

Related

Zoom and Pan on a UIPageViewController

I have a simple application which consists of a UITableViewController with cells of Languages. When the user clicks a specific language, it brings up a UIPageViewController to show horizontally, 6 images in a pageView. That part is working really well and the images are loading.
I have implemented this, using this tutorial: http://code.tutsplus.com/tutorials/using-scrollstyle-with-uipageviewcontroller--mobile-13551.
I would like to achieve a zoom and pan functionality within this as well now.
I have zoom working with the following code.
CGFloat scale = pinchRecognizer.scale;
self.pageViewController.view.transform = CGAffineTransformScale(self.pageViewController.view.transform, scale, scale);
pinchRecognizer.scale = 1.0;
The problem is that the zoom is always in the centre of the image with no way to pan around the image like you can in a normal Photo on an iOS device.
I have found lots of good tutorials on how to achieve this, like http://iosdeveloperzone.com/2012/07/07/tutorial-all-about-images-part-2-panning-zooming-with-uiscrollview/ as an example. However, my confusion stems from the very first part.
I am loading my UIPageViewController using a NSArray:
self.modelArray = [NSMutableArray arrayWithObjects:[[ImageModel alloc] initWithImageName:#"3facts-english-page1.jpg"], [[ImageModel alloc] initWithImageName:#"3facts-english-page2.jpg"], [[ImageModel alloc] initWithImageName:#"3facts-english-page3.jpg"], nil];
How to I extract each image into a UIImageView?
I can see that fundamentally, I need to have most of this code to enable the Pan:
UIImage* image = [UIImage imageNamed:#"KinkakuJi"];
self.imageView.image = image;
[self.imageView sizeToFit];
self.scrollView.contentSize = image.size;
In my case however, I'm not loading a single UIImage but rather a NSArray. How do I extract the UIImage from the NSArray to make this pan happen?
Any thoughts on this would really be appreciated.

Morphing with CoreAnimation

I am creating an Navigation Button. When user presses it, the image of the button should change, reflecting it's state (e.g. menu opened / closed). I decided to do a morphing-liek animation for this. Is it possible to implement with CoreAnimation? What animation type do I need to use?
I attached the picture to clearly illustrate what I want. Also, you might see these animations in "Pimp My Ride" show.
You can use animationImages property of UIImageView for this, like this:
myImageView = [[UIImageView alloc] initWithFrame:myImageViewbounds];
//Add images which will be used for the animation using an array. These should exist in your project and bundle already.
myImageView.animationImages = #[[UIImage imageNamed:#"1.png"], [UIImage imageNamed:#"2.png"],[UIImage imageNamed:#"3.png"], [UIImage imageNamed:#"4.png"],[UIImage imageNamed:#"5.png"]];
//Set the duration of the entire animation
myImageView.animationDuration = 0.5;
//Set the repeat count. If you don't set that value, by default will be a loop (infinite)
myImageView.animationRepeatCount = 1;
//Start the animation
[myImageView startAnimating];
To ensure smooth morphing like transition you may check out GPUImage which has many great blur filters. Ideally you should be able to wrap a blur animation between two image animations to achieve what you want.

Memory leaks when loading images to scroller

I have a scrollView in which i load images into from the net .I sometimes get memory warnings, which i assume are because i am doing something wrong with the images loader.
I am trying to fix little things, and i just wanted to show the code here, and hear maybe there are more things i can fix to get rid of this warnings.
So every time the scroller (iPad) has only 4/5 images that are : current page-3->current page+3.
This is how i load the images(every image has also a blur effect with Apple's classes) :
(should i allocated imageView every time? can i improve something here? )
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^
{
NSData *imdata2 = [NSData dataWithContentsOfURL:url];
dispatch_async(dispatch_get_main_queue(), ^
{
UIImage *theImage=[UIImage imageWithData:imdata2 scale:1];
UIImage *LightImage = [theImage applyLightEffect];
UIImage *scaledImage =[resizer resizeImageToWidth:[Globals sharedGlobals].imagesWidth WithImage:theImage];
CGRect viewSizeBack=CGRectMake(scroller.bounds.size.width*toPage , 0, scroller.bounds.size.width, scroller.bounds.size.height);
int x=[Globals sharedGlobals].pageMargins;
int y=([UIScreen mainScreen].bounds.size.height-scaledImage.size.height)/2;
CGRect viewSizeFront=CGRectMake(x , y, scaledImage.size.width,scaledImage.size.height);
UIImageView *backImageView=[[UIImageView alloc] initWithFrame:viewSizeBack];
UIImageView *frontImageView=[[UIImageView alloc] initWithFrame:viewSizeFront];
backImageView.layer.cornerRadius = 0.0;
backImageView.layer.masksToBounds = YES;
backImageView.image=LightImage;
frontImageView.layer.cornerRadius = 0.0;
frontImageView.layer.masksToBounds = YES;
frontImageView.image=scaledImage;
frontImageView.layer.borderWidth=1.0;
frontImageView.layer.borderColor=[UIColor colorWithRed:255.0 green:255.0 blue:255.0 alpha:1.0].CGColor;
[backImageView addSubview:frontImageView];
backImageView.tag=toPage;
frontImageView.tag=toPage;
[scroller addSubview:backImageView];
});
});
You should only ever have 3 images loaded at a maximum - the previous page (if it exists), the current page and the next page.
Any other images you have loaded above this is wasteful because you can't see them and they're just taking up memory for no good reason. If the images aren't too big then you can maintain them in memory and purge them when you get a warning, but for large images this will still generally cause you issues.
If you don't use ARC then add this:
[backImageView autorelease];
[frontImageView autorelease];

iOS app - Apply background image object to UIView

Can anyone help me understand how I apply a background image object to a UIView please?
I have created a background image which is a blurred version of a background and I would like to apply it to be the background of a uiView in the foreground which would ideally mask the background image.
I have the following code so far -
_blurImage = [source stackBlur:50];
[_HPBlurView.backgroundColor = [UIColor colorWithPatternImage:[_blurImage]]];
I would like to apply the image object(_blurImage) to be the background image of _hpBlurView but i'm struggling to get it working!
At first glance, you are using too many brackets. Here is a working version of your code :
_burImage = [source stackBlur:50];
_HPBlurImage.backgroundColor = [UIColor colorWithPatternImage:_blurImage];
I can't see what stackBlur:50 returns. So start from the beginning. colorWithPatternImag takes UIImage as a parameter. So Start by adding a picture, any picture, to your application. Lets imagine that the image is called image.png. This is one way to do it:
UIImage *image = [UIImage imageNamed:#"image.png"];
_HPBlurView.backgroundColor = [UIColor colorWithPatternImage:image];
This should help to get you going.
Create an image and add to the background.:
UIImage *image = [UIImage imageNamed:#"youimage"];
self.view.backgroundColor = [UIColor colorWithPatternImage:image];
It's that.
To make sure everything resizes properly, no matter rotation, device size and iOS version, I just set an UIImageView
//Create UIImageView
UIImageView *backgroundImageView = [[UIImageView alloc] initWithFrame:self.view.frame]; //or in your case you should use your _blurView
backgroundImageView.image = [UIImage imageNamed:#"image.png"];
//set it as a subview
[self.view addSubview:backgoundImageView]; //in your case, again, use _blurView
//just in case
[self.view sendSubviewToBack:backgroundImageView];

UITableView Background Scroll but NOT Repeat

I am trying to set a UITableView background using the following method:
[self.tableView setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:#"backgroundImage.png"]]];
This works great for making the background scroll with the table. However, my background image fades into a solid color, so instead of the background repeating, I'd love for it to just scroll up and just fit to the screen height. Then I can set self.view's backgroundColor to be the solid color and it will look great.
Other options seem to be blitting a small image at the bottom, but this seems complicated and I didn't quite understand how to draw the background and blit using CGContext.
Can someone tell me how to do this?
I'm not sure whether this will work but you should try creating a resizeable UIImage for the background:
If you want the last line of pixels to repeat you would call the
- (UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets resizingMode:(UIImageResizingMode)resizingMode
on your image ( [UIImage imageNamed:#"backgroundImage.png"] )
with edgeinsets: UIEdgeInsetsMake(backgroundImage.size.height-1,0,0,0)
and resizingMode: UIImageResizingModeStretch
the complete call would look like
UIImage* backgroundImage = [UIImage imageNamed:#"backgroundImage.png"];
UIImage* newBackgroundImage = [backgroundImage resizableImageWithCapInsets:UIEdgeInsetsMake(backgroundImage.size.height-1,0,0,0) resizingMode:UIImageResizingModeStretch];
And now you could try to use this image for the pattern creation:
[self.tableView setBackgroundColor:[UIColor colorWithPatternImage:newBackgroundImage]];
This worked for me:
UIImageView* bgImageView = [[UIImageView alloc] initWithFrame:self.tableView.frame];
bgImageView.image = [UIImage imageNamed:#"bg"];
bgImageView.contentMode = UIViewContentModeTop;
[self.tableView addSubview:bgImageView];
[self.tableView sendSubviewToBack:bgImageView];
In my case it worked fine. I didn't test it with a lot of cells which are reused. But it should work :D

Resources