Proper image handling in web and mobile applications is critical to performance, therefore to user experience.
The Problem with Images
Image handling in frontend development is problematic in a number of ways:
Caching
Image caching is an absolute requirement in frontend development otherwise each reload will re-download all images.
Caching is simple in theory, but uncertain in practice: one can’t really be sure that all requested images are cached properly especially when dealing with images from different domains/sources (own domain fixable, CDNs are reliable, but what about the rest?)
Optimization
Images should be delivered in the optimal supported format and size:
- image format should be adapted to browser support
- e.g. send WebP when it is supported, otherwise send PNG or JPG
- image size should be adapted to display size which usually depends on viewport
- image file should be compressed losslessly
Current observed practices regarding these matters are questionable and impractical: having multiple versions of each image in different formats/sizes, and choosing image format and/or size from frontend.
Processing
Image processing, even though doable and even performant in some case, is not the job of a frontend application.
Introducing Thumbor
Thumbor is a smart imaging service. It enables on-demand crop, resizing and flipping of images. It features a very smart detection of important points in the image for better cropping and resizing, using state-of-the-art face and feature detection algorithms.
Thumbor provides a comprehensive features set: image upload, storage, retrieval, caching, and processing (crop, resize, flip, filter).
It comes with a set of plugins (AWS S3, MongoDB, …) and libraries (JavaScript, Python, Ruby, …) adding more features and enabling flexible integration.
Thumbor is installed as pip
package (pip install thumbor
), executed in CLI as thumbor
, and used as following:
http[s]://THUMBOR_SERVER/[HMAC|unsafe]/OPTIONS_1/OPTIONS_2/OPTIONS_3/.../IMAGE_URI
Example
Original Image
https://raw.githubusercontent.com/wiki/thumbor/thumbor/logo-thumbor.png
Resized Image
http://localhost:8888/unsafe/fit-in/200x100/https://raw.githubusercontent.com/wiki/thumbor/thumbor/logo-thumbor.png
Resized and Blurred Image
http://localhost:8888/unsafe/fit-in/200x100/filters:blur(4)/https://raw.githubusercontent.com/wiki/thumbor/thumbor/logo-thumbor.png
Proposed Solution
Use Thumbor as intermediate image server for optimal image handling:
- caches by default (configurable)
- all processing should be done by Thumbor (crop, resize, filter, …)
and request images with exact display size in frontend:
- varies from simple (viewport width minus container margin/padding) to tricky (requires some clever code with DOM node width measure, still doable)
- common frontend framework filter feature is useful to construct Thumbor URL from original image URL (
<img src="{{ imgSrc | thumborize }}">
, withthumborize
a custom filter)