I'm working on an iPad-only iOS app that essentially downloads large, high quality images (JPEG) from Dropbox and shows the selected image in a UIScrollView and UIImageView, allowing the user to zoom and pan the image.

The app is mainly used for showing the images to potential clients who are interested in buying them as framed prints. The way it works is that the image is first shown, zoomed and panned to show the potential client if they like the image. If they do like it, they can decide if they want to crop a specific area (while keeping to specific aspect ratios/sizes) and the final image (cropped or not) is then sent as an email attachment to production.

The problem I've been facing for a while now, is that even though the app will only be running on new iPads (ie. more memory etc.), I'm unable to find a method of handling the images so that the app doesn't get a memory warning and then crash.

Most of the images are sized 4256x2832, which brings the memory usage to at least 40MB per image. While I'm only displaying one image at a time, image cropping (which is the main memory/crash problem at the moment) is creating a new cropped image, which in turn momentarily bumps the apps total RAM usage to about 120MB, causing a crash.

So in short: I'm looking for a way to manage very large images, have the ability to crop them and after cropping still have enough memory to send them as email attachments.

I've been thinking about implementing a singleton image manager, which all the views would use and it would only contain one big image at a time, but I'm not sure if that's the right way to go, or even if it'd help in any way.

  • If you reached the physical boundaries of the memory you can't do much about it. Maybe you can scale down the images after download and crop these? – MrBr Nov 26 '13 at 14:50
  • I believe that AFNetworking will be useful for downloading images and managing some kind of internal caching. Also, instead of using UIScrollView you should be using something like UICollectionView, which will reuse your UIImageView objects. Once the images are replaced in your UIImageViews your memory should be clearing too. – Guy Kogus Nov 26 '13 at 14:55
  • @MrBr I could absolutely scale down the images when viewing and even when cropping them, but when I need to be able to send them to "production", that's when I'd need the (cropped or not) high quality image. – Dids Nov 26 '13 at 14:58
  • @GuyKogus I'm currently using Dropbox's Sync API, which caches the files, then I'm only loading the images to memory when I need to. Since the current implementation works well otherwise, I'd rather stick with UIScrollView. I might add a shared UIImageView to an image manager singleton though, wonder if that'd help (or even work). – Dids Nov 26 '13 at 14:59
  • and just sending a download-link to a public image will not serve your needs? – MrBr Nov 26 '13 at 15:09

One way to deal with this is to tile the image. You can save the large decompressed image to "disk" as a series of tiles, and as the user pans around pull out only the tiles you need to actually display. You only ever need 1 tile in memory at a time because you draw it to the screen, then throw it out and load the next tile. (You'll probably want to cache the visible tiles in memory, but that's an implementation detail. Even having the whole image as tiles may relieve memory pressure as you don't need one large contiguous block.) This is how applications like Photoshop deal with this situation.

  • I've read about Apple's implementation of tiled images before, but would it work with cropping as well? Don't get me wrong, I like the idea of tiling them, but if it would require drastic changes to the already working features (apart from implementing the tiled image), I don't think I'd meet the deadline in time. – Dids Nov 26 '13 at 15:43
  • to me a quick and easy implementation of tiling would involve creating a UICollectionView where each cell is a tile of the image. This would take care of cell/image view reuse, never having to keep more than you need in memory. probably not as advanced as photoshop or apple, but it should relieve some memory pressure for you. Though I don't know how zooming and cropping would work with this... – Patrick Goley Nov 26 '13 at 15:54
  • Zooming and cropping (during user interaction) should just be a view transform. It shouldn't in any way affect the underlying image data. Once you need to email the image to the printer, then you can do the actual cropping. It might be some work to implement, but you have to weigh that against the problem you're trying to solve. – user1118321 Nov 26 '13 at 17:12

I ended up sort of solving the problem. Since I couldn't resize the original files in Dropbox (the client has their reasons), I went ahead and used BOSImageResizeOperation, which is essentially just a fast, thread-safe library for quickly resizing images.

Using this library, I noticed that images that previously took 40-60MB of memory per image, now only seemed to take roughly half that. Additionally, the resizing is so quick that the original image gets released from memory so fast, that iOS doesn't execute a memory warning.

With this, I've gotten further with the app and I appreciate all the idea, suggestions and comments. I'm hoping this will get the app done and I can get as far away from large image handling as possible, heh.

Your Answer

