PDA

View Full Version : Consequences of using higher-than-necessary resolution images?




MythicFrost
Feb 21, 2012, 06:59 AM
Hey guys,

I'm curious what the consequences of using higher resolution images than necessary. I'm working on a game right now, it's got a UIImageView in it and will require a 32x32 image for 480x320, 64x64 for 960x640, 64x64 1024x768 and 128x128 for 2048x1536.

It'd be easier for me to simply have my images at 128x128, instead of having "image iPhone" (32x32) and "image iPhone@2x" (64x64) and image iPad@2x (128x128).

Is that a bad idea? I'm thinking it is, but I thought I'd ask to make sure. Will it leave a really large memory footprint? Will it be more process intensive? (i.e will using [image drawInRect:] from 512x512 down to 32x32/64x64/128x128 be very process intensive? Rather than doing it with a 32x32 image?



robbieduncan
Feb 21, 2012, 07:02 AM
Your app will be larger. Depending on the number of images this might mean your app is over the magic 20Mb when it does not need to be.

Your images will take longer to load into memory

You will need more memory (maybe: you could load them then downsample to the size you need and throw away the full sized image)

If you don't downsample drawing will take longer as this will have to be done as you draw.

MythicFrost
Feb 21, 2012, 07:15 AM
Your app will be larger. Depending on the number of images this might mean your app is over the magic 20Mb when it does not need to be.

Your images will take longer to load into memory

You will need more memory (maybe: you could load them then downsample to the size you need and throw away the full sized image)

If you don't downsample drawing will take longer as this will have to be done as you draw.
Mmm, I see. Thanks for pointing that out, I'd forgotten about the 20MB limit.

What about this though:

This image is about 70KB at 128x128 which is the maximum size I'll need. I could simply use that and downscale, or I could also have a 32x32 and 64x64 copy which would probably add up to an additional 50KB. So in this instance it would save space to use only one.

I'm only targeting iOS 5 devices, so they'll have at least 256MBs of memory total. (With a lot less, of course, for my app specifically.)

I may have about thirty of these images at first, which would equate to only about 2.1MBs or 3MBs depending on whether I used one 128x128 image, or that and the 64x64 and 32x32 image.

I understand very little about how much these devices can handle. I take it you're an experienced programmer, what's your opinion? Do you think it's better to have three separate images and draw them at their natural size, despite taking up a little more space overall, or just use the largest required (128x128) and then downscale it. Is it process intensive to downscale these images? Is it more efficient to have the three images?

Keep in mind, I'm actually piecing around two hundred smaller images into one larger image, and that number could go up as high as 500 or so at some point.

I appreciate the input,
Thanks!

robbieduncan
Feb 21, 2012, 07:19 AM
I'd probably just ship the app with the large image and build some sort of internal caching thing that you could request the image at a size from. The cache would resize the image and store it for future requests. Once an image had not been requested for a while and a new image or size was needed it'd be removed from the cache.

How many images to store in the cache? You will probably have to experiment to find out. There will be a balance between performance (cache everything forever) and RAM usage.

MythicFrost
Feb 21, 2012, 07:28 AM
I'd probably just ship the app with the large image and build some sort of internal caching thing that you could request the image at a size from. The cache would resize the image and store it for future requests. Once an image had not been requested for a while and a new image or size was needed it'd be removed from the cache.

How many images to store in the cache? You will probably have to experiment to find out. There will be a balance between performance (cache everything forever) and RAM usage.
Mmm, I see. Thanks.

I'm not familiar at all with caches, but what if in my method where I need to execute these operations, I simply check what device is being used and what the scalingFactor is, and then create an image at the appropriate size in that method, and then call [image copy] in the loop.

That sounds good to me. Alternatively, I could in viewDidLoad do the same check and save the appropriately sized image for the device to storage, and then retrieve the image from that file.

What do you think? Will the performance difference between the two be negligible? Thanks.

robbieduncan
Feb 21, 2012, 07:29 AM
Mmm, I see. Thanks.

I'm not familiar at all with caches, but what if in my method where I need to execute these operations, I simply check what device is being used and what the scalingFactor is, and then create an image at the appropriate size in that method, and then call [image copy] in the loop.

That sounds good to me. Alternatively, I could in viewDidLoad do the same check and save the appropriately sized image for the device to storage, and then retrieve the image from that file.

What do you think? Will the performance difference between the two be negligible? Thanks.

It depends how many times you are going to re-size the image. If you end up doing that over and over for the same image it's clearly wasteful. Even if your app performs OK it's going to consume CPU cycles that could be avoided and use more power than it has to.

MythicFrost
Feb 21, 2012, 07:38 AM
It depends how many times you are going to re-size the image. If you end up doing that over and over for the same image it's clearly wasteful. Even if your app performs OK it's going to consume CPU cycles that could be avoided and use more power than it has to.
Mmm, I see. I'm actually thinking it won't be a problem now, after my method runs and pieces these images together, it'll save the new image to storage and then reload it instead of running the same method over and over again. Which means the method won't be running for those tasks at all, only a few others which I think will be just fine.

So if it's really only CPU cycles that are being wasted, I think it'll be fine for just that first run. Thanks again! You've been a big help.

robbieduncan
Feb 21, 2012, 07:42 AM
Mmm, I see. I'm actually thinking it won't be a problem now, after my method runs and pieces these images together, it'll save the new image to storage and then reload it instead of running the same method over and over again. Which means the method won't be running for those tasks at all, only a few others which I think will be just fine.

So if it's really only CPU cycles that are being wasted, I think it'll be fine for just that first run. Thanks again! You've been a big help.

Yeah, in that case the cost in negligible. I was more thinking of asking for the image to be resized over and over to draw to the screen/animate.

MythicFrost
Feb 21, 2012, 07:44 AM
Yeah, in that case the cost in negligible. I was more thinking of asking for the image to be resized over and over to draw to the screen/animate.
Ah right, no it only gets called once when the user goes to a certain part of the game and then that's it. It'll get discarded when they leave, and it'll be called again if they went back to it.

However, saving the output after it's created will remove any unnecessary processing after the first run.

dejo
Feb 21, 2012, 08:37 AM
If you're really worried about that 20MB limit, you should maybe include all the images and see how close you are getting with your app bundle. Otherwise, resizing the images on first run seems, to me, to be a bit of a waste. You are putting the burden on the client's device to achieve an effect that is the same as if you just bundled the various versions of the images with the app. Plus, you'll have better control of the scaling quality if you do that before, desktop-side, so to speak.

EDIT:

P.S. If you decide to resize images in the app, please be sure to read the following article:
Resize a UIImage the right way (http://vocaro.com/trevor/blog/2009/10/12/resize-a-uiimage-the-right-way/)

MythicFrost
Feb 21, 2012, 08:47 AM
If you're really worried about that 20MB limit, you should maybe include all the images and see how close you are getting with your app bundle. Otherwise, resizing the images on first run seems, to me, to be a bit of a waste. You are putting the burden on the client's device to achieve an effect that is the same as if you just bundled the various versions of the images with the app.
That's true, but is it worth the extra file size just to save that little work that the processor will have to do? I'm not so sure.
Plus, you'll have better control of the scaling quality if you do that before, desktop-side, so to speak.
You've piqued my curiosity on this one. Are you saying scaling quality is less when done via code, rather than say using Photoshop? I believe I've noticed that. That's reason enough for me to use the three different image sizes.

dejo
Feb 21, 2012, 08:48 AM
You've piqued my curiosity on this one. Are you saying scaling quality is less when done via code, rather than say using Photoshop? I believe I've noticed that. That's reason enough for me to use the three different image sizes.

See the addendum to my previous post. Depending on how you scale your images in-app, you can get ugly results.

MythicFrost
Feb 21, 2012, 08:55 AM
See the addendum to my previous post. Depending on how you scale your images in-app, you can get ugly results.
I see. Right now, this is what I'm doing:


CGSize imageSize = CGSizeMake(width, height);
UIGraphicsBeginImageContext(imageSize);
//in actual code, loop starts here
[image drawInRect:CGRectMake(...)];
//and it ends here
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

I've not found it to cause any errors however, I do notice that if the size of the image I'm drawing to the graphics context is scaled down from 512x512 to 4x4 that there's a significant reduction in quality. (Each 4x4 image is a component of a larger image.)

Thanks for the link, it's late right now so I only skimmed over it but I've bookmarked it for future reference.

dejo
Feb 21, 2012, 08:57 AM
Thanks for the link, it's late right now so I only skimmed over it but I've bookmarked it for future reference.

Your welcome. It's kinda old so I'm not sure if some of the problems it discusses have new, better solutions. But it's there if you want it.

seepel
Feb 21, 2012, 08:53 PM
I suspect that when writing a game you will hit memory issues long before you hit the 20MB size limit. For example 128x128 will balloon up to 500 kB of memory In RGBA8888. For this reason it seems practical to scale the images before hand so you don't use up memory you don't need.

MythicFrost
Feb 21, 2012, 08:56 PM
I suspect that when writing a game you will hit memory issues long before you hit the 20MB size limit. For example 128x128 will balloon up to 500 kB of memory In RGBA8888. For this reason it seems practical to scale the images before hand so you don't use up memory you don't need.
Thanks for your reply,

I'm planning on providing the three different image sizes: 32x32, 64x64, and 128x128. I think that'll be the best way to keep memory usage at an appropriate level.

ahan.tm
Feb 22, 2012, 05:24 PM
Hi,

In my app, I used around 40 images and they were all around 500 x 500. My app weighed in at 21 mb. So, After some changes to the size in preview, I reduced the size to 300 x 300. What's special about 300 x 300, is that my images views are 75 x 75. My images now seem to render faster and look sharper because 75 is a factor of 300. My app size was also reduced to 5.9 MB.

Great Question!!:)

dejo
Feb 22, 2012, 05:27 PM
So, After some changes to the size in preview, I reduced the size to 300 x 300. What's special about 300 x 300, is that my images views are 75 x 75.

Why not just have the images at 75x75 then?

firewood
Feb 22, 2012, 05:47 PM
If the app looks good and is plenty small enough and fast enough when using larger than necessary images that need to be rescaled down, then there would be very little consequence.

But Photoshop or your graphic editor may do a better job of rescaling images, or give you the option to select the exact scaling method or do sharpening or fine tuning of the pixel result, to optimize each image's look, if you scale all the images yourself beforehand, versus just letting the iPhone GPU do whatever, which might come out soft or blurry.

Loading larger images than necessary into memory and the GPU will take more time and slow down your app in responsiveness and/or frame rate, as well as getting your app closer to or going over the various app size limits.