We are getting reports in the field, on both iOS and Android, of partially loaded profile images in our mobile app.
Here is what it looks like (note that I have gaussian blurred part of the image to protect the privacy of our members, but the grey is what is actually rendered):
AFAIK there is not a concept of loading "Progressive JPEGS" in UIImageView, so I am at a loss about how this image could even have been rendered at all. This code has not been modified in at least a year. All images are hosted on S3, and have been for 2 years.
Is it somehow possible that carriers are truncating images now if a device hits a certain bandwidth limit?
-- Edit --
I can confirm we were able to repro this behavior on an AT&T network. Is it possible that AT&T is munging images in this fashion when a user goes over his data cap or something?
I had this same issue crop up when I switched from https to http images. Needless to say... I switched back to https based images.
Related
I have a tableview that is populated from images on my server that I download. My question is How would I go about getting different images for the different resolutions for the devices? 6 vs 6plus etc?
Do I write code that is device specific? e.g
if device is equal to 6 load #2x images 'from #2x url'
else if
device is equal to 6 plus load #3x images 'from #3x url'
and so on.
Or is there a more efficient way of going about this?
You've got several options, depending on the back-end technology stack you're connecting to.
Options if you're using a custom server that you've built yourself, or have control over the code:
Add device scale detection into your image service that checks the inbound user-agent for device scale, and serves the appropriate image for that device. This is hands down probably the simplest solution to implement if you manage your own back-end.
Write into your API a url path param that serves the appropriate image scale; you can then use the UIScreen class (UIScreen.mainScreen().scale) to adjust your target URL accordingly, e.g.:
https://api.yourbackend.service/images/{imageid}/#2x.jpg
This is arguably more difficult to implement, but it's also a lot more robust (doesn't rely on potentially changing user-agent strings), and it's a lot cleaner when logging or querying analytics.
You could probably also use something like retina.js to handle this on your back-end, though I can't tell you whether or not it will work heedlessly (haven't tried it).
Options if you're using a CDN image host:
Use their built in HiDPI support (Cloudinary, for example, provides this -- read about it here).
If your CDN doesn't support this, switch to one that does ;)
You are coming at this exactly backwards.
A table view cell's image view is tiny. You are not going to be showing these images at full size anyway. So there is no point whatever downloading larger and larger images only to be displayed at tiny sizes. That's a massive waste of time, bandwidth, and ultimately memory (if you really try to display large images in every cell, you will run out of memory and crash).
If you have a choice of image size to be retrieved from the server, you should be doing just the opposite of what you are suggesting: download a thumbnail of your image suitable for display in the table view. If the thumbnail is twice the size of the image view, it will look good at all resolutions with minimal waste of memory.
If this app is about also fetching the real full-sized image, outside your table view, you can do that later when requested by the user.
I've built a website that stores images in 4 different sizes on the file system. It keeps the origional file size, medium, thumb, small image and resizes them as they upload.
We then created the web api to allow us to build the ios/android apps.
while building the apis our overseas developer then asked to provide the image dimensions along with the image file name. it took a lot of work regarding calculating the image sizes and saving them to the database.
{ "imagefilename" : "someimage.jpg", "LargeimageHeight" : "1000",
"LargeimageWidth" : "500", "mediumImageHeight" : "500",
"mediumImageWidth" : "250",
"smallImageHeight" : "100", "smallImageWidth" : "60" }
with the amount of image sections we have in the website made it a task and i want to know if this is really nessesary. Im not an ios developer but not really sure as to why the additioanl dimensions of the image need to be saved and or really needed.
i thought the ios has the image feature (#3x) (#2x) (#3x) ??
or do i use 1 specific folder image size for ios ??
does this always happen in the ios world for images that the code needs to know the image dimensions for the best result?
thanks
If your iOS application show images in flow layout (like pinterest style) you must return image dimensions. Otherwise I don't think its nessesary
Do you need the return the image dimensions:
Short answer: no. You can load the image using UIImage, and call image.size.height and image.size.width.
Long answer: maybe, depending on the interface design of your application, and if every image has different dimensions, it might take a performance toll to load the image into memory before being able to get its size (and probably do autolayout and have it render on screen). You might have issues with scrolling speed, but it will depend on the specific design and requirements.
What is the #2x #3x iOS image feature
iPhone and iPad screens come in different pixel densities (non-retina, retina and the retina iPhone 6+ screen). If you have a local image, stored on the phone, it can preload the image with the right scale automatically, by just providing the base name of the image, if you add the right suffix to each asset like name#2x, etc.
Sadly, it doesn't work the same for remote images see this answer. You will have to check yourself for the scale and load the right image, or load one big file, and let it be resized on the device.
You should consider providing dimensions inside your API response.
Think design:
When you scale your app to have many images at once, or when you distribute your app to multiple devices, you may realize the advantage. Your iphone 4 may end up downloading the image (worse, images) intended for iPhone 6S, and so on. If the reverse is true, it's even scary to think about.
How about the device asking for the image it's best suited for?
As for scaling of images, Bram De Geyter is correct - you can render whatever resides on the device, not fetch the correct one from the server. So having your API giving you the right dimensions is the only solution.
I have described the whole image loading from API approach in my blog here.
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
I've developed a fairly graphic heavy website.
Mostly it is fully functional but a few users are observing a few corrupted background images when viewing from iPad or iPhone.
It doesn't seem to make a difference whether the image is a .jpg, .png or DataURI image.
Screenshots of the corrupted images can be seen here http://imgur.com/a/UbRim
On an iPhone, refreshing the page doesn't make a difference. On and iPad apparently, it does. Most of the time and most of the images look absolutely fine.
The website is http://www.alternative-tune.co.uk/
The only other thing I wonder is could it be the color profile (simply because I don't have a clear understanding of them). Photoshop tells me it's:
RGB: sRGB IEC61966-2.1
CMYK: US Web Coated (SWOP) v2
But surely this is ruled out by the fact that it works fine most of the time?
Does anyone have any ideas what's going on?
Many thanks,
Ben
I want to make an iOS app. This app will have over 200 images, each with different sizes (500x500[maybe smaller] and less). What is the best method to keep them, having a smaller app size?
I think about optimizing their sizes for web in photoshop, but still the app will have a big size if I want to keep and a respectful quality.
Any ideas?
Well, I don't know if you can do this for your app, but you can download them from the internet once the user installed your app. This way you can keep the size of the package as small as possible (I assume you talk about non-critical images, that can be obtain afterwards).
UPDATE
Alternatively you can use SVG instead of bitmaps, of course if applicable:
how to render svg file in iphone and ipad