Protect Your Privacy with ImageMagick
Tutorials – ImageMagick
Ben Everard wants to keep his location open, but only vaguely.
The ImageMagick tool lets you do almost everything you would want to with an image. You can tweak, poke, prod, and otherwise meddle with pixels (Figure 1). In this tutorial, we'll look at how to use this tool to form a command that can help protect our privacy online. This is also the perfect excuse to see how we can use the Linux terminal to build up a complex, powerful command from many smaller commands.
When you take pictures on a digital camera, a whole lot of information is stored along with the actual image. The exact information varies from camera to camera but might include things like the camera settings and location at which the picture was taken. This information is all useful until you start sharing the images online, at which point it can be used to trace exactly where you've been. Many tools will just remove the location data, but we want to be a little more clever. We want to keep the general area the picture was taken but remove the precision. We want a command that embeds the location to the nearest town. Rather than put this information in hard-to-read metadata, we want the info displayed in the image itself as a caption at the bottom. This can be done as shown in Listing 1.
Listing 1
Embed Location
Obviously, this command is a little complex, but don't worry. It's made up of lots of smaller bits that are all easy to understand. Let's break it down and look at it bit by bit. The two basic building blocks of this command are the pipe (|
) and command substitution ($())
. The pipe sends the output of one command to another. In some cases, we use this to send text from one command to the next; in other cases, we're sending images. Command substitution runs the command inside the brackets and inserts the text that the command outputs in the place of the dollar sign.
Let's first look at the command substitutions.
$(identify -format '%w' IMG_20170504_191133.jpg)
This uses the identify
command (part of ImageMagick, so you might need to install this package via your package manager) to extract the width of the image. To test this command substitution, run it without the first dollar sign or opening and closing brackets. Obviously, you'll need to change the image name to an image you have.
The second command substitution is a little more complex (Listing 2).
Listing 2
Second Command Substitution
This itself contains a command substitution:
$(exiftool IMG_20170504_191133.jpg -n | grep 'GPS Pos' | cut -d ':' -f2 | cut -f2,3 -d" " | tr " " ",")
exiftool
gets the metadata out of the image (we could use identify
, but exiftool
is better for formatting the GPS data in the way we need). The metadata is then piped to grep
, which discards all of it other than the data that matches "GPS Pos" – the latitude and longitude. A pair of cut
commands are used to first get everything after the colon, and then get the second and third fields (when separated by a space). This gives us the latitude and longitude with a space between them. But, as you'll see in a minute, we need them separated by a comma, so the final part of this subcommand is tr
, which just replaces every space (and there is only one) with a comma.
Now, let's go back to the outer command substitution (Listing 3).
Listing 3
Outer Command Substitution
As you can see, we've put 1.0000,1.0000 where the previous command placed the latitude and longitude of the picture. The first part of this pipe uses the Google Maps API to get the closest address for this latitude and longitude in JSON format. By default, you're limited to 2,500 daily requests from the API, so if you have a lot of images, you may need to spread them out over several days.
We then use the jq
command (which you may need to install via your package manager) to get the data we want out of this. The format for jq
is a language in itself, but what we do is get the first item in the results list, and then loop through the address_components
list inside this item. If the address_components
item has a type of country or town, output the long_name
.
This gives us the town and country on different lines (Figure 2). We would like them comma-separated, so use tr
to first delete the quote marks, and then replace the newlines with commas. The final sed
removes the last character, which is a comma.
Let's now look at the full command with this data put in:
convert -size 680x100 -background '#00000080' -fill white caption:"Bristol,United Kingdom" miff:- | composite -gravity south -geometry +0+3 - IMG_20170504_191133.jpgannoimg.jpg
What was once a matted knot of commands is now reduced to two. Both are commands from ImageMagick: convert
and composite
. The first makes an image that's the same width as the image we're editing (from the first command substitution) and a hundred pixels high that has a black slightly transparent background and the text of the town where the picture was taken.
The command saves this new image in miff format (ImageMagick's own format) and sends this data to stdout where it's picked up by the pipe and sent to the next
command. composite, as you might expect, takes two images and combines them. The -gravity
and -geometry
options tell composite to put the text horizontally at the bottom of the other image. The hyphen tells the command to take input from stdout, and the final two options are the original image and the newly modified image to save the output as.
This one massive command does all the modifying. The only thing left is to strip the metadata out of the image, which can be done with:
convert annoimage.jpg -strip strippedimg.jpg
Here ends our whistle-stop tour of ImageMagick and the Bash tools for composing commands. We haven't had time to look into all the options, but you should now have an idea of how you can put together several simple tools to build complex commands in a way that's almost endlessly flexible. Here, we've built a command that we've hand-coded for the specific image that we want to edit. As an extension, you could put this into a script that took an option for the image and performed this action on it or a command that iterated through a collection of images updating each one as it went.
Buy Linux Magazine
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters
Support Our Work
Linux Magazine content is made possible with support from readers like you. Please consider contributing when you’ve found an article to be beneficial.
News
-
Juno Tab 3 Launches with Ubuntu 24.04
Anyone looking for a full-blown Linux tablet need look no further. Juno has released the Tab 3.
-
New KDE Slimbook Plasma Available for Preorder
Powered by an AMD Ryzen CPU, the latest KDE Slimbook laptop is powerful enough for local AI tasks.
-
Rhino Linux Announces Latest "Quick Update"
If you prefer your Linux distribution to be of the rolling type, Rhino Linux delivers a beautiful and reliable experience.
-
Plasma Desktop Will Soon Ask for Donations
The next iteration of Plasma has reached the soft feature freeze for the 6.2 version and includes a feature that could be divisive.
-
Linux Market Share Hits New High
For the first time, the Linux market share has reached a new high for desktops, and the trend looks like it will continue.
-
LibreOffice 24.8 Delivers New Features
LibreOffice is often considered the de facto standard office suite for the Linux operating system.
-
Deepin 23 Offers Wayland Support and New AI Tool
Deepin has been considered one of the most beautiful desktop operating systems for a long time and the arrival of version 23 has bolstered that reputation.
-
CachyOS Adds Support for System76's COSMIC Desktop
The August 2024 release of CachyOS includes support for the COSMIC desktop as well as some important bits for video.
-
Linux Foundation Adopts OMI to Foster Ethical LLMs
The Open Model Initiative hopes to create community LLMs that rival proprietary models but avoid restrictive licensing that limits usage.
-
Ubuntu 24.10 to Include the Latest Linux Kernel
Ubuntu users have grown accustomed to their favorite distribution shipping with a kernel that's not quite as up-to-date as other distros but that changes with 24.10.