

IOS Image Tricks - gurgeous
http://www.dwellable.com/blog/Tech-iOS-Image-Tricks

======
bradleyland
I'm being a bit picky here, but IOS is an operating system that runs on Cisco
networking equipment. "Images" is how one refers to the software that is
loaded on the switch/router/etc. For example, I can buy an "layer 3 enhanced
image" for a Cisco switches that will give me limited routing capabilities.

For that reason, one should be careful about the case of the letters when
referring to IOS and iOS, as they can lead to confusion if not used
appropriately.

~~~
taylorfausak
The author correctly capitalizes "iOS" in the article. Hacker News
automatically capitalizes the first letter of submission titles, though.

~~~
sjwright
The rule would be improved if it only capitalized the first letter when the
first word does not contain any capital letters.

~~~
geon
Or it should stop trying to second guess users.

------
oofabz
Using 16-bit images won't save any memory, and may actually use more memory.
The iOS graphics pipeline requires 32-bit images for rendering, so all other
types of images are converted to a 32-bit texture.

If you are trying to optimize memory consumption, you need to measure memory
consumption! You can't just change some code and assume your memory
consumption has gone down.

~~~
gurgeous
I certainly was measuring memory consumption. Many of these images are
offscreen in paging scroll views (per the blog post), or stuck in caches.

------
kstenerud
You could compress those images down to 4bpp or even 2bpp by encoding to
PVRTC. Since they're photorealistic images you'll retain image quality despite
being 8x or even 16x smaller, and the graphics chip supports the format
natively so you don't need to decompress it.

I use it in games whenever a photorealistic image is required. Some more info:

[http://www.uchidacoonga.com/2011/07/pvrtc-textures-and-
cocos...](http://www.uchidacoonga.com/2011/07/pvrtc-textures-and-cocos2d/)

[https://developer.apple.com/library/ios/#qa/qa2008/qa1611.ht...](https://developer.apple.com/library/ios/#qa/qa2008/qa1611.html)

~~~
gurgeous
I'm not familiar with PVRTC, unfortunately. Here's one of the better articles
I could find:

[http://www.kihongames.com/blog/labs/2011/04/labs-pvrtc-
power...](http://www.kihongames.com/blog/labs/2011/04/labs-pvrtc-powervr-
texture-compression/)

Some highlights from the article:

\- "Avoid using PVRTC when you have static images that are the focus of your
content" \- "images are 2-4x larger, but memory use is less" \- "amazing
memory improvement, but no real change in performance" \- "textures must be
power of two"

It probably doesn't fit my use case, but it's fascinating.

~~~
kstenerud
Right now you are using 32bpp images, and then falling back to 16bpp for
slower devices. Because PNG uses zip-style compression, pictures of houses
won't compress that well, so your size on disk and size in memory will be
similar.

PVRTC allows you to save at 4bpp or 2bpp, so you'll get sizes 8x or even 16x
SMALLER than a full color image, both on disk and while loaded into memory
(loading images are a major source of lag on iPhone, so a smaller on-disk
footprint is always welcome). You can even zip compress it for further on-disk
savings, though YMMV.

The quality degradation is similar to what you'll get in JPEG, in that there
will be some artifacting depending on the quality of the encoder and the
source image (hard edges don't compress well, nor does text, but
photorealistic images retain a lot of quality).

The power-of-2 restriction is the only real pain point of PVRTC. But if you're
making sprite sheets, that's probably not going to be a big issue for you
anyway. Once it's in memory it's just a texture like any other, and you can
use it sprite sheet style like you're already doing, chopping up the contents
any way you choose.

I suggest you try cropping one of your house images to a square sized power-
of-2 as a quick test and convert it to PVRTC so you can see for yourself what
the quality is like. It may yet be usable for your purposes, and the potential
payoff is huge.

~~~
kstenerud
Actually here you go:

I took the first image from here: [http://www.dwellable.com/h/8559/Cape-
Cod/Upper-Cape-Cod/Falm...](http://www.dwellable.com/h/8559/Cape-Cod/Upper-
Cape-Cod/Falmouth/East-Falmouth/155-Teaticket-Path)

Cropped it to 1024x1024 (you'd of course make a sprite sheet instead). Then
shrank it to 512x512 just for demonstration purposes.

I then converted it using texturetool, also back-converting it to make a png
with exactly the pixels produced in the PVRTC image:

    
    
        $ texturetool -e PVRTC --channel-weighting-perceptual --bits-per-pixel-2 -p converted2.png -o converted2.pvrtc original.png
        $ texturetool -e PVRTC --channel-weighting-perceptual --bits-per-pixel-4 -p converted4.png -o converted4.pvrtc original.png
    

The PVRTC images are significantly smaller, both on disk and in memory:

    
    
        $ ls -l original.png 
        -rw-r--r--  1 kstenerud  staff  571225 Jul 27 15:10 original.png
        $ ls -l converted*.pvrtc
        -rw-r--r--  1 kstenerud  staff   65536 Jul 27 15:12 converted2.pvrtc
        -rw-r--r--  1 kstenerud  staff  131072 Jul 27 15:12 converted4.pvrtc
    
    

Here's the quality:

Original image: <http://i.imgur.com/flT7c.png>

4bpp image (converted back to png): <http://i.imgur.com/Itz4F.png>

2bpp image (converted back to png): <http://i.imgur.com/tzqlw.png>

~~~
gurgeous
Ooh, cool! We're using JPGs, though. At quality 75:

    
    
       67K  flT7c.jpg
      558K  flT7c.png
    

Once those JPGs make it across the network and arrive on the device, we're
stuck with plain old CGImages, right?

~~~
kstenerud
Yeah. When you load a JPEG image, it gets decoded to a 32bpp image in memory
on the device. PVRTC images, on the other hand, stay the same size (2bpp or
4bpp) when loaded into memory. Plus they don't need to be decoded.

So this 512x512 image would take 64k of RAM using 2bpp pvrtc, 128k using 4bpp
pvrtc, and a whopping 1MB using JPEG or PNG.

------
0x0
Very interesting read, especially the image sprite part and how it improved
cpu usage.

BTW:

    
    
      gIsLowCPU = [gModel matches:[NSRegularExpression re:@"^(iPhone1|iPod[12])"]];
    

this is gonna be fun when the iPhone 10 is released!

~~~
gurgeous
Ha! I really hope none of these techniques are in vogue for iPhone 10. Or iPod
10, for that matter.

~~~
projct
That's what people said about 2 digit years :P

------
kalleboo
I remember back in the day of 60 MHz PowerPC with 16 MB RAM, that I used
software that would decode JPEG files in blocks, so you could look at high-res
photos without holding the whole uncompressed image in RAM. In fact, I have an
app like that for my Android phone for viewing a very high res bike route map
I rendered out of a PDF.

Are there any libraries like that floating around that would work in this
situation?

------
campnic
So, it sounds like 'spriting' in this context is a way of sending a stitched
together larger image and then showing a portion of it in each uiimage. I work
on Android, and I'm interested in the technique but just was looking for some
validation before I go off doing research.

------
nutjob123
Here's a tip when you start working on android. There is a method in the
bitmap factory class that can handle image scaling for you on device.

