#0044: How I make basic pixel art animations

#0044: How I make basic pixel art animations

Preamble

I wanted to make a guide to how I cobble together the basic pixel art animations for A Tinkerer’s Blog. This is before learning how to do this type of stuff at a more professional level; by learning the methods in a formal course. Something I intend to pick up once my workload lightens. This is just the way I do it now. Something I wish to document for posterity. Please note that my skill level is very basic. However, I think it is also very serviceable for decorating Mein Blog. And that is enough for now. Additionally, this guide will include how to make other GIFs from images as well. Not just pixel art. Enjoy.

Tools used

Hardware:

  • Lenovo Thinkpad X230 laptop (Intel Core i5)

Programs:

  • GIMP
  • ImageMagick
  • image viewers (qview, xviewer)
  • browsers (Brave, Firefox)
  • xed text editor
  • VLC media player

Making pixel art images (using GIMP)

Creating initial image

I start by opening GIMP, my graphics editor of choice on the Linux platform. Here I created a 16×16 pixel square (256-pixel image). This is the blank slate for most of my art. With a 16×16 grid, a single-pixel (1×1) sized pen/pencil tool can be used to draw effectively. As it makes a really clean line, that also fits well mathematically for making symmetrical images.

I will use my “Tired Smiley” image as an example. The symmetry of it makes it easy to make. First thing I do is draw out guidelines. In this case an ‘x’ cross that segments the image space into 4 identical quadrants. A ‘+’ plus sign cross is good too, as are both of them overlaid. Although the plus sign would have to be 2 pixels thick to be symmetrical within this grid. Use whichever you feel you need.

I recommend using bold colours for guidelines to make them pop. I.e for easy visibility. Like a hi-viz vest in a forest. The only rule for colour choice is that the chosen colour (or a similar colour) must not be used within the image itself. Because of that I tend to go for: hot pinks, neon hues, bright reds, or bright blues. Any colour that will heavily contrast against the image’s general colour palette.

Now, using the guidelines it becomes a simple enough endeavour to key in something resembling a curve in one of the quadrants. Then using GIMP’s built-in functionality: copy that quadrant, paste it onto a new layer, then flip/rotate that layer to cover one of the other three quadrants. Repeat until we have a full circle across four different layers, then flatten to a single layer. This is a very easy way to make a circle.

After this I drew in the facial features, and saved that as a single layer. Then made several other versions, and had them on their own layers. Cleaned up the image, hid the guidelines and background. Then exported each face layer as its own image. And named them accordingly.

Naming files

I chose to name them ‘PA_TS_0_16x16’, and incremented the number for each additional image. It stands for ‘Pixel-Art_Tired-Smiley_0_16x16’. I recommend inserting the image dimensions as a filename addendum. This is especially useful when working with varying sized versions of the same images. Something we will be doing here.

Continuing. The incremental filename numbering makes it easy to keep adding images into a sequence (i.e. animation frames). This is as opposed to descriptive naming, which would require active thinking for naming each individual image. Incurring unnecessary mental overhead (i.e. fatigue). In addition it will extend the length, as well as remove the uniformity of the filenames. Two factors that are undesirable when organising the files for the animation. Especially when using a TUI.

I like to keep the names short since we will be working with them in the terminal. In other words we’ll have to write them out, and have to read them there too. Long names (or overly differentiated descriptive names) can make the output confusing, especially once they start spilling over into new lines. Additionally, for formatting: it is advisable to NOT have any spaces in the filenames. It makes working with them more cumbersome, since one will have to use quotation marks each time a reference to that filename is made.

While discussing file naming conventions, I’ll add that since this is a blinking animation I like to thematically link the zero in the filename with an open eye, and the 1 with a closed one. Because typographically they look like that. So I assign them accordingly. A silly little detail I know, and one hardly worth mentioning. However it is solely because I try to work with, not against my built-in eccentricities; as they can undermine my efforts later on in the process if ignored in the moment.

This comes usually in the form of incorrect implicit assumptions when working with data. Where one forgets the actual setup between sessions; leaving the internal schemas, biases, and implicit assumptions to kick in, in a bid to unconsciously bridge gaps in one’s knowledge. Often upsetting the workflow later down the line, when the errors are finally revealed. This is something to be cognisant of. Try to work with yourself when you can. Use the tool YOU have. Otherwise get used to going back and correcting a session’s worth of contributions. Ask me how I know.

Animation mock-up demonstration

Separate project files for each image

Next. I decided to edit each exported image in its own XCF project file. Here I scaled up each image by ten times to 160×160. Be mindful to set the ‘Interpolation’ under the ‘Quality’ settings to ‘None’. Otherwise the resultant scaled-up image would have blurry/fuzzy edges. And translucent border pixels, something that will become an issue later. At the very least this spoils the sharp pixel art aesthetic.

I recommend scaling each image in its own dedicated project file, as a final task. Because if you scale-up the main project file. You’ll have to undo it back to 16×16 every time you wish to make an edit to the core images. I stipulate ‘undo’, and not say scale back down; because scaling down from a larger image to a smaller one often damages the fidelity of that image. It is unlikely in my opinion to regain a pixel-perfect copy of the original image in this manner. This is because image scaling relies on algorithms. It is a machine guessing at what an image should look like at different sizes, with different pixel densities. Hence, it is fine for a project to have multiple project files to avoid this, as long as they are labelled descriptively. Once ready: export each image in PNG format.

Additionally before I move on, I will say that to make longer or taller images; one could either add another 16×16 to the initial canvas size, before the scale up. Or alternatively make a separate 16×16 image then join it to the primary after the resize; on a larger canvas used for the composition and layout of the final image. The example image below, is not a perfect example because I don’t remember whether I employed this particular method, or something analogous.

Making the animation (using ImageMagick)

Basic method

Now that we have the four 160×160 PNG images ready. It is time to make the animation. This is where ImageMagick comes into play. Within the terminal we will use the ‘convert’ command from the ImageMagick suite. There are two relevant parameters with arguments to pass to the program. The first is ‘-delay’, this denotes the time (in 10 milliseconds) each frame is shown within the animation. (I.e. ‘-delay 100’ = 1 second.) The second is ‘-loop’, this denotes how many times the animation sequence loops. 0 being infinite.

The example below uses a wildcard marker (‘*’) to include all files in that directory that contain the ‘.png’ file extension. However, alternatively one could name all the files manually. This is useful when the ordering of the files is especially important. Such as when reusing previously used images for more than one frame in an animation sequence, or when desiring some frames to be displayed longer than others.

Syntax:

$ program_name -parameter argument -parameter argument input_files(list_of_images.png) output_image.gif

Example command:

$ convert -delay 120 -loop 0 *.png result.gif

Exploring causes of visual errors

The first result – a four frame test animation using the method above – has a colour error within it for some reason. Frames 2 and 3 are colour inverted. Why? I don’t know. At least I did not know initially. ChatGPT tells me that there is no notable issue within the GIF file outputted. And after a little A-B testing, I realised that this display error only occurred within the ‘xviewer’ image viewer program, and not others such as ‘qview’. Additionally when displayed via a browser it also rendered as expected. So this was an issue particularly within my default image viewer program. This is something that you should be aware of. Just because a file displays oddly, doesn’t necessarily mean that the issue is within the file itself. As is often assumed.

Animated GIF displayed on xviewer

Animated GIF displayed on qview

Information on image formats

Before moving on I will make you aware of one thing here. Different image formats have different intrinsic qualities that you should be aware of. In this case, PNG images support a varying or gradual alpha level. In other words: image/pixel translucency. Whereas GIF images have a binary alpha level. A given GIF pixel is either opaque or transparent. Nothing in between. It is not a problem for my pixel art in general, as I do not make use of translucent pixels. However, it would be if, say, I wanted to make an animated GIF of the Pokemon Ghastly with its vapours clouding around it. That is an issue for another day. :/

Using a plan file

ImageMagick has a fair few parameters one could pass to it. Ones that stipulate the background, alpha, colour mapping.. all sorts. However, my personal credo is KISS. Keep it simple stupid. In this regard, I only use the absolutely necessary ones that I need to use.

However, there is one complication that I need to add. Instead of the wildcard selecting all files in order, as I mentioned above – I wanted to manually list the image files in the order that I wish them to appear. While reusing images, and having other images stay displayed for twice the allotted standard time. To do this start with an image sequence plan.

Extract from plan file:

// animation setup
Animation sequence: 0,0,0,0, 0,1,0,1, 0,1,1,0, 2,3,0,1, repeat.
Frame speed: 1.2 seconds

// terminal command
convert -delay 120 -loop 0 PA_TS_0_160x160.png PA_TS_0_160x160.png PA_TS_0_160x160.png PA_TS_0_160x160.png PA_TS_0_160x160.png PA_TS_1_160x160.png PA_TS_0_160x160.png PA_TS_1_160x160.png PA_TS_0_160x160.png PA_TS_1_160x160.png PA_TS_1_160x160.png PA_TS_0_160x160.png PA_TS_2_160x160.png PA_TS_3_160x160.png PA_TS_0_160x160.png PA_TS_1_160x160.png PA_tired_smiley_animation.gif

You see all the code written above? Imagine having to go back and forth tweaking that. It looks tedious honestly. That is why I recommend as a best practice, to create a separate plan file for your animated image. This doesn’t take long. However it makes it significantly simpler/easier to organise the animation. As it has all the information required for the animation, as well as the (easily editable) command written within the text editor. I recommend writing the shell command fully within the text editor, saving it (for posterity), then when ready to execute – just copy and paste it into the terminal. This avoids any back and forth, editing within the terminal.

Pixel Art Tired Smiley Animation image

no alpha version

GIF plan file

Making a non-pixel art GIF animation

This is very easy: simply capture the images you wish to use as animation frames, then size them appropriately for the GIF. This usually means reducing their dimensions. Use interpolation if you don’t need the clean sharp lines of pixel art. Convert files to GIF format. This lets you preview something of the final quality, or at the very least appreciate the step-down in image fidelity. You may have another within the outputted animated GIF. Although it shouldn’t be as large of a step-down incurred by the initial conversion from PNG to GIF. Moving on. Make sure all image files are uniform in dimension. Then create a plan file like above, and run the command when you are satisfied with it. Done.

For my example: I used VLC player’s snapshot feature while watching a Cowboy Bebop episode. Caught 2 frames of Edward blinking in shock after an explosion. Using GIMP I scaled them down by 50% and trimmed their canvas to 480×360. Then converted their file type from VLC’s PNG to GIF. This caused a notable loss in image quality. That’s fine. It came with a significant file-size reduction. (-66%.) Then I wrote a plan file for how I wanted the animation to display the two frames. Wrote out the command within the plan file. Tweaked it until satisfied. Then. Copy, paste, run. Done.

Image quality side-by-side comparison

File size reduction demonstration

Edward blinking animation image

GIF plan file

Closing thoughts

The technical process of creating animated GIFs is actually very simple. Because of that, there is little commentary to have on it here that hasn’t already been said. So instead I will opine on a tangential matter. The cool thing about the Linux platform is that the majority of software available is FOSS. On this platform, users have access to robust productivity tools, that are provided free of charge. And with little to no tangible usage restrictions. So any method I demonstrate here, will have no financial barriers preventing people from achieving their goals. These being in the form of commercial programs, or paid services.

I wanted to write this article as a way of documenting this process. A process whose fruits are evidenced on dis blog. This is the method that I personally use to create my pixel art animations. (As of 2026-10-30, and likely going forwards.)

Thank you for reading.

Acronyms used

FOSS – Free and Open Source Software
KISS – Keep It Simple Stupid
GIF – Graphics Interchange Format
GIMP – GNU Image Manipulation Program
PNG – Portable Network Graphics
TUI – Text User Interface
VLC – VideoLAN Client (i.e. VLC media player)
XCF – eXperimental Computing Facility

Links, references, and further reading