i have two image:
-map.png (1985 x 1162)(about 200kb)
-map#2x.png (3969 x 2324) (about 650kb)
now if load this image in this way:
imageMap = [UIImage imageNamed:#"map.png"];
viewMap = [[UIView alloc] initWithFrame:CGRectMake(0, 0, imageMap.size.width, imageMap.size.height)];
viewMap.center = CGPointMake(self.view.frame.size.height/2, self.view.frame.size.width/2);
viewMap.backgroundColor = [UIColor colorWithPatternImage:imageMap];
[self.view addSubview:viewMap];
the image does not load completely in iPhone4 (but works well in iPhone5) and I do not know why.
But if i put in bundle only
map#2x.png
and rename it in
map.png
using the same code, the image is loaded without problems.
what happens? thanks everybody
EDIT:
I think the problem comes from setting the background of a UIView because if I modify the code like this:
imageMap = [UIImage imageNamed:#"map.png"];
viewMap = [[UIView alloc] initWithFrame:CGRectMake(0, 0, imageMap.size.width, imageMap.size.height)];
viewMap.center = CGPointMake(self.view.frame.size.height/2, self.view.frame.size.width/2);
// viewMap.backgroundColor = [UIColor colorWithPatternImage:imageMap];
[self.view addSubview:viewMap];
UIImageView *imageView = [[UIImageView alloc] initWithImage:imageMap];
[viewMap addSubview:imageView];
you can see the image correctly.
Your images are probably too big. You say you have
-map.png (1985 x 1162) (about 200kb)
-map#2x.png (3969 x 2324) (about 650kb)
The size of an image file in bytes, however, is hardly representative of its size in memory. To the best of my knowledge, loading an image of AxB pixels results in somewhere in the neighborhood of A * B * 4 bytes memory usage. In your case, that's about 23MB for the smaller image and 90MB for the bigger one.
Considering that the iPhone 4 has a whopping 512MB of RAM and the iPhone 5 1GB and that apps are limited in how much of that RAM they are entitled to, you might want to rethink how big you want to make these images.
If you are doing something like a map, tiling would probably work. See CATiledLayer.
Related
I have been battling this problem for a bit, I want to display a png on a UIButton, but for some reason the image ends up being very blurry both in the simulator and on a physical device. I have tried using all different sized images, all at 326 ppi (verified in xcode), but none have looked correct. I have also tried resizing the image in my app using UIGraphics but the problem persists. Here is the code which sets up the button:
//MIRROR BUTTON
_mirrorButton = [UIButton buttonWithType:UIButtonTypeCustom];
//_mirrorButton.frame = CGRectMake(buttonWidth, 0.0f, buttonWidth, buttonHeight);
_mirrorButton.frame = CGRectMake(64, 0, 64, 50);
UIImage *mirrorImage;
_mirrorButton.backgroundColor = [MessageView getUserColor];
mirrorImage = [UIImage imageNamed:#"mirror.png"];
[_mirrorButton setImage:mirrorImage forState:UIControlStateNormal];
[_mirrorButton addTarget:self action:#selector(mirrorPressed) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:_mirrorButton];
Both the UIButton and the image are supposed to have a height of 50 pixels. My UIButton's frame is integral, and the image even has an even pixel width and height (someone said this would help with the centering). Any incite would be much appreciated. Thanks.
From what im reading I presume you might be confusing 50 pixels with 50 points.
The frames in general are measured in points and not in pixels, you can see the difference HERE
So basically, if you use a 50 points high frame, in devices with retina screen you will need an image with 100px high, and then it shouldn't look blurry anymore
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];
This how I add an image:
UIImageView *imageHolder = [[UIImageView alloc] initWithFrame:
CGRectMake((self.view.frame.size.width/2) - (290/2),(self.view.frame.size.height) - (140 * 1.8), 290, 140)];
UIImage *image = [UIImage imageNamed:#"no-pins.png"];
imageHolder.image = image;
imageHolder.contentMode = UIViewContentModeScaleAspectFit;
// optional:
// [imageHolder sizeToFit];
[self.view addSubview:imageHolder];
The size of the image (retina version) is exactly the same size as in CGRectMake above. However the image is a little blurred. I only can reduce the blur when I edit the image and give it a higher resolution in photoshop.
But images that I add through storyboard are all fine in quality. Any ideas what might be wrong?
For retina graphics, the image size should be twice the size of the frame of the image view. This allows the image to use a scale of 2 to take advantage of the retina screen capability. So, you should have one image of size 290x140 (if you are supporting non-retina devices) and one image of size 580x280 (this is the #2x image).
The frame of the view is the description of the position and size of the view within the view hierarchy (in terms of the superview coordinate system). If you have fractional values in the frame size or position you can get 'blurring' effects.
I have a high resolution image and I want to use it as a background for a view. But when I add it either via an Interface Builder or programatically I see only its part.This doesn't help:
UIImage* _backGround = [UIImage imageNamed:#"background-clean#2x.png"];
CGRect _viewFrame = self.view.frame;
[_backGround drawInRect:_viewFrame];
UIImageView* _backGroundView = [[UIImageView alloc] initWithImage:_backGround];
[self.view addSubview:_backGroundView];
[self.view sendSubviewToBack:_backGroundView];
And this too:
_backGroundView.contentMode =UIViewContentModeScaleAspectFit;
So the question how can I scale this image in order it fits in the view in a full size in spite of its size?
P.S. Sorry for my bad English.
I agree with Ali, when creating retina-sized images you should also scale them and add their smaller version to your project. With both versions you can simply specify the full name of the image without the #2x.png or .png extension.
But, to fix your implementation you only need one extra line of code:
UIImage* _backGround = [UIImage imageNamed:#"background-clean"];
UIImageView* _backGroundView = [[UIImageView alloc] initWithImage:_backGround];
_backGroundView.frame = self.view.frame;
[self.view addSubview:_backGroundView];
[self.view sendSubviewToBack:_backGroundView];
Once you change the frame of the UIImageView, its contents (i.e. your image) will scale as well.
You must not include #2x in your code when referencing the name of the image!
You should:
Include both files Background.png and Background#2x.png in your Xcode projet resources, Background#2x.png being twice the size (in pixels) of Background.png
But always refer to this file (for example in imageNamed:) as #"Background.png" or even just #"Background": [UIImage imageNamed:#"Background"]
Then iOS will do its magic all by itself, choosing the right image between Background.png or Background#2x.png depending on if the device screen is Retina or not.
For more info see here in Apple documentation.
[self.view setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:#"background-clean"]]];
I'm trying to store UIImage datas in NSArray, actually 60 images, each with size of 300kb. Then, I'm trying to animate that images in UIImageView.
My code:
NSMutableArray *arr = [[NSMutableArray alloc] init];
for (int i=0; i<61; ++i) {
[arr addObject:[UIImage imageNamed:[NSString stringWithFormat:#"%i.png", i]]];
}
img.animationImages = arr;
img.animationDuration = 1.5;
img.contentMode = UIViewContentModeBottomLeft;
[img startAnimating];
When I test it in iPad Simulator 4.3, it works fine.
When I want to test it on my device (iPad 1), application crashes.
Note: App does not crashes if I comment this code: [img startAnimating];
1. What could be the problem? I think it is memory problem...?!
2. Can I store a loooots of UIImages in NSArray?
Your png files may have 300KB, but this is a compressing format.
To get an idea of the size of the Image itself you should multiply the width, height and bytes per pixel.
i.e. If an image has the size 1024 * 1024 and RGBA model, the images itself has an size of 4MB in the memory. And this is just one image. If you have 300 it is about 120MB.
Note: this is only a rough rule of thumb, but it gives you an idea.
So you should keep path-names in the array and load the image only if need, and thumbnails should be resized and stored on the disk as files. Do not just scale the UIImageView.
Here's a great article with code about resizing.
I solved the app crash problem with alternative way: I tried to use simple NSTimer. For each iteration I set n'th image to UIImageView:
I have UIImageView in xib file, pointing to img variable.
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:.03
target:self
selector:#selector(tiktak)
userInfo:nil repeats:YES];
int n = 0;
-(void)tiktak {
n++;
img.image = [UIImage imageNamed:
[NSString stringWithFormat:#"Blue Menu_%i.png", n]];
if(nn == 60) nn = 0;
}
Animation is amazing. I've also tested it in Activity Monitor, CPU usage is 6% and less.
I would not advise you store that many UIImages in an NSArray, its way too heavy and inefficient. From where are these images from (bundle, internet, device's gallery)?
Edit: I don't know how you want it to look, but you can build the array with the names of the UIImages, and then load the UIImage and show it. Like this:
for(i=0;i<60;i++){
NSString *nameOfPicture=[NSString stringWithFormat:#"picture_%d",i+1]
[array addObject:nameOfPicture];
}