1. Overview
There are occasions when we need to convert an image from one format to another. It could be to reduce the file size or meet specific format requirements for a particular purpose.
In this tutorial, we’ll check how we batch convert a set of files from one format to another.
2. Using the mogrify Command
To convert images from one format to another, we can use the mogrify command. This is an excellent tool from ImageMagick for all our image manipulation needs. Apart from format conversions, it also supports cropping, resizing, blurring, flipping, joining, and many more operations on image files.
The usage is:
mogrify [options] input-file
Let’s convert PNG files to JPG format:
$ ls
Tracks1.png Tracks2.png
$ mogrify -format jpg *.png
$ ls
Tracks1.jpg Tracks1.png Tracks2.jpg Tracks2.png
$ file Tracks1.jpg
Tracks1.jpg: JPEG image data, JFIF standard 1.01, aspect ratio, density 1x1, segment length 16, baseline, precision 8, 800x718, frames 3
As seen above, we’ve got a couple of PNG files. Then we ran the mogrify command over them. In that command, we’ve used the -format option to specify the output format as JPG. As a result, we can see the newly created JPG files. Also, by using the file command, we’ve verified that the resulting file is in JPG format.
Typically, the mogrify command edits the files in place. Hence, it is always recommended to backup the existing files before running this command.
3. Using the convert Command
Similar to the mogrify command, the convert command also supports different image processing techniques. This is yet another tool from ImageMagick.
While the mogrify command edits the files in place, the convert command puts the result in a new file.
Usage is:
convert [input-options] input-file [output-options] output-file
Let’s see this command in action:
$ convert *.png Tracks.jpg
$ ls
Tracks-0.jpg Tracks-1.jpg Tracks1.png Tracks2.png
$ file Tracks-0.jpg
Tracks-0.jpg: JPEG image data, JFIF standard 1.01, aspect ratio, density 1x1, segment length 16, baseline, precision 8, 800x718, frames 3
In the above command, we took all the PNG files as input. And for the output, we’ve mentioned a filename with a jpg extension. With this, it’ll create new JPG files with Tracks as prefix and a number starting from zero as the suffix.
As a result, we can see the newly created JPG files with different filenames. And using the file command, we’ve confirmed that the newly generated files are in JPG format.
From the fact that the mogrify command edits the files in place, it is more efficient and better suited for batch processing.
On the other hand, the convert command reads all files in the input to memory and does the processing. Thus, if we’re running the command from a directory with lots of files, it can cause memory issues.
However, the convert command is more versatile in allowing us to specify a different destination or filename for the output. Furthermore, it is better for handling multiple images for composition and animations.
3.1. Converting to GIF Format
If we use the above command to convert the image file to GIF format, it’ll take all the PNG files in the folder and create a single GIF file. For most of the scenarios, this is expected. But sometimes, we might need to convert each PNG file to a separate GIF file.
With this, we’ll also see the name mangling capability of the convert command, which is essential during a batch operation.
Let’s check that:
$ convert *.png -set filename:fn '%t' +adjoin '%[filename:fn].gif'
$ ls
Tracks1.gif Tracks1.png Tracks2.gif Tracks2.png
$ file Tracks1.gif
Tracks1.gif: GIF image data, version 89a, 800 x 718
As we can see in the above results, it has created separate GIF files.
Let’s check the different options we’ve used:
- -set: to specify a setting
- filename: we’re doing a filename setting. This is finally used to create the output filename
- fn: a label for identification
- %t: this stands for the filename without extension
- +adjoin: this option creates a separate filename for each input file
- %[filename:fn].gif: this is the percent escape to generate the final GIF filename
So far, we’ve seen the different ways to use either the mogrify command or the convert command to change the format. If we combine these with other commands in Linux, it will become more flexible in handling files. Also, using the Bash commands save us some time from learning the intricacies of the convert command.
Let’s quickly look at a few of them.
3.2. Using the for Loop
Let’s check how we can do a batch conversion using the for loop:
$ for f in *.png ; do convert "$f" "${f%.*}.jpg" ; done
$ ls
Tracks1.jpg Tracks1.png Tracks2.jpg Tracks2.png
In the above command, we’ve iterated through all the PNG files. Then we passed the files one by one to the convert command. Finally, we got all the files converted to JPG format.
3.3. Using the ls Command
We can execute batch conversion using the ls command in combination with the xargs command.
Let’s take a look at it:
$ ls -1 *.png | xargs -n 1 bash -c 'convert $0 "${0%.*}.jpg"'
$ ls
Tracks1.jpg Tracks1.png Tracks2.jpg Tracks2.png
We can see the JPG files are created properly from the above results.
3.4. Using the find Command
Next, let’s check how we can use the find command:
$ find . -name '*.png' | xargs -n 1 bash -c 'convert $0 "${0%.*}.jpg"'
$ ls
Tracks1.jpg Tracks1.png Tracks2.jpg Tracks2.png
This is very similar to the above command. Instead of the ls command, we’ve used the find command to pick up the files.
3.5. Using the parallel Command
Whenever we’ve to execute something in batch, the parallel command comes in handy.
$ ls -1 *.png | parallel convert '{}' '{.}.jpg'
$ ls
Tracks1.jpg Tracks1.png Tracks2.jpg Tracks2.png
Here also, we can see the newly created JPG files.
4. Using FFMpeg
Finally, let’s use FFMpeg for converting PNG files to JPG format. As we know, the FFMpeg is used for performing various multimedia tasks. Using this, we can convert images from one format to another.
Let’s run it:
$ for i in *.png ; do ffmpeg -i "$i" "${i%.*}.jpg" ; done
$ ls
Tracks1.jpg Tracks1.png Tracks2.jpg Tracks2.png
$ file Tracks1.jpg
Tracks1.jpg: JPEG image data, baseline, precision 8, 800x718, frames 3
Here, we’ve used a for loop to iterate through the files. Then, we’ve passed the files one by one to the ffmpeg command. Finally, the ffmpeg command converts them to JPG format since we’ve given jpg as the output filename extension.
5. Changing the Quality of Images
In this section, we’ll learn how to change the quality of images using the convert and mogrify commands.
5.1. Using convert
PNG files give lossless compression, so we’ll not notice a visible difference if we change the quality of such files. So, let’s take JPEG files for our use case:
$ ls -latrh sample_{1,2}.jpeg
-rw-r--r-- 1 root root 87K Aug 17 03:15 sample_1.jpeg
-rw-r--r-- 1 root root 327K Aug 17 03:15 sample_2.jpeg
Now, let’s use the -quality option to reduce the quality of the sample files to 60% of their original quality:
$ convert -quality 60% '*.jpeg' \-set filename:original "%t" "%[filename:original]_compressed.jpeg"
It’s worth noting that we used the -set option to save the original filename attribute without extension as the filename:original attribute. Later we used it to form the prefix for the filename of the compressed file.
Lastly, we can verify that the images are indeed compressed:
$ ls -latrh sample_{1,2}_compressed.jpeg
-rw-r--r-- 1 root root 41K Aug 17 03:52 sample_1_compressed.jpeg
-rw-r--r-- 1 root root 147K Aug 17 03:52 sample_2_compressed.jpeg
Great! We got this one right.
5.2. Using mogrify
Like earlier, let’s take JPEG files as our sample files:
$ ls -latrh sample_{1,2}.jpeg
-rw-r--r-- 1 root root 327K Aug 17 03:57 sample_2.jpeg
-rw-r--r-- 1 root root 87K Aug 17 03:57 sample_1.jpeg
Next, let’s use the -quality option to reduce the quality of these files:
$ mogrify -quality 60% *.jpeg
We must remember that mogrify edits the file in place. So, we aren’t specifying the output filenames explicitly.
Finally, let’s check the size of the images after compression:
$ ls -latrh sample_{1,2}.jpeg
-rw-r--r-- 1 root root 41K Aug 17 03:57 sample_1.jpeg
-rw-r--r-- 1 root root 147K Aug 17 03:57 sample_2.jpeg
The result looks as expected.
6. Conclusion
In this tutorial, we’ve seen the different ways to batch convert image files from one format to another.
As we’ve seen, the convert command can handle all the required conversions. Combining this with the Bash commands gives us more control over the conversion process.