📜 ⬆️ ⬇️

Effective resizing of images using ImageMagick

Nowadays, more and more sites are faced with the need to introduce responsive design and responsive pictures - and in this regard, there is a need to effectively change the size of all pictures. The system should work so that each user can send a picture of the desired size upon request - small for users with small screens, large ones for large screens.

The web works fine this way, but to deliver pictures of different sizes to different users, you must first create all these pictures.

Many tools are involved in resizing, but too often they give out large files that invalidate the performance gain that should come along with responsive pictures. Let's take a look at how using ImageMagick , a command-line tool, to quickly resize images while maintaining excellent quality and getting files of small sizes.
')

Big pictures == big problems


The average web page weighs 2 MB , of which 2/3 are pictures. Millions of people go to the Internet via 3G, or worse. 2MB sites in these cases work terribly. Even on a fast connection, such sites can use up traffic limits. The work of web designers and developers is to simplify and improve the user's life.

image

Very small sites can simply save several versions of all the pictures. But what if you have them dofiga? For example, there may be hundreds of thousands of pictures in a store - do not manually make their variants.

Imagemagick


The command line utility with 25 years of experience is at the same time a full-featured image editor. It has a huge pile of features, and among them is a quick and automatic resizing of images. But with the default settings, files are often overly large — sometimes larger in size than the original, although they have fewer pixels. Now I will explain what the problem is and show you what settings are needed to solve it.

How image size resizing works


By definition, when the image is resized, the number of pixels in it changes. If it is increased, there will be more pixels at the output than at the input; when decreasing - the opposite. The challenge is how best to preserve the contents of the original image with a different number of pixels.

Zooming in on pictures is easier, so let's start with it. Consider a picture with a square of 4x4 pixels, which we want to double to 8x8. In fact, we take this picture and pull on a new grid - this is called resampling (discretization). To do a 4x4 picture at 8x8, you need to insert 48 extra pixels somewhere. They must have some color - the process of its selection is called interpolation. When sampling, an algorithm that chooses how interpolation works is called a sampling filter.

image

There are many such filters. The easiest way to add four rows and four columns of any color. Well, let's say red. This will be the background interpolation when the background color (red) appears on the empty places. In Photoshop, this is done via “Image” → “Canvas Size” instead of “Image” → “Image Size”.

This, of course, does not suit us. The picture will not be similar to the original. Background interpolation is used only to add new pixels, and even then it is useless when resizing.

image

Another simple interpolation is to make the color of the new pixels the same as their neighbors - this is the interpolation of the nearest neighbors. For pictures, especially for our square, the result will be much better.

image

When downsampling, that is, reducing the picture, it is not so easy to interpolate the nearest neighbors. It is necessary to accept that for mathematical purposes it is possible to operate with fractional pixels. To begin with, a new grid is applied to the original picture. Since the pixels are smaller and their size is larger, some of them contain several colors.

But real pixels have only one color. The resulting color of each pixel of the new grid is determined by the color of its center. Therefore, sometimes the interpolation of the nearest neighbors with decreasing is called point discretization.

image

But if it is something more complicated than lines and squares, this method produces jagged and square pictures. It works quickly, produces small files, but it looks bad.

Most filters use interpolation variations on their nearest neighbors — they do point sampling on several points and somehow calculate a certain average color for them. In bilinear interpolation, a weighted average of colors is considered.

image

But such a filter affects the file size, because it adds new colors along with rounded edges. The original picture had only two colors, but now we have more of them. And other things being equal, the more colors, the heavier the file.

And what does this mean for us

We need to somehow reduce the number of colors without losing quality. Most influenced by the choice of filter, but other settings too.

Optimal settings for ImageMagick


ImageMagick Basics

ImageMagick doesn't have settings and functions , and finding the one you need is pretty hard. We are interested in two functions, convert and mogrify. They perform similar actions, but mogrify works with several files at once, and convert - one at a time.

Simple operation:

convert input.jpg -resize 300 output.jpg 


At the same time, IM takes input.jpg and changes its size by pixels wide, saving the result in output.jpg. The -resize 300 function is an example of one of a variety of functions. They all have the same format: -functionName option.

You can also use mogrify, with a small addition:

 mogrify -path output/ -resize 300 *.jpg 


Here IM takes all the JPEG files from the current directory (* .jpg), changes their size to 300 pixels wide and stores them in the output directory.

Functions can be combined:

 convert input.jpg -resize 300 -quality 75 output.jpg 


This also changes the size of input.jpg to 300 pixels, but sets the JPEG quality to 75 before saving to output.jpg.

Testing and results

By testing various IM settings, I tried to reduce the size of the files without compromising their quality - so that they could not be distinguished from the Photoshop option “Save for Web”. I used to test both subjective opinion and objective, measuring structural differences (structural dissimilarity, DSSIM). DSSIM compares two pictures and gives a rating. The lower the score, the more they are similar. 0 means identity. I sought a DSSIM score of no more than 0.0075. And in one of the studies last year, it was found that usually people cannot distinguish by eye pictures with DSSIM less than 0.015.

Having tested various images of different sizes in JPEG and PNG formats, I came to the conclusion that the following IM settings produce the lowest results, which are almost indistinguishable from the output of Photoshop:

 mogrify -path OUTPUT_PATH -filter Triangle -define filter:support=2 -thumbnail OUTPUT_WIDTH -unsharp 0.25x0.25+8+0.065 -dither None -posterize 136 -quality 82 -define jpeg:fancy-upsampling=off -define png:compression-filter=5 -define png:compression-level=9 -define png:compression-strategy=1 -define png:exclude-chunk=all -interlace none -colorspace sRGB -strip INPUT_PATH 


We analyze them in more detail.

Mogrify or Convert

IM uses convert to process images one by one, and mogrify is usually needed for batch processing. In an ideal world, the results of their work must coincide. Unfortunately, there is an error in convert that makes it ignore some of the settings (-define jpeg: fancy-upsampling = off), so I had to use mogrify.

Resampling

The selection of the sampling filter in IM is somehow confusing. There are three ways to do this:



image
Work examples of twelve different resizing functions.

The most obvious is to use –resize, but the results are too large. I checked 11 different functions and found that it’s best to reduce –thumbnail, both in size and quality. This feature works in three steps:

  1. Resizes a picture to a size that is five times larger than what you need, using the –sample function, which has its own built-in filter
  2. then resizes to the required through –resize
  3. removes meta data from image


That is, if we reduce the image to 500 pixels wide, -thumbnail will first change its size to 2500 using –sample. Then IM will change the size from 2500 to 500 via –resize. And at the end will delete the meta data.

The second way to select a sampling filter is via –filter. Some features have built-in filters, while others have default filters that can be changed. In the second step of working –thumbnail, –filter is used, because the –resize function is used there.

I checked 31 settings for –filter and achieved the best results using Triangle. This filter is also known as bilinear interpolation. It calculates a weighted average color from neighboring pixels. I found it best to set the region of neighboring pixels as -define filter: support = 2 setting.

The third way to select a filter is –interpolate, but it is ignored when using -thumbnail.

Among other things, IM by default uses a certain function called JPEG fancy upsampling, which tries to produce better quality JPEG. I decided that it only increases the size of the pictures, and the difference in quality is negligible, so I recommend turning it off via -define jpeg: fancy-upsampling = off.

Sharpening

When you change the size of the image is slightly blurred, so the same photoshop uses different techniques to increase the definition. I recommend the unsharp filter, which, despite the name, increases the clarity of the picture: -unsharp 0.25x0.25 + 8 + 0.065.

The filter works in such a way that Gaussian blur is applied first. The first two numbers are the radius and sigma (in our case, 0.25 pixels each). After the blur, the filter compares the blurred version with the original, and where the brightness differs more than the specified threshold (0.065), an increase in the definition of the specified force (8) is applied.

Color reduction

As I said earlier, the main reason for the increase in file size when changing the size of pictures is the addition of new colors. Therefore, we must try to reduce their quantity, but without loss of quality.

One way to do this is posterization (posterization), when gradients are replaced with sets of crisp colors. Posterization reduces the number of levels of color - this is how many options remain in the red, green and blue channels. The total number of colors of the picture will be a combination of the colors of these channels.

Posterization can reduce the file size, but also degrade the quality. I suggest the number 136, at which you get a small file, without losing much in quality.

image
Original

image
Reducing the number of colors

Dithering is a process that mitigates the effects of reducing the number of colors by adding noise to color sets to create the illusion of more colors. In theory, this is a good idea.

image
After dithering

Unfortunately, in IM there is an error that spoils the pictures with transparency in dithering. Therefore, it is better to disable it through -dither None. Fortunately, without it, the posterization results look good.

image
Dithering error in IM

Color space

Color space is indirectly related to the number of colors in the picture. This space determines which colors are available. The picture below shows that the ProPhoto RGB color space contains more colors than Adobe RGB, which in turn contains more than sRGB. And they all contain less flowers than the eye sees.

image

sRGB made the king of internet color spaces. He was approved by the W3C and other organizations. It is required to support in CSS Color Module Level 3 and in the specifications of SVG and WebP. It is referenced in the PNG specification. In Photoshop, this is also the default color space. In short, sRGB is the best choice for the web, and if you want your images to display correctly, it’s best to use it.

Quality and Compression

In lossy formats like JPEG, quality and compression are directly related - the greater the compression, the lower the quality and the smaller the file size. Therefore, you need to find a balance.

In my tests for control images and photoshop, the quality was set to high, or 60. And in the IM settings, I recommend using 82. Why?

It turns out that the quality setting is not quantified in JPEG format, and therefore it is not a standard. Quality 60 in Photoshop can be the same as quality 40 in one program, B + quality in another, or “awesome” quality in the third. In my tests, I found out that Photoshop 60 corresponds to -quality 82 in ImageMagick.

And for formats without loss of quality like PNG, quality and compression are not related. High compression does not change the look of the picture, but depends only on the level of CPU usage during its processing. If you do not feel sorry for computers, then there is no reason not to set the maximum PNG compression.

PNG compression in IM can be set in three settings: -define png: compression-filter, -define png: compression-level and -define png: compression-strategy. The compression filter is an extra step before compression, which sorts the data in such a way that compression becomes more efficient. I achieved better results using adaptive filtering (-define png: compression-filter = 5). I recommend setting the compression level to a maximum of 9 (-define png: compression-level = 9). And the strategy determines the algorithm itself. I liked the default strategy more (-define png: compression-strategy = 1).

Meta data

In addition to the picture itself, files may contain meta data — information about the picture, when it was created, about the device that created it. This information takes place, but does not improve the perception of the picture, and it is better to delete it. And although I have indicated that –thumbnail deletes meta data, it still doesn’t delete them all. It is possible to delete everything using -strip and -define png: exclude-chunk = all. This does not affect the quality.

Progressive render

JPEGs and PNGs can be saved using progressive (progressive) or sequential (sequential) rendering. By default, the second one is executed, when pixels are loaded in rows, from top to bottom. Progressive means that the picture is transmitted and output gradually.

JPEG progressive render can occur in any number of steps - this is determined when saving the file. The first step is the low resolution version of the full image; on each subsequent version of a higher resolution appears, until the entire picture in high resolution is displayed.

image

PNG has a kind of progressive rendering called Adam7 interlacing , where pixels are displayed in seven steps based on an 8x8 grid.

image

Both types of render can be configured in IM through –interlace. But is it necessary?

This render increases the size of files. For a long time it was thought that it should be included, because it improves user perception. Even if the ideal picture does not load right away, it recognizes something, and it will be better than nothing.

Last year, according to the results of the study, it became clear that users prefer a consistent render. This is only one study, but still interesting. So I decided to recommend using a sequential render using "-interlace none".

Image Optimization

I mentioned optimization. I recommend all the settings described before, if you do not optimize your pictures. If they can be optimized, then I will change them: small changes in the -unsharp settings work better (-unsharp 0.25x0.08 + 8.3 + 0.045 against -unsharp 0.25x0.25 + 8 + 0.065 without optimization) and do not need to use -strip.

 mogrify -path OUTPUT_PATH -filter Triangle -define filter:support=2 -thumbnail OUTPUT_WIDTH -unsharp 0.25x0.08+8.3+0.045 -dither None -posterize 136 -quality 82 -define jpeg:fancy-upsampling=off -define png:compression-filter=5 -define png:compression-level=9 -define png:compression-strategy=1 -define png:exclude-chunk=all -interlace none -colorspace sRGB INPUT_PATH 


There are plenty of optimizers. I tested image_optim , picopt and ImageOptim , and they all chase the pictures through a series of different steps. I checked them one by one and came to the conclusion that it is better to run the files through all three in the order in which they are given. However, after using image_optim, the benefit from picopt and ImageOptim becomes minimal. If you do not have extra time and processor power, the use of more than one optimization will be excessive.

Results (and what, it was necessary to suffer so?)


Of course, my settings are complicated, but they are needed to improve user perception. I am pleased to announce that having spent time on tests, I managed to drastically reduce the volume of files without losing in quality.

On average, the file size has decreased by 35% compared to the “Save for Web” Photoshop option.

Comparison with Photoshop Creative Cloud


My settings without optimization turned out to be even better than Photoshop with optimization!

Compared to the default settings when changing the size of IM images, my recommendations won an average of 82%.


Compared to the default settings in WordPress, which “under the hood” uses ImageMagick, my settings won on average 77%.


Compared to other CMS and tools that use ImageMagick, my settings won up to 144%.


I remind you that all the pictures turned out to be indistinguishable from Photoshop output.

How to implement it in your projects


bash shell

Here you can add a macro function to the .bash_aliases (or .bashrc) file, which will replace my recommended command:

 smartresize() { mogrify -path $3 -filter Triangle -define filter:support=2 -thumbnail $2 -unsharp 0.25x0.08+8.3+0.045 -dither None -posterize 136 -quality 82 -define jpeg:fancy-upsampling=off -define png:compression-filter=5 -define png:compression-level=9 -define png:compression-strategy=1 -define png:exclude-chunk=all -interlace none -colorspace sRGB $1 } 


And you need to call it like this:

 smartresize inputfile.png 300 outputdir/ 


Node.js

The npm package called imagemagick allows you to use ImageMagick. When using it, you can add a resizing function as follows:

 var im = require('imagemagick'); var inputPath = 'path/to/input'; var outputPath = 'path/to/output'; var width = 300; // output width in pixels var args = [ inputPath, '-filter', 'Triangle', '-define', 'filter:support=2', '-thumbnail', width, '-unsharp 0.25x0.25+8+0.065', '-dither None', '-posterize 136', '-quality 82', '-define jpeg:fancy-upsampling=off', '-define png:compression-filter=5', '-define png:compression-level=9', '-define png:compression-strategy=1', '-define png:exclude-chunk=all', '-interlace none', '-colorspace sRGB', '-strip', outputPath ]; im.convert(args, function(err, stdout, stderr) { // do stuff }); 


Grunt

If you use Grunt to run tasks, then especially for you I did a task called grunt-respimg ( npm ), which does everything I described. You can include it in your projects like this:

 npm install grunt-respimg --save-dev 


And then it can be done in the Grunt file:

grunt.initConfig({
respimg: {
default: {
options: {
widths: [200, 400]
},
files: [{
expand: true,
cwd: 'src/img/',
src: ['**.{gif,jpg,png,svg}'],
dest: 'build/img/'
}]
}
},
});
grunt.loadNpmTasks('grunt-respimg');


Php

In PHP, ImageMagick is integrated under the name Imagick . Unfortunately, there it is limited and does not know how to do everything that I recommended - in particular, to configure the sampling filter to use the thumbnail function.

But you were lucky - I created a php-respimg ( packagist ) module that does everything necessary. It can be included in the project using Composer :

 composer require nwtn/php-respimg 


And then change the size of the pictures like this:

 require_once('vendor/autoload.php'); use nwtn\Respimg as Respimg; $image = new Respimg($input_filename); $image->smartResize($output_width, 0, false); $image->writeImage($output_filename); 


Content Management Systems

If your CMS works in PHP, take the “PHP” section and make a plugin out of it. If you are using WordPress, then you can use the RICG Responsive Images plugin. After installing it, you will need to add the following to the functions.php file to activate it:

 function custom_theme_setup() { add_theme_support( 'advanced-image-compression' ); } add_action( 'after_setup_theme', 'custom_theme_setup' ); 


Other CMS somehow give access to functions for working with pictures - refer to their documentation.

Speed ​​performance


In my tests, I found that, compared to –resize, by default IM took 2.25 times longer to process images.

Conclusion


Designers and developers greatly influence how the web works. We can make websites more nimble, improve their perception by users, and even bring our content to new markets . Reducing the volume of images is quite simple and greatly affects the increase in site performance - I hope that all this information will be useful for you and allow you to improve your website for your users.

Links


grunt-respimg
php-respimg
RICG Responsive Images plugin

Source: https://habr.com/ru/post/261625/


All Articles