Caching locally created images on iOS for fast reuse - ios

I have a method in my app that builds UIImages with specific colors. Since most likely the same colored image will be created multiple times, I would like to cache that UIImage, then use the cached version rather than building a new one if that specific color is needed.
This is NOT caching of remote images from the web, these are locally created images.
What is the best method to do this? From disk or just save the UIImage objects into an NSDictionary? What about NSCache?
** I would prefer not to have to use library for this. Looking for a simple solution.

It depends how many images you have and how frequently and concurrently each is used.
If you have a set of images which are all used frequently then NSDictionary is a good choice as it will keep all the images in memory. If you do get a memory warning you can always remove all of the images and then regenerate them when required.
As you're generating the images in code it seems like caching to disk won't be so useful, but that depends on how complex the images are. Again NSDictionary can be used for an in memory cache, then fail out to disk if nothing in the dict, then recreate if all else fails.
The NSCache route offers you some multi-threading benefits (if you'd use them) but is generally similar to the NSDictionary route. You have a little less control as the memory management is handled for you so it's possible that the cache could decide to destroy some of your images more frequently than you might if you manage it explicitly.
In any case you only need a handful of lines on top of your current generation code.

Related

CALAyer vs CGLayer confusion: manipulating and saving images in the background

im pulling in images from the net, and want to manipulate them a bit such as adding perspective with CATransform3D, and compositing a couple together. After im done, I would like to save the file in memory so they can be pulled up when needed (like in a tableview cell for example). I managed to extract the image from the web, and manipulate them by making a CALayer. After a bit of reading, im a bit confused as to how to properly do this since these images arent displayed until needed and I obviously would like to do my work on a worker thread so the system wont lag. What would the best procedure be?
Apple recommends that you almost never try to cache images yourself since they cache them internally and you can be guaranteed that the cache will function properly even under high memory pressure.
You can cache an image using Apple's internal cache via the setName: and imageNamed: methods`. Furthermore, you should save a local copy of the image to disk in the caches directory so you dont need to download it again if the cache gets cleared.
So, in summary, use imageNamed:, if that is nil check the disk cache directory, if that is nil download the image. Caching a CALayer will make sooo much dirty memory,

In-Memory cache and DiskCache for Images Strategies

Now, I am developing a news reader app like BBC news iOS.
see in BBC News
In my app, I must download image from server to and show it in view to make users easier to choose the news they want to read.
For more performance, I must cache image to avoid reloading image for server.
I know that there are 2 kinds of cache: In-memory cache that saving images in memory (RAM) and DiskCach that save images in Disk to load it when we need.
My question is:
What is best images cache mixed strategies for my App? (use both in-memory cache and image-cache)
My solution is:
download image --> save them in diskcache + save them in memory cache --> load image from in-memory cache on demand and show in view ---> in-memory cache over its MAX_SIZE --> free in-memory cache ---> load image from disk cache on demand and save it to memory cache --> repeat........
Is my solution is right approach?
Another question: when in-memory cache over its MAX_SIZE --> we will free its --> all images in cache will lose so image in our view will disappear.
--> How to solve this problem?
Sorry for poor English.
Thank in advance.
In one of my projects I implemented pretty much the same caching methods (Disk Cache and Memory Cache).
Maximum cache size
Each cache system had its own max size limit. The "size" of each image was computed differently in the cache systems.
For the memory cache, each image would have a size computed as
image size = image width * image height (in pixels)
So, the maximum size for the memory cache would represent a the maximum area of a pixel surface
For the disk cache, I used the actual file size for each file.
Making room
When using the cache systems, you might get to a situation where one of the caches is full and you want to insert a new item in it - you have to remove some items to make room.
What I did was assign a timestamp to each entry in the cache. Every time I access that item I updated the timestamp. When you want to make room, you just need to start removing items from the oldest to the newest based on the last access timestamp.
This is a simple algorithm for freeing up space and in some cases might actually behave poorly. It is up to you to experiment and see if you need something more advanced than this.
For example, you could improve this method by adding a priority value for each item and keep old items in the cache if their priority is high.
Again, it depends on your app's needs.
Expiration
For the disk cache, I would definitely add an expiration date for each entry. If the memory cache is destroyed when the user completely terminates the app, images in the disk cache might be stuck in there forever.
Encapsulation
Another aspect I would consider, is making the caching system as transparent as possible to the programmer. If you want to enable/disable one of the cache it would be best to have most of the code remain the same.
In my app, I built a central content delivery system and I would always request images from the internet through this object. The caching system would then check the local caches (memory / disk) and either return me the image immediately or make a request to download it.
Either way... I, as the "user" of the caching system did not care what was happening behind the curtains. All I knew is I made a request to get an image from an URL and I got it (faster or slower depending if the image was cached).

Drawbacks of embedding resources in binary as byte array?

To get around an iOS limitation with static libraries I'm embedding some binary resources (a few small images, primarily) in a static library as byte arrays.
Functionally - this works well.
My question is - what are the drawbacks of such an approach?
Specifically, if someone were to go overboard with this and embed tons of large resources in the binary - would this cause any problems?
Because I'm not 100% sure about how iOS loads binaries/etc I'm not sure if this data is all loaded into memory at the point the app is loaded, or is it kept in the DATA section and loaded from disk on demand?
It depends on how you're generating the byte array. Is it PNG/JPEg data or raw pixels? The latter will be much larger in terms of storage space and memory than if you are storing JPEG/PNG data.
And the data in the byte array is always going to be in memory, and it will probably need to be copied again to actually load the image so you're using twice the memory as if you'd loaded it from a file.
Also you are missing out on some of the built-in behaviours that iOS has for managing images. For example if you load an image using [UIImage imagedNamed:#"foo.png"] the image is cached so it's quicker to load next time, and loading multiple copies doesn't result in duplicate memory usage, and the cache is automatically cleared if the memory runs low. If you load the image from data, you're missing out on those features.
The conventional approach is to supply a resources bundle along with your library and then load assets from the resources bundle using the NSBundle methods (you can load additional bundles and then use the pathForFile:... methods just like you do with the mainBundle).

Generate thumbnail images at run-time when requested, or pre-generate thumbnail in harddisk?

I was wondering, which way of managing thumbnail images make less impact to web server performance.
This is the scenario:
1) each order can have maximum of 10 images.
2) images does not need to store after order has completed (max period is 2 weeks).
3) potentially, there may have a few thousands of active orders at anytime.
4) orders with images will frequently visit by customers.
IMO, pre-generate thumbnail in hard disk is a better solution as hard disk are cheaper even with RAID.
But what about disk I/O speed, and resource it need to load images? will it take more resource than generate thumbnails at real-time?
It would be most appreciate if you could share your opinion.
I suggest a combination of both - dynamic generation with disk caching. This prevents wasted space from unused images, yet adds absolutely no overhead for repeatedly requested images. SQL and mem caching are not good choices, both require too much RAM. IIS can serve large images from disk while only using 100k of RAM.
While creating http://imageresizing.net, I discovered 29 image resizing pitfalls, and few of them are obvious. I strongly suggest reading the list, even if it's a bit boring. You'll need an HttpModule to be able to pass cached requests off to IIS.
Although - why re-invent the wheel? The ImageResizer library is widely used and well tested.
If the orders are visited frequently by customers, it is better to create the thumbnails ones and store on disk. this way the webserver doesn't need to process the page that long. It will speed up the loading time of your webpages.
It depends on your load. If the resource is being requested multiple times then it makes sense to cache it.
Will there always have to be an image? If not, you can create it on the first request and then cache it either in memory, or more likely a database, for subsequent requests.
However, if you always need the n images to exists per order, and/or you have multiple orders being created regularly, you will be better off passing the thumbnail creation off to a worker thread or some kind of asynchronous page. That way, multiple request's can be stacked up, reducing load on the server.

What is the fastest way of loading and re-sizing an image?

I need to display thumbnails of images in a given directory. I use TFileStream to read the image file before loading the image into an image component. The bitmap is then resized to the thumbnail size, and assigned to a TImage component on a TScrollBox.
It seems to work ok, but slows down quite a lot with larger images.
Is there a faster way of loading (image) files from disk and resizing them?
Thanks, Pieter
Not really. What you can do is resize them in a background thread, and use a "place holder" image until the resizing is done. I would then save these resized images to some sort of cache file for later processing (windows does this, and calls the cache thumbs.db in the current directory).
You have several options on the thread architecture itself. A single thread that does all images, or a thread pool where a thread only knows how to process a single image. The AsyncCalls library is even another way and can keep things fairly simple.
I'll complement the answer by skamradt with an attempt to design this for being as fast as possible. For this you should
optimize I/O
use multiple threads to make use of multiple CPU cores, and to keep even a single CPU core working while you read (or write) files
The use of multiple threads implies that using VCL classes for the resizing isn't going to work, as the VCL isn't thread-safe, and all hacks around that don't scale well. efg's Computer Lab has links for image processing code.
It's important to not cause several concurrent I/O operations when using multiple threads. If you choose to write the thumbnail images back to files, then once you have started reading a file you should read it completely, and once you have started writing a file you should also write it completely. Interleaving both operations will kill your I/O, because you potentially cause a lot of seeking operations of the hard disc head.
For best results the reading (and writing) of files should also not happen in the main (GUI) thread of your application. That would suggest the following design:
Have one thread read files into TGraphic objects, and put these into a thread-safe list.
Have a thread pool wait on the list of files in original size, and have one thread process one TGraphic object, resize it into another TGraphic object, and add this to another thread-safe list.
Notify the GUI thread for each thumbnail image added to the list, so it can be displayed.
If thumbnails are to be written to file, do this in the reading thread as well (see above for an explanation).
Edit:
On re-reading your question I notice that you maybe only need to resize one image, in which case a single background thread is of course enough. I'll leave my answer in place anyway, maybe it will be of use to someone else some time. It's what I learned from one of my latest projects, where the final program could have needed a little more speed but was only using about 75% of the quad core machine at peak times. Decoupling I/O from processing would have made the difference.
I often use TJPEGImage with Scale:=jsEighth (in Delphi 7). This is really fast because the JPEG de-compression can skip a lot of the data to fill a bitmap of only an eighth of width and height.
Another option is to use the shell's method to extract a thumbnail, which is pretty fast as well
I'm in the vision business, and I simply upload the images to the GPU using OpenGL. (typically 20x 2048x2000x8bpp per second), a bmp per texture, and let the videocard scale (win32, Mike Lischke's opengl headers)
Upload of such an image costs 5-10ms depending on exact videocard (if not integrated and nvidia 7300 series or newer. Very recent integrated GPUs might be doable also). Scaling and displaying costs 300us. Which means customers can pan and zoom like crazy without touching the app. I draw an overlay (which used to be a tmetafile but is now an own format) on top of it.
My biggest picture is 4096x7000x8bpp which shows and scales in under 30ms. (GF 8600)
A limitation of this technology is max texture size. It can be resolved by fragmenting the picture into multiple textures, but I haven't bothered yet because I deliver the systems with the software.
(some typical sizes:
nv6x00 series: 2k*2k but uploading is just about break even compared to GDI
nv7x00 series: 4k*4k For me the baseline cards. GF7300's are like $20-40
nv8x00 series: 8k*8k
)
Note that this might not be for everybody. But if you are in the lucky situation to specify hardware limits, it might work. The main problem are laptops like Thinkpads, the GPUs of which are older than the avg laptop, which are in turn often a generation behind Desktops.
I chose OpenGL over DirectX because it is more static in time, and easier to find non-game related examples.
Try to look at the Graphics32 library : it's very good at drawing things and works great with Bitmaps. They are Thread - Safe with good example, and it's totally free.
Exploit windows capacity to create thumbnails. Remember that hidden Thumbs.db files in folders that contain images?
I have implemented something like this feature but in VB. My software is able to build thumbnails of 100 files (mixed size) in around 10 seconds.
I am not able to convert it to Delphi though.

Resources