## Images in Web Development
### Background
Processing images for use in web-development is a "knowledge area"
I have had to reform into a more coherent thought-process. As a result,
I decided to produce a quasi-unified set of principles - cobbled together from
notes in my past - to serve as a sort of general reference guide in the field.
I am not delving into the specifics of graphic design or hyper-technical
specifications of color resolution and the various technologies involved
in rendering these.
Rather, the idea is to just set down a set of best-practice principles as a
reference guide for optimizing images in their use for web pages.
To skip the background discussion and go directly to the list of principles,
please proceed to the Conclusion: Putting it all together section.
### Some Preliminaries
#### Optimization of what?
Ostensibly, the challenge which presents itself when working with images for
the purposes of web development is a question of *optimization*.
Before proceeding any further, it's helpful to establish precisely what it is
we're trying to accomplish with the task at hand - in other words, optimization
of *what*?
For all intents and purposes, I am assuming here that our goal is:
#### ***To deliver the best image quality in the most efficient manner possible.***
As is implied by this goal, there is a trade-off involved here. Namely, that
trade-off has to do with delivering the best image quality while doing this
either as quickly as we possibly can or in a manner which minimizes the size
of the transferrable file(s) involved.
As load times are highly correlated with file sizes, we can assume these
constraints to be one and the same and thus focus our efforts on the
constraint that is most easily checked when working from the host machine -
the resulting file size.
*Note that tools which come bundled with some browsers like Chrome allow*
*developers to test load-times under various throttling conditions to better*
*approximate page loads under various circumstances. As a result, we can use*
*such tools at our disposal once we've addressed the basic challenge of*
*maximizing image quality while minimizing file size.*
As with optimization functions in general, our goal can be expressed
mathematically with use of an objective function and a corresponding constraint
to properly formulate the optimization task at hand.
<br/>
Namely:
**Objective:**
max(Q)
**Constraint**
s.t.: s <= k
</br>
<br>
For which 'Q' in our objective function represents image quality which is
subject to the constraint that file size (s) must be no larger than a given
limit (k).
What Q actually is or should be varies with every situation. This is because
not only is Q dependent upon the available file format(s) for the image at
hand, it also varies with every use-case scenario such as whether the site
is meant to be used for print media as opposed to screen/display.
Indeed, stated thusly, one might be tempted to think that such variables are
easily substituted with desired values from the real-world. This is misleading,
however.
Since it is not possible to know *a priori* what every use-case scenario will be
and thus the determinants of 'Q' image quality or 'k' file size, we are left to
reducing our choices to a list of *best practices* for which the 'optimal'
approach is a function of available options and the intended use of said
image(s).
#### Determinants of best practices
This leads us to establishing what the parameters are which *determine* the best
practices mentioned above which; in turn, inform us of our options to arrive
at optimized images for use in web pages.
In short order, the determinants of these best practices are:
* image file format
* image resolution
* target viewport size
Before delving into how these three determinants interact with each other
to mold the requirements backdrop against which images are processed, a *brief*
treatment of the notion of compression will help to better gauge what's
involved in the task at hand.
#### Compression
*Compression* is the tool that we have at our disposal to reduce image file
sizes so that we may reduce file transfer/load times.
In other words the decision to compress or not to compress an image is
concerned with the delivery of the image:
"*in the most efficient way possible*"
part of our optimization goal discussed above.
##### Lossy vs. Lossless
Different image file formats exhibit different compression properties and the
notion of lossy as opposed to lossless compression is important to
understanding the quality of image that is renderable with various file
formats.
*Lossy* compression refers to the deterioration in image quality when
compression is applied to an image. This happens because the compression
method supported by the file format involves rendering either approximations
to the original image or by allowing some data to be discarded.
*Lossless* compression, as might be expected, is a compression approach which
avoids the deterioration in image quality because features of the original
image are accurately preserved in the resulting compressed version.
*Compression Ratio* refers to the ratio of the size of the uncompressed file
to that of the compressed file:
<div><pre class="code">
Compression Ratio = (Uncompressed Sz) / ( Compressed Sz)
</pre></div>
and is a shorthand way of comparing the efficacy of various compression
techniques. A ratio of 2:1, for example, would imply that the compressed
image is one-half (or 50%) of the size of the original uncompressed image,
thus introducing a benefit of a 50% size reduction.
Bearing in mind that the whole point of compression is to reduce file size, it
should be readily apparent that lossy compression techniques can yield much
smaller file sizes but only at the cost of a degradation in resulting image
quality when compared with lossless compression.
With that said, let's have a look at different image file formats and what
compression properties each has.
### Image File Formats
##### SVG vs Bitmap/Raster
A critical difference between formats which needs to be established is that of
the general categories of SVG and Raster images.
SVG stands for *Scalable Vector Graphics* and is a graphics format which uses
mathematical formulas to draw shapes/images which comprise the overall image.
A massive advantage of SVG format files is their scalability. The SVG format
was specifically formulated for the Web and as a result SVG images exhibit *no*
loss in quality when they are zoomed/resized. Because of its very nature, SVG
images are lossless and thus maybe compressed at will.
Raster images, on the other hand, are bitmaps composed of a fixed set of pixels.
Some raster/bitmap formats support lossless compression while others do not.
When enlarged, lossy-compressed bitmap images may well exhibit poor-quality
with noticeable pixelation.
Despite the drawbacks associated with lossy-compressed bitmap images, issues
like the effort required in the vectorization of images, capacity constraints
in handling complex color situations, and a historical predilection towards the
use of raster images has meant that **bitmap images still dominate** with the SVG
format being used mostly in simplified graphics use-case scenarios such as
logos and the like.
##### Bitmap/Raster Image Formats
As of the time of this writing, the most popular image requests by format
according to the [http archive](http://httparchive.org/interesting.php#imageformats) were:
* JPG ~45%
* PNG ~28%
* GIF ~24%
* WEBP ~1%
* OTHER (TIFF, BMP, etc.) ~1%
<br>
**JPEG/JPG** - from the acronym Joint Photographic Experts Group, which created the
standard. JPGs are perhaps the most popular image file format on the web
because they were developed specifically for handling photographs in mind
(which, in turn, are a high proportion of all web images). They render
images in excellent quality even at very high compression ratios which they do
by discarding information in images the eye is least likely to notice.
**PNG** - stands for Portable Network Graphics and is a format which was created
as an open source alternative to GIF (see below). Unlike GIF files, however,
PNG files support more than 256 colors and support transparency. Beyond that,
PNG files support lossless compression and thus deliver better quality files
at a smaller size than do GIFs.
**GIF** - the Graphics Interchange Format is an older format which supports a
maximum of 256 colors. As a result of this, recommended use-case scenarios for
\*.gif files tend to be those for non-photographic images with broad-sweeping color
areas and *not* recommended for images with more complex color schemas such as
photographs or highly-detailed illustrations. GIF files may be losslessly
compressed but the trade-off is generally a simplistic/low quality image where
the advantages to compression are small to begin with.
**WEBP** - one of the newer formats introduced by Google to overtake JPG/PNG
and designed specifically with more efficient loading of web pages in mind.
Both lossy and lossless compression is supported by the WEBP format and it
sports better compression ratios than traditional file formats. It is very
likely that webp image formats will come to reign in the future as they are
far more efficient than their popular JPEG counterparts. That said,
not all browsers natively support this type as of this writing.
**TIFF** - or the Tagged Image File Format is a flexible format which can
support either lossy or lossless compression as the file stores details of
its own image storage data. Generally speaking, TIFF serves as the standard
for sharing photographs meant for printing and is commonly the format to which
photos from cameras in their native RAW format are converted. As a result,
usage for most TIFF files tends to be of either not compressed or losslessly
compressed, resulting in large file sizes.
**BMP** - an old Microsoft format which does not support compression, thus
lossless by default. While it had its day as it does render images well,
\*.bmp files do not scale well and for these reasons it is rarely (if at all)
used on web platforms.
My preferential rank-ordering of each format (based purely on my own
experience) as broken down by feature is as follows:
***Photographic Source Sets***: TIFF > PNG > JPG
The TIFF format by far carries the highest density photo information, being
one-step removed from the actual camera RAW files. PNG files *as a source*
for photos is superior to JPG as the latter will see quality deteriorate with
each save while the PNG remains unchanged.
***Lossless Compression***: TIFF > PNG > BMP > GIF
Both TIFF and PNG files offer better lossless compression than either GIF or
BMP. Although BMP image quality is arguably better than that of a GIF, it
really isnt' supported. GIF is only lossless when it comes to images with
no more than 256 colors (so very simple images).
***Lossy Compression***: TIFF > JPG
TIFF only comes out first here because of the quality of lossy compression in
a TIFF has the potential to approximate lossless but JPGs are superior when
compared on a quality/size basis.
***Photo Transparency/Translucency***: PNG > WEBP
Both formats offer a transparency effect but PNG is far more widely supported
than WEBP which (as of now) still requires plug-ins in some browsers. That
said, I expect the WEBP format to grow in dominance in short order.
***Simple Graphics/Icons***: SVG > GIF
While both formats are well suited to simplified graphics and even animation,
the flexibility of SVG over the older GIF with cruder graphics and color
constraints portends that SVG will likely make up a lot of ground against
GIFs.
***Photo Use for the Web***: JPG > PNG > TIFF
Use-wise, JPGs offer flexible compression settings such that the quality-to-
size trade-off can be customized. In just about any case, JPGs will offer
the best *quality-for-size* results. PNGs are lossless and thus trivially
compressible but generally of smaller size than a TIFF whose quality is
bound to be the best of the bunch.
(*Note that I am skipping treatment of many other file types such as*
*\*.psd and \*.xcf (Adobe Photoshop and GIMP, respectively) and others*
*which are specially designed for image processing tasks, in the interest*
*of restricting scope to popular web-destined formats.*)
##### Use in Practice
All this information is fine and dandy but what does it all boil down to
in practice?
Given what we've just reviewed, it should be obvious that this answer
depends on one's own circumstances including the file options/source sets
one has available, for what purpose the images are going to be used, and the
like.
***Okay, okay - but what about that 'general' use-case scenario, you say?***
The only way to really address this is identifying use-cases which might not
fall under the 'general' category implied here. Special cases of web sites
requiring highly-specialized image handling includes scenarios such as the
following (among others):
* Catalogs for Art Museums/Galleries
* Artist portfolios
* Photographic forensics
Setting such use-cases aside, one might consider a "typical" web application
to be a collection of *supporting images* for your text (be that a blog, online
store, etc.) rather than the *main focus* of the site.
In such use-cases, I would conjecture 99% of the time it all comes down to:
<div><pre class="code">
use: SVG for small, simple graphics files like logos
use: JPG compressed at desired levels for photographs
--[ unless photos: a). must be exact or b). transparent then use: PNG ]
use: PNG for small non-photographic complex (256+ colors) graphics images
</pre></div>
I hasten to point out that this is a very generalized list and does not
withstand some of the many possible use-case scenarios referenced above.
*(In other words: I realize there are many exceptions to the above so hold*
*that hammer where it is)!*
##### Mind the Quality Chain
Due to the prevalence of photographs in web imagery, our general practice
guidelines above put the JPG out as the centerpiece file format.
Being a lossy file format, one thing I can point out without hesitation is that
one should always be mindful that quality-wise:
<div><pre class="code">
There is no better than the master.
</pre>
In other words, for lossy formats, any/all descendant images generated after
processing can only equal (and will frequently be inferior to) the master in
terms of quality.
This is particularly true with JPGs where every successive save re-encodes the
image which results in an iterated approximation of its former self, thus
degrading the quality of the image with subsequent saves.
As such, it's always best, when possible, to work from a non-degradable
high-quality photo master (such as TIFF or at least a PNG) and to convert to
JPEG at the end of the processing.
This reminds me of another maxim I've often heard repeated:
<div><pre class="code">
Don't sacrifice quality for the sake of speed.
</pre></div>
The idea is, it defeats the point if your site loads quickly only to render
very low-quality images to the end-user. In such cases, either opt for a
compromise between speed and quality (preferably by re-working the image in a
better way) or choose not to use images at all.
##### File Formats: The Takeaway
Given the foregoing discussion, it is tempting to reduce our optimization
challenge introduced in the beginning to a matter of:
*Applying the 'best' compression-quality trade-off to JPEGs in our site.*
While there is some truth to this, it should be noted that this is nevertheless
a reductionist viewpoint which ignores various scenarios referenced above.
That said, we will adopt this is our working assumption as we move onto
non-format considerations below.
### The Resolution Question
The question of resolution comes into play because many of the tools which
handle image compression also allow for editing of image dimensions, thus
raising the question as to what dimensions are appropriate for web-based
images.
While this is intertwined with the topic of display sizes (discussed in the
following section), it is helpful to pause to consider what is meant by
resolution and how resolution settings, in turn, effect the manner in which
the processed image is rendered.
The term *resolution* has evolved to take on several meanings, among them:
* dots per inch (DPI)
* pixels per inch (PPI)
Conventionally, resolution was expressed in something called 'DPI' or dots per
inch. This was intended for print-based media but as the current treatment
is for web-based projects, PPI is our relevant metric.
Higher resolution means higher pixel density, which is measured by the pixel
L x W area formula of a given display (thus the megapixel metric of cameras).
Pixel size, however, also impacts resolution wherein smaller pixels packed in
a given area will render a crisper image than larger pixels. Thus, holding
the total number of pixels between two pictures constant on an identical
display, raising the PPI in one image will necessarily result in shrinkage
of the overall image size, ergo the following maxim:
<div><pre class="code">
image size = total pixels / pixel density
</pre></div>
which is another way of saying that all else held constant, you get higher
resolution in smaller images - something which we all by know instinctively now
in our interactions with digital media. In other words, resolution suffers as
images exhibit pixelation at larger dimensions given a constant pixel density.
PPI and resolution varies greatly from one display to another. That said,
for a long time most devices exhibited display resolutions which fell into one
of several standardized categories, broadly mapping to typical resolutions for
mobile, tablet, laptop, and desktop.
That all changed in 2012, however, with the introduction of Apple's 2x Retina
displays (and later 3x displays) which effectively squeezed two and three times
as many pixels into a given area per legacy displays (thus capable of displaying
higher resolution images).
This last point is important. The interplay between the resolution of a given
image and that of the display impacts the decision to render images for web use
in that it doesn't help to have a very high resolution image if the display
resolution is far inferior to that of the image. In such cases, *scaling down*
an image from its native resolution would be in order.
Conversely, images with low native resolution relative to target displays
should be given careful consideration so as to avoid rendering overly-pixelated
images. In such cases, a smaller image size (thus higher resolution) can help
offset such undesirable effects.
To summarize:
<div><pre class="code">
1). Scale down ultra high-res to target display res
2). CSS-constrain max-image size limits for low res images
</pre></div>
The overriding dominant solution, of course, is to use the highest resolution
possible/appropriate for given the image's resolution and the display's
capability.
### Viewport Sizes and Responsive Design
The task of resizing an image given the foregoing discussion raises the
question as to what image sizes should be produced. This depends, in turn,
on the size of the display (or viewport) which is handling/displaying the
image.
Whereas picture resolution, as discussed above, is a function of the display's
pixel density, the question of resizing an image is predicated on the pixel
size of the displaying viewport which can be conveniently referenced using
the shorthand measure of viewport display widths.
Naturally, there are a wide variety of devices all sporting their own viewport
widths on the market, but these can be generally classed into the following
pixel-width categories (widths shown in upper bounds, inclusive):
mobile phone: ~479 px
tablets-medium: ~767 px
tablets-large: ~991 px
desktops: ~1199 px
If an image were to take up the entire width of a device's viewport, these
would be the *very rough* guidelines according which images could be sized
(and for which image widths should be sized smaller than these measures).
However, unless every image is being used as some sort of *hero* on a page,
it's highly likely that the image will be substantially smaller than these
widths. As such, viewport sizes are typically used as inputs into the
*responsive design* approach to building websites, serving as breakpoints
used in media queries.
The assumption of using responsive design, together with the principal of
*mobile first* development when it comes to building websites, is an overarching
one - but one which we presume is a *good* approach, in keeping with best
practices in page layouts and design. As such, we leave aside any discussion
of the pros and cons of responsive website design and simply take it as our
goal, here.
Over time, the setting of media query breakpoints for responsive images in
websites has evolved from the approach of matching them to the miscellany of
device display widths to the common practice today of allowing *site content*
to dictate appropriate breakpoints - mindful of broad categories of "standard"
viewport widths such as those listed above.
[Note: If you're using a responsive CSS framework like Bootstrap, helpful
guidelines on viewport widths and media queries can be found [here](http://getbootstrap.com/css/).
I also find [Viewport sizes](http://viewportsizes.com/) to be helpful reference for devices and their
viewport widths, if you need that level of detail.]
### HTML to the rescue: picture element and srcset attribute
In an effort to better match client-side requirements with server-side
deliverables, we are lucky to have the html picture element and associated
srcset tag, at least for browsers which support them (see [this](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/picture#Browser_compatibility) for a list
of compatible browsers).
For browsers which fully support these, not only are we able to ascertain
information regarding client-side viewport widths in which our images are
being displayed, we are also able to deliver the appropriately *processed*
image to the client (which we take to mean the best possible quality subject
to the client-side constraints communicated back to the server via this
information). As such, these HTML features play a critical role in optimizing
the delivery of images to the client.
An example of a picture element with srcset tags is as follows:
```
<picture>
<source media="(min-width: 1000px)" srcset="mypic_large_1x.jpg 1x, mypic_large_2x.jpg 2x">
<source media="(min-width: 500px)" srcset="mypic_medium_1x.jpg 1x, mypic_medium_2x.jpg 2x">
<img src="mypic_small.jpg" alt="The mypic">
<picture>
```
As can be gleaned from this entry, a media-query is used in the source
attribute of the picture tag, delineating the viewport breakpoints. This way,
we can vary the deliverable image given the viewport width information that is
communicated back to the server.
The corresponding image source is then set using the srcset tag, which is very
convenient. As can be seen from this example, descriptive filenames delineate
image sizes which, if they have undergone an optimization process involving
scaling/cropping, resolution, and compression treatments as discussed above,
go a long way toward satisfying our optimization goal we stated in the
introduction.
Further note that the srcset attribute allows for a resolution specifier.
The suffixes '1x' and '2x' are pixel density multipliers. Thus, if the browser
communicates back that the image is being displayed on a Retina display, for
example, we can send back the higher-density 2x resolution image (which we
ordinarily would *not* want to do with standard/non-Retina displays).
Finally, the picture element has the img fallback tag for browsers which may
not support the picture element.
[More on the picture element see [here](https://www.w3schools.com/tags/tag_picture.asp).
For browsers which do not support the
picture element, a generic picture polyfill may serve as a workaround.]
### Conclusion: Putting it all together
A lot of background information has been reviewed above. It's time to tie
it all together.
In so doing, let us restate our goal for reference:
#### ***To deliver the best image quality in the most efficient manner possible.***
and rephrase this to a working version as follows:
#### ***To deliver the highest quality conforming image at the smallest possible file size.***
By *conforming image* we take this to mean an image appropriate to client-side
conditions which includes features such as resolution/pixel density and viewport
size, as discussed above.
<br>
Let us also list our **working assumptions**:
1). Mindful of various image file format qualities and the characteristics of
lossy format images, we mind the quality chain and produce deliverable images
rendered from a high-quality (or highest available quality) master.
<br>
2). We accept responsive design (and thus the use of responsive images) as our
operating framework.
<br>
With the practical considerations/discussions referenced above, the following
would serve as a reasonable set of steps in preparing images for web use:
<br>
<div><pre class = "code">
<b>1). Whenever possible, start from a high-quality master. </b>
a). If the image is a RAW camera image, convert it to TIFF first.
b). If the image is neither of these, use a PNG or some other lossless
format of the image and derive all processed children from this master.
1). Note that this holds for masters in JPEG/JPG lossy formats, too. (*)
c). Separate source masters from processed children. (**)
<b>2). Produce responsive images with responsive design in mind.</b>
a). Decide on your content and breakpoints and the corresponding image
sizes you need to produce (e.g.: 1 for mobile, 1 tablet, 1 desktop, etc.).
b). Make note of your image resolutions and desired target viewport
resolutions.
c). Note the visual complexity of your images (i.e., how detailed are they?)
<b>3). Decide on a rendered file format.</b>
a). If it's a simple logo, go with an SVG and forget the overhead that
comes with raster image processing.
b). If you're reasonably confident your content will be viewed via Chrome
or some WEBP-compatible browser, go with WEBP (best quality for the size).
c). If none of the above, go with the common fallback 'JPG'.
<b>4). Apply preliminary renderings</b>
a). This includes things like cropping images where appropriate - mindful
to save these in lossless format before further processing.
<b>5). Process (rescale, convert and compress) your images.</b>
a). Use the high quality master (or pre-rendered equivalent from above)
as your source for each renderable image.
b). Resize images to desired dimensions given the responsive layout and
associated breakpoints you have in mind. (***)
c). If rendering images in JPG or some other lossy format, decide what
level of compression is acceptable given the visual complexity of the image.
1). More detailed images can stand up to higher compression as the
naked eye does not notice loss of detail as easily with simpler images
like broad sunsets/landscapes.
d). If applicable/possible, produce density-variant images (e.g., 2x or 3x
renderings for high-resolution displays).
<b>6). Use the picture element and associate image source sets (srcset) tags</b>
a). Source your images when possible in these elements in your html to
deliver the appropriately rendered image to the target viewport
and display resolution.
<b>7). Exercise CSS max-width contraints</b>
a). Where applicable, add a max-width constraint to your CSS for
low-resolution images to prevent them from becoming pixelated after a
certain width.
_______________________________________________________________________________
<div class="footnote">
*For safekeeping, I find it's good practice to convert lossy masters to
lossless PNG to serve as a master. Obviously, this will not result in
an image file that's any better than the source JPG, but this way I have
a lossless master/backup I can use in case I should overwrite the lossy
version (which, for JPGs, results in successive degradation with each
save).
**In other words, in your working environment, keep a source folder,
say 'img_src' for masters and a default 'img' for sourced images where
processed children are saved.
***While this was not mentioned before, it's generally assumed that image
dimensions are kept at their original to avoid distortion (unless, of course,
this is meant to happen).
</div>
</pre></div>
<br/>
Most/all of the actual image processing tasks (file format conversion,
rescaling, compression) are made possible by modern graphics applications of
which [ImageMagick](http://www.imagemagick.org/script/index.php) and its offshoot [GraphicsMagick](http://www.graphicsmagick.org/) are popular.
Often, such tasks end up being integrated into either a [gruntified](https://gruntjs.com/) or [gulpified](http://gulpjs.com/)
workflow (though traditionally, I have used my own sets of bash wrappers around these
engines and their convenient command line interfaces).
### Summary
Image file sizes often make up a sizeable chunk of a given website's *page
weight*.
As a result, the proper rendering or optimization of images for website use is
often a key part of the eternal quest to reduce page weight and increase the
speed of a given site to improve user experiences.
In addition to local testing options such as the network throttling features
which come with Chrome's Developer Tools, Google's [PageSpeed Insights](https://developers.google.com/speed/pagespeed/insights/)
is one of many resources developers have at their disposal in evaluating
their website's efficiency.
When it comes to the image preparation part, I hope this set of stylized
rules/principles helps to serve as a guide to the use of images in websites.