Thursday, June 3, 2021

Instagram Image Quality

At my day job I spend all day capturing live video, compressing it, distributing it, and showing it to users.  Hence when people ask questions like, "Why do my Instagram photos look crappy?", it tends to pique my interest.  In this post I'll briefly summarize the basic workflow and offer some guidance on how to debug such issues.

There are a variety of moving parts associated with contributing image content to a site like Instagram.  The following diagram shows the basic workflow.  While not specific to Instagram's specific internal process, all these sites basically work the same and have the same components.

(click to enlarge)

The important consideration here is that there are two largely disconnected processes:  the process by which the content gets into Instagram, and the process that users viewing the content go through.  Problems introduced as part of the contribution process will likely impact all viewers, but there are cases where the contribution phase may have worked perfectly but different viewers see different results due to the way content is delivered to the user.

Let's quickly go through the different stages and then we can talk about how to break down the problem.

Acquisition - This essentially encompasses taking the initial picture.  This is a combination of the content itself and the camera settings used.

Question:  Why might close-up photos of an object look ok but a picture of me standing in grass in front of some trees look crappy?  Answer:  image complexity.  Bear in mind that the encoder typically has a target image size so it has to make decisions about which parts of the picture to make look best while still creating an image that is N megabytes in size.  An object in front of a solid color background is comparatively simple to encode and the compression process emphasizes ensuring the object looks good.  When you take a picture in front of a complex background the compression engine may not know what areas to optimize, and thus the encoder will dedicate more bits in the final image to making the grass look less blurry at the cost of your face looking worse.  This is why it's often difficult to take good video of soccer games or other games played on a large field.  What the viewer cares about is the players and the ball (sometimes referred to as the "Region of Interest") but the compression engine doesn't know that and thus it spends as many bits encoding the entire field at the cost of quality of the individual players.

Ingest - This is the process where you take the picture from the camera and send it to Instagram.  There is processing that can happen within the phone before it gets sent out.  The image from the camera may be decoded and re-encoded to allow cropping (either as a result of user defined cropping, or to meet an expected aspect ratio), change the resolution (e.g. Instagram has a maximum width of 1080 pixels, so anything larger than that needs be rescaled before uploading), or reduce the size of the encoded picture (e.g. change the 5MB photo into a 1MB photo at 1080x1080 prior to upload to reduce bandwidth usage).  Aside from allowing the user to crop the photo, Instagram doesn't expose many user-configurable options to control the upload process, but decisions are being made behind-the-scenes which the user won't be aware of, and this behavior may change whenever the Instagram application is updated.

Server Side Processing - this is what the website does to the photo after it's uploaded from the Instagram application running on the phone.  The main task being performed is creating multiple renditions of the image at different resolutions and bitrates.  While the user is uploading a high quality photo, it's entirely likely that some users would be better suited to receive lower quality renditions, and the rescaling/re-encoding that occurs here is how that is accomplished.  Doing it at the server also allows for the user to only have to upload a single high quality version of the picture which helps from a bandwidth perspective.  That said, it's possible that bugs in this process may result in cases where a particular rendition of an image has problems (e.g. the 1080x1080 version looks fine, but the 640x640 version look poor).

Viewing - Unlike a desktop browser, a mobile application like the Instagram app has much more complex decision making when determining which rendition of an image to download and show to the user.  In order to provide an optimal viewing experience for all users, the app may automatically do things like downloading a low quality version of an image to minimize cellular data usage.  If there is a problem with this decision making though the user may end up with poor quality images (i.e. they were connected over Wifi and had plenty of bandwidth, but are being sent the 320x320 version of the image).

A note about "Pinch to Zoom":  When you zoom in on an image in the application, you're not really seeing a higher quality version of the image.  You're just zooming in on whatever image was already downloaded.  When the image you're zooming in on has a higher resolution than the display, this results in being able to see more detail.  However if you're zooming in on a very low resolution image, you'll see artifacts like blurring or jagged lines.  It's also important to note that zooming in on the original image prior to uploading is a very different experience than when viewing it after upload.  This is because in the former case you're zooming in on the original, highest quality image, while in the latter you're zooming in on whatever the website delivered which may already be of reduced quality.

"Ok, so now you've spent a bunch of paragraphs explaining how all this works in principle.  How do I actually figure out what's broken?"

Having explained the workflow, you can break up the problem to understand which stage is causing the issue.  This is especially true if you know definitively that the image quality was good at one point but has since gotten worse with new content.

For the purpose of offering an example, let's say you know definitively that image quality was fine in April, but now all the images you upload look crummy.  Here are a few concrete steps you can perform to narrow down the issue:

  1. Go back to posts from April and make sure the image quality still looks good in the app (i.e. pinch-to-zoom and ensure proper detail is shown).  If those posts from April look good, then you've likely just cut the problem in half and confirmed that it's not an issue with the viewing experience and the problem is some aspect of the authoring half of the workflow.
  2. Assuming Step 1 looked good, pick a specific photo from a post from April, and go back into your Instagram app and find that photo in your camera reel.  Upload that exact same photo again in a new post.  This cuts the problem in half again:  If the newly uploaded photo looks good, then you've got some problem with the camera app and how new photos are being taken (e.g. camera settings changed).  If the newly uploaded photo looks bad, then you know it's got something to do with how the photo is being processed by the Instagram app and/or the Instagram website.
  3. If step 2 looked good then you need to figure out why the camera app is taking pictures that no longer are properly processed by Instagram.  Set up a tripod and be prepared to take a series of images of the same object but with different camera settings (putting a small post-it pad in the corner with a number will allow you to keep track of the pictures without impacting the image quality).  Create a spreadsheet to keep track of exactly how each possible setting in the camera application was configured for each image.  Upload the resulting images in a post and compare the quality to see which settings have an impact.  Hopefully you'll create 20 pictures and come to a conclusion like, "When the HDR+ option is enabled, the images look like crap" or "When the aspect ratio is changed from 4:3 to 16:9 the problem happens".
  4. If step 2 looked bad, then photos that are known to have worked previously now don't work and something has changed either within Instagram's infrastructure, the Instagram app, or the app settings.  There are fewer dials available to the user, but I would suggest uploading the same photo multiple times with different settings for the "data saver mode", "high resolution photos", cropping settings, making sure you're on Wifi and not cellular during upload, etc.  It may also be worthwhile to completely uninstall the app after doing a "clear data" and "clear cache" in the Android Application Preferences screen.  This will wipe out all settings/configuration, in case there is some subtle or undocumented setting which is causing the issue (e.g. something which didn't get properly handled when upgrading from one version to the next).
I hope this offers some insight that will help in diagnosing such problems.