junguler / _dork-word-play

character animations for learning some imagemagick

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool


imagemagick is massive, it's too big in fact but that doesn't mean we can't mess around with it and see what we can come up with, i'm interested in making small animated gifs of keyboard characters and that's exactly what i'm going to showcase here

note: there are a lot of little gifs need to be loaded for this page to look correctly, if you see any weird behavior of links not loading just refresh the page and your web browser hopefully caches everything by that time

this tutorial markdown was made possible partially by a helpful comment on reddit that fixed my problem printing speciall characters and helped giving usable names for them


quick links


how to create an image using characters with imagemagick?

this couldn't be more easier, we'll use the program convert (in the newest versions it's called magick so if you don't have the convert commandline program just change convert to magick in the commands) to achieve this

convert -gravity center -background yellow -fill black -size 30x30 caption:"A" A.jpg

A-A

as you can see -gravity center is supposed to center our character vertically and horizontally but it doesn't do that completely, we can correct this using -trim which removes white spaces in the image and pad it to center with -extent and passing the same size as our output image

convert -gravity center -background yellow -fill black -size 30x30 caption:"A" -trim -extent 30x30 A.jpg

A-B


output all of the characters in a for loop

now that we know how to output an image we'll use a for loop to convert all the numbers and alphabet characters in lower and higher case

for i in {a..z} {A..Z} {0..9} ; do convert -gravity center -trim -background yellow -fill black -font ./nerd.ttf -size 30x30 caption:$i -extent 30x30 $i.jpg ; done

0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z

{a..z} {A..Z} {0..9} in our for loop tells our shell to iterate thru numbers 0 to 9, characters from a to z and A to Z one by one

we also used a custom font with -font called nerd.ttf which was actually Caskaydia Cove Nerd Font Mono which i renamed for simplicity and put inside the folder i'm making these images, you can also pass the absolute path to it in your filesystem

the mono in that font name refers to every character taking the same width as other, these fonts are typically used in ascii art, terminal emulators and code editors to easily be able to read them but i'm using the mono variant because it's easier to fit into the image


printing special characters

special characters are harder to work with since they are not aloud to be used in file names in windows specially so because we want to have a cross-platform solution we convert their file names to their hex counterparts, note that this command is a zsh exclusive command and doesn't work on bash

for char in {\!..\)} \@ \` {\*..\/} {\:..\?} {\[..\^} {\{..\~} ; do printf -v hex '%02X' $(( #char )) ; convert -gravity center -trim -background yellow -fill black -font ./nerd.ttf -size 30x30 -extent 30x30 caption:$char $hex.jpg ; done

21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 3A 3B 3C 3D 3E 3F 40 5B 5C 5D 5E 60 7B 7C 7D 7E

notice the segmented ranges in our for loop {\!..\)} \@ \` {\*..\/} {\:..\?} {\[..\^} {\{..\~} the reason for this is that we don't want duplicate characters as our normal characters above so we exclude the ranges they are in within our for loop, if you don't care about file names you can do {\!..~} and combine both steps together


animating the characters

so far we've been working with static image but let's change all of that and use ffmpeg to make a simple animation, we'll combine two for loops together one for the degrees of hue change (which changes the color of the images) and one for ffmpeg to iterate thru our images

for h in {30..360..30} ; for i in {a..z}.jpg {A..Z}.jpg {0..9}.jpg ; do mkdir output ; ffmpeg -i $i -vf hue=h=$h output/$h-$i ; done

we also made a output folder and put the output images inside it to keep things organized, now cd into that folder cd output/

now we are ready to animate these image sequences using the convert program

for m in {a..z} {A..Z} {0..9} ; do convert $(ls -v *-$m.jpg) $m.gif ; done 

notice that the same pattern that we used when converting the input images is used for outputting the animations, we also used ls -v here to sort filenames numerically, if you don't do this the shell doesn't really sort filenames correctly and only sort by the first digit number, for example 20.jpg is placed earlier than 3.jpg

0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z


animating special characters

the same principles applies here, we just need to adjust our commands a bit, first the ffmpeg command

for h in {30..360..30} ; for i in 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 3A 3B 3C 3D 3E 3F 40 5B 5C 5D 5E 60 7B 7C 7D 7E ; do mkdir output2 ; ffmpeg -i $i.jpg -vf hue=h=$h output2/$h-$i.jpg ; done

because we only want specially characters and don't need duplicates we specially named every output file we need, we also made a new output2 folder to keep things organized, cd into the folder like before, now lets convert them to animated gifs

for m in 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 3A 3B 3C 3D 3E 3F 40 5B 5C 5D 5E 60 7B 7C 7D 7E ; do convert $(ls -v *-$m.jpg) $m.gif ; done

21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 3A 3B 3C 3D 3E 3F 40 5B 5C 5D 5E 60 7B 7C 7D 7E


invert your output gifs

the easiest way to modify our newly made gifs is to invert them, it really changes the look of everything and it's so simple to do

for i in *.gif ; do mkdir inverted ; ffmpeg -i $i -vf negate inverted/I-$i ; done

I-0 I-1 I-2 I-3 I-4 I-5 I-6 I-7 I-8 I-9 I-21 I-22 I-23 I-24 I-25 I-26 I-27 I-28 I-29 I-2A I-2B I-2C I-2D I-2E I-2F I-3A I-3B I-3C I-3D I-3E I-3F I-40 I-5B I-5C I-5D I-5E I-60 I-7B I-7C I-7D I-7E I-a I-A I-b I-B I-c I-C I-d I-D I-e I-E I-f I-F I-g I-G I-h I-H I-i I-I I-j I-J I-k I-K I-l I-L I-m I-M I-n I-N I-o I-O I-p I-P I-q I-Q I-r I-R I-s I-S I-t I-T I-u I-U I-v I-V I-w I-W I-x I-X I-y I-Y I-z I-Z


scroll your gifs

using ffmpeg scroll filter, we can scroll our gifs horizontally or vertically

for i in *.gif ; do mkdir h-scroll ; ffmpeg -i $i -vf scroll=h=0.09 h-scroll/H-$i ; done

H-0 H-1 H-2 H-3 H-4 H-5 H-6 H-7 H-8 H-9 H-21 H-22 H-23 H-24 H-25 H-26 H-27 H-28 H-29 H-2A H-2B H-2C H-2D H-2E H-2F H-3A H-3B H-3C H-3D H-3E H-3F H-40 H-5B H-5C H-5D H-5E H-60 H-7B H-7C H-7D H-7E H-a H-A H-b H-B H-c H-C H-d H-D H-e H-E H-f H-F H-g H-G H-h H-H H-i H-I H-j H-J H-k H-K H-l H-L H-m H-M H-n H-N H-o H-O H-p H-P H-q H-Q H-r H-R H-s H-S H-t H-T H-u H-U H-v H-V H-w H-W H-x H-X H-y H-Y H-z H-Z

for i in *.gif ; do mkdir v-scroll ; ffmpeg -i $i -vf scroll=v=-0.09 v-scroll/V-$i ; done

V-0 V-1 V-2 V-3 V-4 V-5 V-6 V-7 V-8 V-9 V-21 V-22 V-23 V-24 V-25 V-26 V-27 V-28 V-29 V-2A V-2B V-2C V-2D V-2E V-2F V-3A V-3B V-3C V-3D V-3E V-3F V-40 V-5B V-5C V-5D V-5E V-60 V-7B V-7C V-7D V-7E V-a V-A V-b V-B V-c V-C V-d V-D V-e V-E V-f V-F V-g V-G V-h V-H V-i V-I V-j V-J V-k V-K V-l V-L V-m V-M V-n V-N V-o V-O V-p V-P V-q V-Q V-r V-R V-s V-S V-t V-T V-u V-U V-v V-V V-w V-W V-x V-X V-y V-Y V-z V-Z

if you want to reverse the motion either add a negative sign - before the values like in our vertical example or do not include it like the horizontal example


combine multiple filters

say i don't care about the colors of above animations but i do like motion so let's make it black & white we also use , to combine this filter with invert to make a dark variant of those animations

for i in *.gif ; do mkdir bw-inv ; ffmpeg -i $i -vf hue=s=0,negate bw-inv/B-$i ; done

B-H-0 B-H-1 B-H-2 B-H-3 B-H-4 B-H-5 B-H-6 B-H-7 B-H-8 B-H-9 B-H-21 B-H-22 B-H-23 B-H-24 B-H-25 B-H-26 B-H-27 B-H-28 B-H-29 B-H-2A B-H-2B B-H-2C B-H-2D B-H-2E B-H-2F B-H-3A B-H-3B B-H-3C B-H-3D B-H-3E B-H-3F B-H-40 B-H-5B B-H-5C B-H-5D B-H-5E B-H-60 B-H-7B B-H-7C B-H-7D B-H-7E B-H-a B-H-A B-H-b B-H-B B-H-c B-H-C B-H-d B-H-D B-H-e B-H-E B-H-f B-H-F B-H-g B-H-G B-H-h B-H-H B-H-i B-H-I B-H-j B-H-J B-H-k B-H-K B-H-l B-H-L B-H-m B-H-M B-H-n B-H-N B-H-o B-H-O B-H-p B-H-P B-H-q B-H-Q B-H-r B-H-R B-H-s B-H-S B-H-t B-H-T B-H-u B-H-U B-H-v B-H-V B-H-w B-H-W B-H-x B-H-X B-H-y B-H-Y B-H-z B-H-Z

B-V-0 B-V-1 B-V-2 B-V-3 B-V-4 B-V-5 B-V-6 B-V-7 B-V-8 B-V-9 B-V-21 B-V-22 B-V-23 B-V-24 B-V-25 B-V-26 B-V-27 B-V-28 B-V-29 B-V-2A B-V-2B B-V-2C B-V-2D B-V-2E B-V-2F B-V-3A B-V-3B B-V-3C B-V-3D B-V-3E B-V-3F B-V-40 B-V-5B B-V-5C B-V-5D B-V-5E B-V-60 B-V-7B B-V-7C B-V-7D B-V-7E B-V-a B-V-A B-V-b B-V-B B-V-c B-V-C B-V-d B-V-D B-V-e B-V-E B-V-f B-V-F B-V-g B-V-G B-V-h B-V-H B-V-i B-V-I B-V-j B-V-J B-V-k B-V-K B-V-l B-V-L B-V-m B-V-M B-V-n B-V-N B-V-o B-V-O B-V-p B-V-P B-V-q B-V-Q B-V-r B-V-R B-V-s B-V-S B-V-t B-V-T B-V-u B-V-U B-V-v B-V-V B-V-w B-V-W B-V-x B-V-X B-V-y B-V-Y B-V-z B-V-Z

the same results can be achieved with the convert's own -negate for the invert and -monochrome for black and white filter but since we already had our gifs made i used ffmpeg because it has more options and filters to play with


rotate your characters

convert has a native flag for rotating images and in our case characters so let's use it to create these images and iterate thru them all with rotation

for h in {30..360..30} ; for i in {a..z} {A..Z} {0..9} ; do convert -gravity center -trim -background blue -fill cyan -font ./nerd.ttf -size 30x30 caption:$i -rotate $h -extent 30x30 $h-$i.jpg ; done

and for special characters

for h in {30..360..30} ; for char in {\!..\)} \@ \` {\*..\/} {\:..\?} {\[..\^} {\{..\~} ; do printf -v hex '%02X' $(( #char )) ; convert -gravity center -trim -background blue -fill cyan -rotate $h -font ./nerd.ttf -size 30x30 -extent 30x30 caption:$char $h-$hex.jpg ; done

for turning everything counter-clock wise just add a negative sign - before $h like this -rotate -$h in both commands to achieve this, lets get to converting these

for m in {a..z} {A..Z} {0..9} ; do convert $(ls -v *-$m.jpg) RR-$m.gif ; done

and for special characters

for m in 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 3A 3B 3C 3D 3E 3F 40 5B 5C 5D 5E 60 7B 7C 7D 7E ; do convert $(ls -v *-$m.jpg) RR-$m.gif ; done

same two commands can be run on your counter-clock rotation image sequences

RR-0 RR-1 RR-2 RR-3 RR-4 RR-5 RR-6 RR-7 RR-8 RR-9 RR-21 RR-22 RR-23 RR-24 RR-25 RR-26 RR-27 RR-28 RR-29 RR-2A RR-2B RR-2C RR-2D RR-2E RR-2F RR-3A RR-3B RR-3C RR-3D RR-3E RR-3F RR-40 RR-5B RR-5C RR-5D RR-5E RR-60 RR-7B RR-7C RR-7D RR-7E RR-a RR-A RR-b RR-B RR-c RR-C RR-d RR-D RR-e RR-E RR-f RR-F RR-g RR-G RR-h RR-H RR-i RR-I RR-j RR-J RR-k RR-K RR-l RR-L RR-m RR-M RR-n RR-N RR-o RR-O RR-p RR-P RR-q RR-Q RR-r RR-R RR-s RR-S RR-t RR-T RR-u RR-U RR-v RR-V RR-w RR-W RR-x RR-X RR-y RR-Y RR-z RR-Z

RL-0 RL-1 RL-2 RL-3 RL-4 RL-5 RL-6 RL-7 RL-8 RL-9 RL-21 RL-22 RL-23 RL-24 RL-25 RL-26 RL-27 RL-28 RL-29 RL-2A RL-2B RL-2C RL-2D RL-2E RL-2F RL-3A RL-3B RL-3C RL-3D RL-3E RL-3F RL-40 RL-5B RL-5C RL-5D RL-5E RL-60 RL-7B RL-7C RL-7D RL-7E RL-a RL-A RL-b RL-B RL-c RL-C RL-d RL-D RL-e RL-E RL-f RL-F RL-g RL-G RL-h RL-H RL-i RL-I RL-j RL-J RL-k RL-K RL-l RL-L RL-m RL-M RL-n RL-N RL-o RL-O RL-p RL-P RL-q RL-Q RL-r RL-R RL-s RL-S RL-t RL-T RL-u RL-U RL-v RL-V RL-w RL-W RL-x RL-X RL-y RL-Y RL-z RL-Z


using shades of grey as color

imagemagick uses a wide variety of color values and names as input, look here for a complete explanation, but the easiest way to use this is by choosing color names, for the shades of grey specifically there are grey0 which is a black color to grey100 which is a white color and everything between grey1 and grey99 are shades of grey, knowing this we can easily loop thru them in a for loop like this

for i in {0..9} {a..z} {A..Z} ; for g in {0..100..10} ; do convert -gravity center -trim -background grey50 -fill grey$g -font ./nerd.ttf -size 30x30 caption:$i -extent 30x30 $g-$i.jpg ; done

as you can see we just need to loop thru the numbers and append them to the grey word in the -fill flag -fill grey$g we also only use every 10th number in the loop for a total of 10 frames, the background color stays the same as a neutral grey50, now for converting

for m in {a..z} {A..Z} {0..9} ; do convert $(ls -v *-$m.jpg) $m.gif ; done

for special characters do

for char in {\!..\)} \@ \` {\*..\/} {\:..\?} {\[..\^} {\{..\~} ; for g in {0..100..10} ; do printf -v hex '%02X' $(( #char )) ; convert -gravity center -trim -background grey50 -fill grey$g -font ./nerd.ttf -size 30x30 -extent 30x30 caption:$char $g-$hex.jpg ; done
for m in 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 3A 3B 3C 3D 3E 3F 40 5B 5C 5D 5E 60 7B 7C 7D 7E ; do convert $(ls -v *-$m.jpg) g-$m.gif ; done

g-0 g-1 g-2 g-3 g-4 g-5 g-6 g-7 g-8 g-9 g-21 g-22 g-23 g-24 g-25 g-26 g-27 g-28 g-29 g-2A g-2B g-2C g-2D g-2E g-2F g-3A g-3B g-3C g-3D g-3E g-3F g-40 g-5B g-5C g-5D g-5E g-60 g-7B g-7C g-7D g-7E g-a g-A g-b g-B g-c g-C g-d g-D g-e g-E g-f g-F g-g g-G g-h g-H g-i g-I g-j g-J g-k g-K g-l g-L g-m g-M g-n g-N g-o g-O g-p g-P g-q g-Q g-r g-R g-s g-S g-t g-T g-u g-U g-v g-V g-w g-W g-x g-X g-y g-Y g-z g-Z


merge multiple files together

using -adjoin we can easily combine multiple images to make a gif file

convert -adjoin $(ls -v *.jpg) all.gif

all

if you want to change the framerate of these gifs we can use the -delay flag, by default convert has a 100 ticks (same as milliseconds) per seconds, any amount of delay we add gets divided by this number and applied before each image in our sequence of images, so the number 8 results in 12.5 frames per second, 16 results in 6.25 fps and so on

convert -adjoin -delay 16 $(ls -v *.jpg) all+.gif

all+

combining multiple gifs together can be done using the same joining method

convert -adjoin $(ls -v *.gif) numbers.gif

numbers


making a smooth gradient animation, the hard way

in one of the above sections i showed how to use ffmpeg's hue filter to make a gradient with colors, it gets the job done but sometimes you want more control with exact colors you want to use

imagemagick gives many options for specifying colors, in our case we'll use rgb(100%, 0%, 0%) which takes percentages as RGB values, lets start by changing the colors from red rgb(100%, 0%, 0%) to magenta rgb(100%, 0%, 100%) with 10% increments

for i in {a..z} {A..Z} {0..9} ; for g in {0..100..10} ; do convert -gravity center -trim -background "rgb(100%,0%,$g%)" -fill white -font ./nerd.ttf -size 30x30 caption:$i -extent 30x30 A-$g-$i.jpg ; done
for char in {\!..\)} \@ \` {\*..\/} {\:..\?} {\[..\^} {\{..\~} ; for g in {0..100..10} ; do printf -v hex '%02X' $(( #char )) ; convert -gravity center -trim -background "rgb(100%,0%,$g%)" -fill white -font ./nerd.ttf -size 30x30 -extent 30x30 caption:$char A-$g-$hex.jpg ; done

now, make a loop that changes magenta rgb(100%, 0%, 100%) to blue rgb(0%, 0%, 100%)

for i in {a..z} {A..Z} {0..9} ; for g in {100..0..10} ; do convert -gravity center -trim -background "rgb($g%,0%,100%)" -fill white -font ./nerd.ttf -size 30x30 caption:$i -extent 30x30 B-$g-$i.jpg ; done
for char in {\!..\)} \@ \` {\*..\/} {\:..\?} {\[..\^} {\{..\~} ; for g in {0..100..10} ; do printf -v hex '%02X' $(( #char )) ; convert -gravity center -trim -background "rgb($g%,0%,100%)" -fill white -font ./nerd.ttf -size 30x30 -extent 30x30 caption:$char B-$g-$hex.jpg ; done

now convert your first batch of images to gifs

for m in {a..z} {A..Z} {0..9} ; do convert $(ls -v A-*-$m.jpg) A1-$m.gif ; done
for m in 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 3A 3B 3C 3D 3E 3F 40 5B 5C 5D 5E 60 7B 7C 7D 7E ; do convert $(ls -v A-*-$m.jpg) A1-$m.gif ; done   

A1-0 A1-1 A1-2 A1-3 A1-4 A1-5 A1-6 A1-7 A1-8 A1-9


convert the second batch of images to gifs

for m in {a..z} {A..Z} {0..9} ; do convert $(ls -vr B-*-$m.jpg) A2-$m.gif ; done
for m in 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 3A 3B 3C 3D 3E 3F 40 5B 5C 5D 5E 60 7B 7C 7D 7E ; do convert $(ls -vr B-*-$m.jpg) A2-$m.gif ; done  

note that we use the -r flag with ls to sort and feed images in reverse for the second batch of gifs

A2-0 A2-1 A2-2 A2-3 A2-4 A2-5 A2-6 A2-7 A2-8 A2-9


combine both sets of gifs together

for m in {a..z} {A..Z} {0..9} ; do convert -adjoin A1-$m.gif A2-$m.gif A3-$m.gif ; done
for m in 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 3A 3B 3C 3D 3E 3F 40 5B 5C 5D 5E 60 7B 7C 7D 7E ; do convert -adjoin A1-$m.gif A2-$m.gif A3-$m.gif ; done

A3-0 A3-1 A3-2 A3-3 A3-4 A3-5 A3-6 A3-7 A3-8 A3-9


now make a reversed duplicated sets of these gifs to have a smooth back and forth motion in the last step

for m in {a..z} {A..Z} {0..9} ; do convert -reverse A3-$m.gif A4-$m.gif ; done
for m in 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 3A 3B 3C 3D 3E 3F 40 5B 5C 5D 5E 60 7B 7C 7D 7E ; do convert -reverse A3-$m.gif A4-$m.gif ; done

A4-0 A4-1 A4-2 A4-3 A4-4 A4-5 A4-6 A4-7 A4-8 A4-9


finally combine your 3rd and 4th batches of gifs to get the final result

for m in {a..z} {A..Z} {0..9} ; do convert -adjoin A3-$m.gif A4-$m.gif A5-$m.gif ; done
for m in 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 3A 3B 3C 3D 3E 3F 40 5B 5C 5D 5E 60 7B 7C 7D 7E ; do convert -adjoin A3-$m.gif A4-$m.gif A5-$m.gif ; done

A5-0 A5-1 A5-2 A5-3 A5-4 A5-5 A5-6 A5-7 A5-8 A5-9 A5-21 A5-22 A5-23 A5-24 A5-25 A5-26 A5-27 A5-28 A5-29 A5-2A A5-2B A5-2C A5-2D A5-2E A5-2F A5-3A A5-3B A5-3C A5-3D A5-3E A5-3F A5-40 A5-5B A5-5C A5-5D A5-5E A5-60 A5-7B A5-7C A5-7D A5-7E A5-a A5-A A5-b A5-B A5-c A5-C A5-d A5-D A5-e A5-E A5-f A5-F A5-g A5-G A5-h A5-H A5-i A5-I A5-j A5-J A5-k A5-K A5-l A5-L A5-m A5-M A5-n A5-N A5-o A5-O A5-p A5-P A5-q A5-Q A5-r A5-R A5-s A5-S A5-t A5-T A5-u A5-U A5-v A5-V A5-w A5-W A5-x A5-X A5-y A5-Y A5-z A5-Z


for the bonus round, lets invert these gifs using convert's own -negate and make it like these are completely new gifs

for m in {a..z} {A..Z} {0..9} ; do convert -negate A5-$m.gif A6-$m.gif ; done
for m in 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 3A 3B 3C 3D 3E 3F 40 5B 5C 5D 5E 60 7B 7C 7D 7E ; do convert -negate A5-$m.gif A6-$m.gif ; done

A6-0 A6-1 A6-2 A6-3 A6-4 A6-5 A6-6 A6-7 A6-8 A6-9 A6-21 A6-22 A6-23 A6-24 A6-25 A6-26 A6-27 A6-28 A6-29 A6-2A A6-2B A6-2C A6-2D A6-2E A6-2F A6-3A A6-3B A6-3C A6-3D A6-3E A6-3F A6-40 A6-5B A6-5C A6-5D A6-5E A6-60 A6-7B A6-7C A6-7D A6-7E A6-a A6-A A6-b A6-B A6-c A6-C A6-d A6-D A6-e A6-E A6-f A6-F A6-g A6-G A6-h A6-H A6-i A6-I A6-j A6-J A6-k A6-K A6-l A6-L A6-m A6-M A6-n A6-N A6-o A6-O A6-p A6-P A6-q A6-Q A6-r A6-R A6-s A6-S A6-t A6-T A6-u A6-U A6-v A6-V A6-w A6-W A6-x A6-X A6-y A6-Y A6-z A6-Z


variable sizes

using -pointsize flag we can set the size of our characters in our for loop

for i in {a..z} {A..Z} {0..9} ; for s in {5..50..5} ; do convert -gravity center -trim -background grey25 -fill grey75 -font ./nerd.ttf -size 30x30 -pointsize $s caption:$i -extent 30x30 $i-$s.jpg ; done
for char in {\!..\)} \@ \` {\*..\/} {\:..\?} {\[..\^} {\{..\~} ; for s in {5..50..5} ; do printf -v hex '%02X' $(( #char )) ; convert -gravity center -trim -background grey25 -fill grey75 -font ./nerd.ttf -size 30x30 -extent 30x30 -pointsize $s caption:$char $hex-$s.jpg ; done

now for converting them

for m in {a..z} {A..Z} {0..9} ; do convert -delay 8 $(ls -v $m-*.jpg) S-$m.gif ; done
for m in 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 3A 3B 3C 3D 3E 3F 40 5B 5C 5D 5E 60 7B 7C 7D 7E ; do convert -delay 8 $(ls -v $m-*.jpg) S-$m.gif ; done 

S-0 S-1 S-2 S-3 S-4 S-5 S-6 S-7 S-8 S-9 S-21 S-22 S-23 S-24 S-25 S-26 S-27 S-28 S-29 S-2A S-2B S-2C S-2D S-2E S-2F S-3A S-3B S-3C S-3D S-3E S-3F S-40 S-5B S-5C S-5D S-5E S-60 S-7B S-7C S-7D S-7E S-a S-A S-b S-B S-c S-C S-d S-D S-e S-E S-f S-F S-g S-G S-h S-H S-i S-I S-j S-J S-k S-K S-l S-L S-m S-M S-n S-N S-o S-O S-p S-P S-q S-Q S-r S-R S-s S-S S-t S-T S-u S-U S-v S-V S-w S-W S-x S-X S-y S-Y S-z S-Z

reversing this motion is easy

for m in {a..z} {A..Z} {0..9} ; do convert -reverse S-$m.gif R-$m.gif ; done
for m in 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 3A 3B 3C 3D 3E 3F 40 5B 5C 5D 5E 60 7B 7C 7D 7E ; do convert -reverse S-$m.gif R-$m.gif ; done

R-0 R-1 R-2 R-3 R-4 R-5 R-6 R-7 R-8 R-9 R-21 R-22 R-23 R-24 R-25 R-26 R-27 R-28 R-29 R-2A R-2B R-2C R-2D R-2E R-2F R-3A R-3B R-3C R-3D R-3E R-3F R-40 R-5B R-5C R-5D R-5E R-60 R-7B R-7C R-7D R-7E R-a R-A R-b R-B R-c R-C R-d R-D R-e R-E R-f R-F R-g R-G R-h R-H R-i R-I R-j R-J R-k R-K R-l R-L R-m R-M R-n R-N R-o R-O R-p R-P R-q R-Q R-r R-R R-s R-S R-t R-T R-u R-U R-v R-V R-w R-W R-x R-X R-y R-Y R-z R-Z


use multiple fonts

we can use multiple fonts in our for loop, i've included a few nerd fonts in the font folder of this repo, for the simplicity and ease of use the names have been removed for this following command and i only use the two digit numbers at the beginning

for i in {a..z} {A..Z} {0..9} ; for f in *.ttf ; do convert -gravity center -trim -background grey75 -fill grey25 -font ./$f -size 30x30 caption:$i -extent 30x30 $i-$f.jpg ; done
for char in {\!..\)} \@ \` {\*..\/} {\:..\?} {\[..\^} {\{..\~} ; for f in *.ttf ; do printf -v hex '%02X' $(( #char )) ; convert -gravity center -trim -background grey75 -fill grey25 -font ./$f -size 30x30 -extent 30x30 caption:$char $hex-$f.jpg ; done

convert the image sequences, using a longer delay of 16

for m in {a..z} {A..Z} {0..9} ; do convert -delay 16 $(ls -v $m-*.jpg) F-$m.gif ; done
for m in 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 3A 3B 3C 3D 3E 3F 40 5B 5C 5D 5E 60 7B 7C 7D 7E ; do convert -delay 16 $(ls -v $m-*.jpg) F-$m.gif ; done

F-0 F-1 F-2 F-3 F-4 F-5 F-6 F-7 F-8 F-9 F-21 F-22 F-23 F-24 F-25 F-26 F-27 F-28 F-29 F-2A F-2B F-2C F-2D F-2E F-2F F-3A F-3B F-3C F-3D F-3E F-3F F-40 F-5B F-5C F-5D F-5E F-60 F-7B F-7C F-7D F-7E F-a F-A F-b F-B F-c F-C F-d F-D F-e F-E F-f F-F F-g F-G F-h F-H F-i F-I F-j F-J F-k F-K F-l F-L F-m F-M F-n F-N F-o F-O F-p F-P F-q F-Q F-r F-R F-s F-S F-t F-T F-u F-U F-v F-V F-w F-W F-x F-X F-y F-Y F-z F-Z


change character position

with every example so far we've been trying to keep the character at the center of the image using -gravity center but we can change the position and make a motion out of it, the -gravity flags takes 9 alignment positions using center, north, northeast and etc, so lets loop all of the 9 positions in a for loop

for i in {a..z} {A..Z} {0..9} ; for g in northwest north northeast west center east southwest south southeast ; do convert -gravity $g -trim -background green -fill yellow -font ./nerd.ttf -size 30x30 caption:$i -extent 30x30 $i-$g.jpg ; done
for char in {\!..\)} \@ \` {\*..\/} {\:..\?} {\[..\^} {\{..\~} ; for g in northwest north northeast west center east southwest south southeast ; do printf -v hex '%02X' $(( #char )) ; convert -gravity $g -trim -background green -fill yellow -font ./nerd.ttf -size 30x30 -extent 30x30 caption:$char $hex-$g.jpg ; done

these two commands give us the character and the position they are after as filenames

northwest north northeast
west center east
southwest south southeast

now we need to decide the direction of our motion and change these filenames accordingly, i want a normal clockwise motion from northwest to west so we'll rename these files one by one and pad the next number after them, here is the first example which changes every filename that has northwest in it to 1 which is the first frame in each of our gifs

for i in *-northwest.jpg ; do mv "$i" "${i/northwest/1}" ; done

same command can be used for the next positions, or better yet, do it all in one giant command!

for i in *-northwest.jpg ; do mv "$i" "${i/northwest/1}" ; done 
for i in *-north.jpg ; do mv "$i" "${i/north/2}" ; done
for i in *-northeast.jpg ; do mv "$i" "${i/northeast/3}" ; done
for i in *-east.jpg ; do mv "$i" "${i/east/4}" ; done
for i in *-southeast.jpg ; do mv "$i" "${i/southeast/5}" ; done
for i in *-south.jpg ; do mv "$i" "${i/south/6}" ; done
for i in *-southwest.jpg ; do mv "$i" "${i/southwest/7}" ; done
for i in *-west.jpg ; do mv "$i" "${i/west/8}" ; done

we take the opportunity to remove the unwanted center pictures since we don't need them anymore, depending on the motion you desire you might want to keep these or remove even more of these positions or don't even include them in your for loops

rm *-center.jpg

now convert these images to gifs

for m in {a..z} {A..Z} {0..9} ; do convert $(ls -v $m-*.jpg) ge-$m.gif ; done 
for m in 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 3A 3B 3C 3D 3E 3F 40 5B 5C 5D 5E 60 7B 7C 7D 7E ; do convert $(ls -v $m-*.jpg) ge-$m.gif ; done

ge-0 ge-1 ge-2 ge-3 ge-4 ge-5 ge-6 ge-7 ge-8 ge-9 ge-21 ge-22 ge-23 ge-24 ge-25 ge-26 ge-27 ge-28 ge-29 ge-2A ge-2B ge-2C ge-2D ge-2E ge-2F ge-3A ge-3B ge-3C ge-3D ge-3E ge-3F ge-40 ge-5B ge-5C ge-5D ge-5E ge-60 ge-7B ge-7C ge-7D ge-7E ge-a ge-A ge-b ge-B ge-c ge-C ge-d ge-D ge-e ge-E ge-f ge-F ge-g ge-G ge-h ge-H ge-i ge-I ge-j ge-J ge-k ge-K ge-l ge-L ge-m ge-M ge-n ge-N ge-o ge-O ge-p ge-P ge-q ge-Q ge-r ge-R ge-s ge-S ge-t ge-T ge-u ge-U ge-v ge-V ge-w ge-W ge-x ge-X ge-y ge-Y ge-z ge-Z


use glyphs/emojis

in a few of the examples above i've mentioned using one of a nerd fonts which are a collection of 50+ free and open source fonts that are patched with 3600+ icons, using them is quite easy, just check their cheat sheet and search for the string you like, when you found a glyph you like hover over it and click on the icon name to copy the glyph to your clipboard

now that we have a few of the icons we like, we can print them using convert

for i in  ﱘ      ; do convert -gravity center -trim -background grey25 -fill orange -font ./nerd.ttf -size 40x40 caption:$i -extent 30x30 $i.jpg ; done 

don't worry if your terminal emulator or web browser is not capable of showing these icons, our font is patched with them and imagemagick is going to print them just fine, notice that we set -size to 40x40 but used -extent 30x30 to make the pictures smaller, this is because these glyphs have some white space around them and because we are working with such small pixel sizes we want to take advantage of the small screen realstate as much as possible

these filenames look kind of weird on your filesystem, so lets change them to be able to use them without any issues

A=1 ; for i in *.jpg ; do mv $i glyph-$[A].jpg ; A=$(( $A + 1 )) ; done

1 2 3 4 5 6 7

how about some arrows

8 9 10 11 12 13 14 15

lock and key

16 17 18 19 20

if for whatever reason you are not able to use a glyph icon directly inside your terminal you can also use the hex value of a glyph like this, just add \u before the actual 4 digit hex glyph to let the shell know what it is

for i in $(echo -e '\ufc58') ; do convert -gravity center -trim -background grey25 -fill orange -font ./nerd.ttf -size 40x40 caption:$i -extent 30x30 $i.jpg ; done

this echo command inside our for loop acts exactly as if we supplied the glyph itself

printing multiple hex glyps is also easy, just include them inside our echo command and separate each with quotes

for i in $(echo -e '\ufc58' '\uf832' '\ufc59') ; do convert -gravity center -trim -background grey25 -fill orange -font ./nerd.ttf -size 40x40 caption:$i -extent 30x30 $i.jpg ; done

gotta print them all!

what if i want to print every nerd font glyphs in one command? well, we can do that no problem, i've scraped all of the hex values of these glyphs from this css file provided by the nerd-fonts repo and included them in the root folder of this repo here, now we just need to echo them one by one and feed them to imagemagick

for i in $(echo -e $(cat nerd-glyphs.txt)) ; do convert -gravity center -trim -background grey25 -fill orange -font ./nerd.ttf -size 90x90 caption:$i -extent 80x80 $i.jpg ; done

if you are on linux you should be ok with glyphs as filenames and it will make them very easy to find but for cross platform compatibility lets rename these files with the command i've showed above

A=1 ; for i in *.jpg ; do mv $i glyph-$[A].jpg ; A=$(( $A + 1 )) ; done

because there is so many images (3689) i'm not going to link them here but i'll include them as a zip file in the root directory of this repo


generate random hex colors and use them

making a list of random colors is easy, i just did a quick search and found this page that has the answer, it does work but we want a list of 100 hex colors so we want to use it in a for loop

for i in {1..100} ; do printf "%02x%02x%02x\n" $((RANDOM%256)) $((RANDOM%256)) $((RANDOM%256)) >> colors.txt ; done

this command saves 100 randomized color values to the colors.txt text file, notice the use of >> if we only used > the text file would have be overwritten each time and would only contain one hex value, now lets use these newly made hex values as background colors for our images

for i in $(cat colors.txt) ; do convert -gravity center -trim -background \#$i -fill black -font ./nerd.ttf -size 30x30 caption:A -extent 30x30 $i.jpg ; done

the backslash \ is used to escape the hashtag # sign which normally comments out everything after it but we want to use it to tell imagemagick we are going to use a hex color value as background color

the same colors can be used as the color of our characters, it looks very different with a simple background color inversion

for i in $(cat colors.txt) ; do convert -gravity center -trim -background white -fill \#$i -font ./nerd.ttf -size 30x30 caption:A -extent 30x30 $i.jpg ; done


hex color values as text captions

using the same command as above, create the list of 100 random hex colors, now use these hex values as the caption of the image too, because the string is longer lets make the images 90x30 pixels

for i in $(cat colors.txt) ; do convert -gravity center -trim -background \#$i -fill black -font ./nerd.ttf -size 90x30 caption:\#$i -extent 90x30 $i.jpg ; done

same colors on a dark background

for i in $(cat colors2.txt) ; do convert -gravity center -trim -background \#222222 -fill \#$i -font ./nerd.ttf -size 90x30 caption:\#$i -extent 90x30 $i.jpg ; done


add border to characters

adding border is easy, specify it's width with -border and it's color with -bordercolor this normally applies to the frame of the image but since we are apply trim to these characters to make them center to border starts to wrap around the character

for i in {a..z} {A..Z} {0..9} ; for s in {1..10..2} ; do convert -gravity center -trim -background yellow -fill black -border $s -bordercolor orange -font ./nerd.ttf -size 30x30 caption:$i -extent 30x30 $i-$s.jpg ; done
for char in {\!..\)} \@ \` {\*..\/} {\:..\?} {\[..\^} {\{..\~} ;  for s in {1..10..2}  ; do printf -v hex '%02X' $(( #char )) ; convert -gravity center -trim -background yellow -fill black -border $s -bordercolor orange -font ./nerd.ttf -size 30x30 -extent 30x30 caption:$char $hex-$s.jpg ; done

now convert the images to gifs

for m in {a..z} {A..Z} {0..9} ; do convert $(ls -v $m*.jpg) B-$m.gif ; done
for m in 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 3A 3B 3C 3D 3E 3F 40 5B 5C 5D 5E 60 7B 7C 7D 7E ; do convert $(ls -v $m*.jpg) B-$m.gif ; done

reverse the frames in these gifs

for m in {a..z} {A..Z} {0..9} ; do convert -reverse B-$m.gif C-$m.gif ; done
for m in 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 3A 3B 3C 3D 3E 3F 40 5B 5C 5D 5E 60 7B 7C 7D 7E ; do convert -reverse B-$m.gif C-$m.gif ; done  

now combine both sets of gifs

for m in {a..z} {A..Z} {0..9} ; do convert -adjoin B-$m.gif C-$m.gif D-$m.gif ; done
for m in 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 3A 3B 3C 3D 3E 3F 40 5B 5C 5D 5E 60 7B 7C 7D 7E ; do convert -adjoin B-$m.gif C-$m.gif D-$m.gif ; done

D-0 D-1 D-2 D-3 D-4 D-5 D-6 D-7 D-8 D-9 D-21 D-22 D-23 D-24 D-25 D-26 D-27 D-28 D-29 D-2A D-2B D-2C D-2D D-2E D-2F D-3A D-3B D-3C D-3D D-3E D-3F D-40 D-5B D-5C D-5D D-5E D-60 D-7B D-7C D-7D D-7E D-a D-A D-b D-B D-c D-C D-d D-D D-e D-E D-f D-F D-g D-G D-h D-H D-i D-I D-j D-J D-k D-K D-l D-L D-m D-M D-n D-N D-o D-O D-p D-P D-q D-Q D-r D-R D-s D-S D-t D-T D-u D-U D-v D-V D-w D-W D-x D-X D-y D-Y D-z D-Z

and the inverted variants

for m in {a..z} {A..Z} {0..9} ; do convert -negate D-$m.gif E-$m.gif ; done
for m in 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 3A 3B 3C 3D 3E 3F 40 5B 5C 5D 5E 60 7B 7C 7D 7E ; do convert -negate D-$m.gif E-$m.gif ; done

E-0 E-1 E-2 E-3 E-4 E-5 E-6 E-7 E-8 E-9 E-21 E-22 E-23 E-24 E-25 E-26 E-27 E-28 E-29 E-2A E-2B E-2C E-2D E-2E E-2F E-3A E-3B E-3C E-3D E-3E E-3F E-40 E-5B E-5C E-5D E-5E E-60 E-7B E-7C E-7D E-7E E-a E-A E-b E-B E-c E-C E-d E-D E-e E-E E-f E-F E-g E-G E-h E-H E-i E-I E-j E-J E-k E-K E-l E-L E-m E-M E-n E-N E-o E-O E-p E-P E-q E-Q E-r E-R E-s E-S E-t E-T E-u E-U E-v E-V E-w E-W E-x E-X E-y E-Y E-z E-Z


add stroke to characters

stroke is not additive to the overal size of our characters but it devours them, we can work with and make a cool effect using -stroke for color and -strokewidth for it's width, this flag also takes negative numbers so making a back and forth motion is easy to do with one command

for i in {a..z} {A..Z} {0..9} ; for s in {3..-3} ; do convert -gravity center -trim -background grey50 -fill yellow -strokewidth $s -stroke orange -font ./nerd.ttf -size 30x30 caption:$i -extent 30x30 $i-$s.jpg ; done
for char in {\!..\)} \@ \` {\*..\/} {\:..\?} {\[..\^} {\{..\~} ; for s in {3..-3} ; do printf -v hex '%02X' $(( #char )) ; convert -gravity center -trim -background grey50 -fill yellow -strokewidth $s -stroke orange -font ./nerd.ttf -size 30x30 -extent 30x30 caption:$char $hex-$s.jpg ; done

convert them

for m in {a..z} {A..Z} {0..9} ; do convert $(ls -v $m*.jpg) ST-$m.gif ; done 
for m in 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 3A 3B 3C 3D 3E 3F 40 5B 5C 5D 5E 60 7B 7C 7D 7E ; do convert $(ls -v $m*.jpg) ST-$m.gif ; done

ST-0 ST-1 ST-2 ST-3 ST-4 ST-5 ST-6 ST-7 ST-8 ST-9 ST-21 ST-22 ST-23 ST-24 ST-25 ST-26 ST-27 ST-28 ST-29 ST-2A ST-2B ST-2C ST-2D ST-2E ST-2F ST-3A ST-3B ST-3C ST-3D ST-3E ST-3F ST-40 ST-5B ST-5C ST-5D ST-5E ST-60 ST-7B ST-7C ST-7D ST-7E ST-a ST-A ST-b ST-B ST-c ST-C ST-d ST-D ST-e ST-E ST-f ST-F ST-g ST-G ST-h ST-H ST-i ST-I ST-j ST-J ST-k ST-K ST-l ST-L ST-m ST-M ST-n ST-N ST-o ST-O ST-p ST-P ST-q ST-Q ST-r ST-R ST-s ST-S ST-t ST-T ST-u ST-U ST-v ST-V ST-w ST-W ST-x ST-X ST-y ST-Y ST-z ST-Z

About

character animations for learning some imagemagick