How to upscale images by hand (in Linux)

Updated: September 27, 2024

Just a few weeks ago, we talked about Upscayl, a truly excellent AI-powered tool that can upscale your images. Before you say ZOMG AI, wait. This is a fully offline, open-source, cross-platform utility, and it doth not phone home or anything like that. Your work stays local. But the quality of upscaling will vary from image to image, as I've outlined in my review.

Now, what if you cannot use this program, for whatever reason? What if you have an unsupported integrated graphics card (as is typical on many a laptop), but you still want to try to upscale your old photos, reduce the blur, and make things better? In today's tutorial, I will tell you how well I fared using ImageMagick on the command-line, plus some wizardry with GIMP. Let's do 4K stuff the old-school way.

Teaser

How to upscale images with ImageMagick (convert)

First, you will need to install (if not already installed) the ImageMagick package in your Linux distribution of choice. My work was all done using Kubuntu 22.04, so it's Ubuntu commands and such.

sudo apt install imagemagick

Once the program is installed, you can use the convert tool. Here's a rather long and complicated command:

convert [IMAGE] \
-alpha on \
-virtual-pixel transparent \
-filter Triangle \
+distort Affine "0,0 0,0 %w,0 [WIDTH],0 0,%h 0,[HEIGHT]" \
-alpha off \
-crop [WIDTH]x[HEIGHT]+0+0 [OUTPUT IMAGE]

What do we have here? Well, take a look at what convert can do:

This isn't a simple command. It took me hours and hours of reading and trawling around the forums to get the right commands. I don't claim any higher wisdom here. In fact, when you use GIMP, a lot of the tools do similar things in the background.

A practical example of a convert command would look like this:

convert input.png -alpha on -virtual-pixel transparent -filter Triangle +distort Affine '0,0 0,0 %w,0 3834,0 0,%h 0,3582' -alpha off -crop 3834x3582+0+0 output.png

Faster work: BASH script

If you want to make your work easier, you could put this command into a script, and substitute actual values for input parameters, so you have more flexibility working with files of different sizes. Here's a very rudimentary BASH script that will take an input file, plus the original width and height values (in pixels). The script is written to enlarge files by a factor of 4 (x4), but this could also be a dynamic (input) parameter, if you like.

The reason my script looks a bit ugly is that the convert command doesn't really like substitution, and so I had to "fake" it by concatenating multiple strings into a command. I'm sure there are more elegant ways, including doing arithmetics on the fly, but the purpose of this script isn't BASH wizardry, it's to run convert and get the job done. Here, $1 means file name, $2 is the original width, $3 is the original height. The output name is hardcoded, but it's your choice.

#!/bin/bash

WIDTH=$(($2*4))
HEIGHT=$(($3*4))

AFF="0,0 0,0 %w,0 $WIDTH,0 0,%h 0,$HEIGHT"
CROPVAL1="$WIDTH"
CROPVAL2="x$HEIGHT+0+0"
CROPVALCAT=$CROPVAL1$CROPVAL2

convert "$1" -alpha on -virtual-pixel transparent -filter Triangle +distort Affine "$AFF" -alpha off -crop $CROPVALCAT output.jpg

exit 0

The usage would then be, for instance:

./my-convert-script.sh filename.jpg 1440 1080

Now, the errors ...

If you run this script, you may get various ImageMagick errors - it could complain about cache resources or memory limit. Indeed, if you try to make your files too big, convert will hit the program policy limits.

convert-im6.q16: width or height exceeds limit `file.jpg' @ error/cache.c/OpenPixelCache/3909.

convert-im6.q16: cache resources exhausted `file.jpg' @ error/cache.c/OpenPixelCache/4095.

To get past this nuisance, open (as sudo) /etc/ImageMagick-6/policy.xml. Then, edit memory values, width or height as you see fit. In my example, I raised the memory limit from 256MiB to 2048MiB, and later even higher, and also changed both width and height values from 16KP to 64KP. Be sensible, though. You may run out of memory on your system, if you exaggerate.

<policymap>
  <!-- <policy domain="resource" name="temporary-path" value="/tmp"/> -->
  <policy domain="resource" name="memory" value="2048MiB"/>
  <policy domain="resource" name="map" value="512MiB"/>
  <policy domain="resource" name="width" value="64KP"/>
  <policy domain="resource" name="height" value="64KP"/>
  <!-- <policy domain="resource" name="list-length" value="128"/> -->
  <policy domain="resource" name="area" value="128MP"/>
  <policy domain="resource" name="disk" value="1GiB"/>
...

Early findings with convert ...

My results were quite interesting:

All right, so the command above resized our images a-la Upscayl. Some interpolation based on the algorithm specified. That's what we wanted. But you could also try to reduce noise, blur or sharpen your images, and then some. Cool.

Thus, separately, and in parallel, I tried using GIMP for some additional image processing, and also tried the equivalent convert commands (so I could script them later on). Most notably, I wanted to try the blur and unsharpen (mask) functions, to see if they could help with my manual conversion, before or after the resizing.

Before we move on to GIMP, here's a very rudimentary example of how you can apply additional processing to images with convert. For instance, to sharpen a photo using a 4px radius, you would run:

convert input.jpg -sharpen 0x4.0 output.jpg

Or perhaps, use an adaptive sharpening function with a 3px radius:

convert input.png -adaptive-sharpen 0x3.0 output.png

Findings using GIMP (and equivalent convert commands)

Before we move on, here are my assumptions:

The following happened:

General recipe for manual conversions (convert and/or GIMP)

After some trial and error, here's what I've come up with. The tools, GIMP, convert, and then eventually, optionally, Upscayl. Of course, the actual "sauce" depends on so many factors, but generally, I found the results to be quite favorable.

First a decision on whether to use convert or GIMP:

Next, a decision regarding the image size:

Next, assuming your images are large but of low quality, I found the following work to help:

Finally, resize the image:

And that's it. You should now have nicer images, and much sharper than before. You ought to get a bit more clarity, bigger size, and (almost) no loss of original information. Here's a little side by side comparison - the original, plus a "massaged" new image - noise reduction, unsharpen twice, selective Gaussian blur once, and a x2 resize.

Original Processed

Optional: subsequent AI upscaling

If you have the ability, try using Upscayl, just to see how it fares. If your computer cannot do it, perhaps ask a friend, so you get a comparison. A general recipe is to take a scaled-down image of your original, the 2500x2500px template we mentioned in the GIMP section, and then work on it.

Upscayl, no resize

You can keep the image size unchanged if you like (faster, easier to compare).

Check the results. This will give you further "proof" that the manual method is pretty solid. Furthermore, your upscaled images will also look a bit better if you've done some contrast/brightness and sharpening beforehand. Again, don't expect miracles, but you could still end up with nice little improvements to your old catalog of images. And in this regard, every little bit can help.

Original, before changes Default Upscayl result

Original vs Upscayl (no other changes done). In some regards, the AI-upscaled work is worse.

Original, before changes After GIMP and Upscayl

Original plus Upscayl after manual unsharpen mask ... AI did much better after noise cleaning and unsharpening.

Default Upscayl result After GIMP and Upscayl

Upscayl (default) versus Upscayl after some manual pre-processing. The new AI result is significantly better.

Finally, if you compare the AI work after post-processing and manual work, you will see that Upscayl did superbly with some help. But without it, the manual resize work on the blurry photo is comparable to the default results with Upscayl. As I noted in my review, Upscayl works superbly with low-res photos with low noise, uniform lighting, and moderate detail. It does not work well with hi-res, blurry, grainy photos where noise exceeds the model fineness and ability to repair and extrapolate information, as in my example no.3 (see the tool review for more information). But if you combine some manual work AND then use Upscayl, you can work around that limitation!

Conclusion

Hopefully, you will find this tutorial useful. Now, the results will vary greatly based on your input files. Some of your photos will remain blurry and grainy no matter what. There's only so much thermodynamic magic we can do with non-existent information. Also remember, what your eye sees is not what the machine does, and it must use algorithms to figure out the "space" between pixels. It has no imagination, only pixels.

In the previous tutorial, we talked about Upscayl. The program is great. But if your system has no discrete GPU, it's not all lost. You can still improve your images manually. It takes more work, you need to be comfortable using nerdy tools, but it's doable. In fact, it's more than doable. You ought to be pleasantly surprised with the outcome. Anyway, that would be all for today. Take care, and see you soon.

Cheers.