1

I'm building a camera application that saves the image data to a single JPEG file in the sandbox. The images average at about 2mb in size.

Problem : I cannot display the images in a photo viewer because having a few images in memory throws memory warnings and makes scrolling through the images very slow.

I cannot split the image into tiles and save them to disk because that's even more expensive than displaying the single image. I tried splitting the image up into tiles upon capture, but on the 5S it took, on average, 5 1/2 seconds to save all the tiles to disk. It will only get worse from there as the app is executed on older devices. This is very bad because what if the user exists the app in the middle of the save? I will have missing tiles and no uncompressed original file to find missing tiles later.

Question : what's the best way to show a full sized image without causing memory issues and keeping the scrolling fast? Tons of camera applications on the App Store do this and the Photos app does this, there has to be a good solution.

Note : I'm currently showing a thumbnail of the image and then loading the full size image from disk in another thread. Once the full size image loading has finished, I present the full size image on the main thread. This removes the memory issues because I only have one full size image in memory at once, with two thumbnails, but still causes lagging on the scrollview because drawing the full size image in the main thread is still pretty expensive.

I would greatly appreciate any input!

Homeschooldev
  • 405
  • 1
  • 7
  • 18
  • Take a look at this sample project: https://github.com/jessedc/JCTiledScrollView Cutting your large images into tiles doesn't have to be more expensive. Many good references are given in the project's readme also. – Adam Eberbach Mar 17 '14 at 05:57
  • Correct me if I'm wrong, but that project assumes you have precut tiles, which is my problem, I don't have precut tiles because it's a camera app. – Homeschooldev Mar 17 '14 at 06:06
  • I would still tile the images by rendering tile-sized regions of the image into a core graphics context and then saving those tiles, as the images are captured. Your immediate display may have to be a lower resolution but you can quickly refine it as your tiles are prepared. You do a lot of work up front but a lot less on successive viewings. – Adam Eberbach Mar 17 '14 at 06:12
  • I tried splitting the image up into tiles and writing them to disk upon capture, but it took, on average, 5 1/2 seconds to save all the tiles on an iPhone 5S. This is really bad because the 5S is pretty much the fastest the device, so that means it will only get slower from there. The problem here is, what if the user closes the app in the middle of the save? I will have missing tiles and no original file to find those missing tiles later. – Homeschooldev Mar 17 '14 at 08:15
  • Granted this is a lot of work but I would still tile them. Start by saving and presenting the original image as you do now. In the background process your tiles and switch over when you can. You just have to live with laggy scroll until your bg processing is complete. – Adam Eberbach Mar 17 '14 at 12:14
  • @Homeschooldev: What was the solution you took? – testing May 01 '15 at 09:13

2 Answers2

0

you could..

  1. create a down sized thumb nail..
    • create a smaller image and save that in a different "sandbox" folder.. and read that for browsing.. then after that load the image if the user wants to look at it full size.
Nokdu
  • 98
  • 7
  • That's what I'm currently doing. Scrolling is very laggy when attempting to present the full sized image because drawing the image using UIImageView is still pretty expensive to be done in the main thread. – Homeschooldev Mar 17 '14 at 05:45
  • @Homeschooldev Oh.. you could tile the images when you are loading them (but not save to disk) then present them if a part of the tile is needed to be drawn. this SHOULD give an increase in performance. – Nokdu Mar 17 '14 at 05:58
0

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.

Second way which I suggest you is to check the example from Apple for processing large images called PhotoScroller. The images have already been tiled. If you need an example of tiling an image in Cocoa check out cimgf.com

Hope this will helps you.

Irfan
  • 4,301
  • 6
  • 29
  • 46
  • This is not a good solution as saving the image as tiles takes, on average, 5 1/2 seconds on the 5S. Performance will only degrade with older devices. If the user exists the app it will cancel my save and there will be missing tiles and no original image to find the missing tiles later. – Homeschooldev Mar 17 '14 at 08:21
  • Ok then kindly check this apple documentation for Large image downsizing amt it helps you : https://developer.apple.com/library/ios/samplecode/largeimagedownsizing/Introduction/Intro.html – Irfan Mar 17 '14 at 09:05
  • Also check this link :http://stackoverflow.com/questions/12089453/huge-images-in-ios-app-without-catiledlayer – Irfan Mar 17 '14 at 09:05
  • Kindly let me know this info helps you or not? – Irfan Mar 17 '14 at 09:06
  • I've never seen that large image downsizing project before. It looks like it would work, but I attempted to run it on my phone and it pretty much immediately crashed due to memory issues. 300mb+ in memory. – Homeschooldev Mar 17 '14 at 18:58