Memory issue in storing and retrieving Image from database - ios

I am working on application which include native SQLite database in which I am storing and retrieving images and showing into My application.
Now my problem is Like I am storing lots of images in directory and its path storing into database. So when I retrieve that path from database and load image into application, Memory Increases upto 10-20 Mb per image.
I also tried to store image data into database but same issue, Memory increase 10-20 Mb per image.
Please what should I do for this memory issue ?
Help me with it

Images, when used in the app, may require considerably more memory than the size of the asset in persistent storage might otherwise suggest. Assets are frequently compressed (e.g. JPG or PNG), but when you use the image, they're uncompressed, often requiring 4 bytes per pixel (one byte for red, green, blue, and alpha, respectively). So, for example, a iPhone 7+ full-screen retina image can require 14mb when you use the image. So, the memory-efficient technique is to employ lazy loading, not creating the UIImage objects until you absolutely need them. And, as Jerry suggested, because the amount of memory is determined by the size of the image and not the imageview in which you use the image, if your images have dimensions greater than required by the UIImageView in which you use them (i.e. width and height of the imageview times the "scale" of the device), you may want to resize the image accordingly.

It may be the case that the images you are trying to display are much larger than they need to be on the screen. Try loading the images into memory, creating a version with the size you need, and then using that. Of course, you could implement some caching so you don't have to keep resizing the same images. But then when the original image goes out of scope, its memory will be released. If you always need your images at the same size, try resizing them before storing them in the database, but if you want to support multiple sizes (for different devices, maybe), then store the images at the largest size you need and resize for the others.

Related

Large jpeg using more memory than smaller jpeg when loaded in a UIImageView. Why?

The login view in our app uses large background images. To try and save on memory/app size I resized and compressed these images, which reduced their filesize significantly (less than 1mb, down from several mb).
When monitoring my apps memory usage (XCode debugger) there is a clear spike when a modified image is displayed (around 30-40mb). I'd accepted this as normal and simply made sure to release the image asap to limit memory usage.
I've recently started replacing a couple of the images and wanted to preview the new ones before resizing/compressing them. I noticed that these images (one of which is 11mb on disk and 4640x3472 pixels) has no visible effect on app memory usage whatsoever, increasing 'Other Processes' instead (by around 20-30mb).
Can anyone explain what's happening here? I want to confirm it is advisable to continue resizing/compressing the images.
Note that I'm loading the images using UIImage(contentsOfFile:) and I resized/compressed the images using GIMP. The new images have been taken straight from Flickr and unmodified.
Cheers.
The in-memory size of the image (as a UIImage) is different to the compressed on-disk size (your JPEG)
The UIImage takes 4 bytes (RGBA) per pixel x height x with - so for a 4640 x 3472 image, you're looking at 64,440,320 bytes - quite different to the 11MB on disk

iOS app crashes because images use too much ram

I know this is a stupid problem, but this is my first real app that I have to make, I have no one to ask and I looked up this problem and found no other similar problems.
My app crashes on real devices with no exception. I saw in the simulator that uses too much RAM and after a while I got to the conclusion that the pictures I am using are to blame.
The app is structured in this way: it has 8 viewControllers for different things: for example, it starts with one which lets the user select the avatar with which he/she will play and here I have two pictures, next is a viewController which shows the stats for that avatar and here it is another picture and so on. The problem is that each picture uses 40MB of RAM to be displayed and things add up so the app uses more than 300MB of RAM when the user gets to the gameviewCOntroller where the game is. Because of this, on devices like iPAD 2 or iphone 4 it crashes, but not on iphone 5.
I tried to set the images both from "images.xcassets" and from a ".atlas" folder, but the result is exactly the same. The pictures have a dimension of no more than 1500x1999px, they are in png format.
Also, I saw that if the app were to start directly into the gaveViewController it would use 180MB so the other viewController remain in memory or something like that. Should I "clear" them or something similar?
//-------update-------
This is what I got from Instruments:
Memory is a big deal on mobile devices, there is not a clear answer to you question, but I can give you some advices:
If your images are plain colors or have symmetric axes use resizable images. You can just use one line of pixel multiplied by with or height to cover the entire screen using a small amount of memory
Image compression doens't have effects when the image is decompressed. So if you have a png that is 600kb and you are thinking that converting in a 300kb will lower memory usage is only true for "disk space" when an image is decompressed in memory the size is widthXheightXNumber_of_channelXbit_for_channel
resize images: if are loading a 2000px square image into memory and you show it inside an image view of 800 px square, resize before adding it.You will have just a peak while resizing, but later it will use less memory
If you need to use big images, use tiling techniques such as CATiledLayer
If you don't need an image anymore get rid of it. It's ok to have an array of path to images, but not an array of full uncompressed images
Avoid -imageNamed it caches images and even if Apple says that this cache is released under memory pressure, you don't have a lot of control on it and it could be too late to avoid a crash
Those are general advices, it's up to you if they fit your requirements.
You should definitely follow Andrea's advices.
Additionally you should consider setting the image size to exactly what your need is. You're saying that you've tried to set them from xcassets so you have full control over the images you're loading, which is great (compared to downloading an image that you cannot modify).
I highly suggest you read some documentation on using Asset catalog files. This will allow you to have high-resolution image for bigger screens that also have more memory, and smaller ones for older devices, which is what you want here.
Also, note that 1500x1999px is still a very big size for most mobile devices.
More links about screen-size:
https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/MobileHIG/IconMatrix.html
http://www.paintcodeapp.com/news/iphone-6-screens-demystified

Display large images on iOS without precut tiles

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!
you could..
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.
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.

What are the ways to reduce bundle size on iOS?

I have some images which are huge in size and my bundle size currently is 70 MB. I think Xcode already runs the assets through png crush.
Do not use any text images with useless effects, use UILabels instead.
Draw simple shapes and effects using CAShapeLayers instead of using
images.
Use JPEGs instead of PNGs where you don't need transparency.
(Actually file size depends on the image content here)
Use Save for Web option in PhotoShop or other tools to optimize PNG
images.
Use sprites combined together instead of separate images.
Make sure you delete all unused resources.
Do not localize common parts of the images, localize only the
different parts. (think of a background image with a small flag at
the bottom for each locale. use one single bg image and separate flag
images. localize flag images only, not the entire bg images with the
flags.)
Use the same splash images for iOS7 and previous iOS versions. (You
need to manually edit the JSON file in .xcassets)
Try using a CDN to download assets on the first launch.
In addition to images keep those in mind too:
Try replacing custom fonts with default system fonts if you don't
need them really.
Use MP3 audio files instead of WAV files. (or other
compressed formats)
Make sure you delete all unused 3rd party frameworks.
You can try converting the images to jpg (if they don't have any transparent regions).
Also try using http://imageoptim.com/
It seems very unlikely that you actually need huge images. After all, the screen is not huge. Thus, the most likely form of size reduction is to reduce the physical dimensions of the images to the size you are actually going to be displaying.
This saves bandwidth when the user downloads the image, reduces the size of the app on the user's hard disk (the device), and also saves memory at the time an image is loaded. It is a vast waste of RAM to load an image that is larger than the size at which it will be displayed; after all, remember, the memory involved rises exponentially with the square of the difference.
One option is to host the images on a CDN like OpenText and fetch them as part of app initialization, or whenever they are first needed. Obviously this is more coding, but projects like SDWebImage make it pretty easy:
https://github.com/rs/SDWebImage/tree/master/SDWebImage
It also gives you the flexibility to swap out those images later if you use caching headers.

Does UIImage Cache the File or the Rendered Bitmap?

I generally use Fireworks PNGs (with different layers, some hidden, etc.) in my iOS projects (loaded into NIBs in UIImageView instances). Often, I take the PNG and resave it as PNG-32 to make the file smaller, but I'm questioning this now (because then I have to store the Fireworks PNG separately)....
In my cursory tests, a smaller file size does NOT affect the resultant memory use. Is there a relationship, or is it the final rendered bitmap that matters?
Note: I'm not asking about using an image that is too big in pixels. A valid comparison would be a high-quality jpeg that weights 1mb vs. a low-quality jpeg of the same content that weights 100K. Is the memory use the same?
UIImageView does not do any processing so if you set a large image the whole thing is loaded into memory when the imageView needs it regardless of the size of the imageView. So, yes, it does make a difference. You should store the smallest images that work within the imageView.
While your current example is using NIB's, if you were creating an app that displays large images acquired from other sources (e.g. the device camera or an external service) then you would scale those to a display size before using them in a UIImageView.

Resources