I just want to share how I did the above effect in G’MIC & GIMP. It’s sometimes called a plotagraph (you need a freemium app for that) and it works on a single image, instead of a cinegraph which is from a short movie. Let’s see how you can do it in Open Source Software.
Open your image in GIMP. For this example, I am using ‘Cachoeira do Pacheco Venezuela 4.JPG’ from Wikimedia Commons. Scale it to your preference (and your system capabilities). I scaled it 800x600 here. Duplicate the layer because you will be morphing the image into itself. Then open Filters->G’MIC-QT.
Choose Deformations->Morph [Interactive]. Here I kept it at 16 frames, but for ‘Output mode’, I changed it to ‘New image’, to avoid replacing the original layers. Click OK to start the interface. Please familiarize yourself with it (perhaps morph some faces beforehand) as I won’t go into the details. For the keypoints, try not to make large displacements, in fact a few small ones are sometimes enough. Don’t cross the streams! See (i) in keypoint image at the end below.
After you’ve placed the keypoints, press Esc or Q for G’MIC to work on it, and you will have 16 layers (named Morphing #0 to #15) in your new image. Open Filters->Animation->Playback to see how the morph turned out. This is how it looks as an animated GIF with the default export settings of 100ms delay between frames (see notes below for other formats):
So everything is moving (except the fixed corners). Also, since layer #0 and #15 are the same, it looks like there is a pause, which we can eliminate by deleting layer #15, which I will do for other animations. Go back to your original 2 layers, and open the Morph interface again. This time try to place fixed keypoints for parts of the image which should not move. Not only must you put it on the edge of the moving area, but you might have to place quite a few beyond it. See (ii) where there are lot of fixed keypoints.
If you export it, there might still be some movement, because it is quite difficult to place the fixed keypoints. So instead, you can mask the animation. You have to do it after generating the new image, because having a selection before going into G’MIC will crop the image instead. Working on transparent layers in Morph will produce strange edge artefacts, so you have to work with a full image.
After getting your new image, start by creating a selection for where you want to the movement to be. I used Paths (then ‘Paths to Selection’ to create (iii). The Paths layer can be drag-copied to another image in case you want to re-use it. With the selection, mask every layer except the bottom layer by repeatedly doing Layers->Mask->Add Layer Mask->Selection->Add. Or you can use this script:
#!/usr/bin/python
from gimpfu import *
def layer_selection_mask_all_except_first(image):
pdb.gimp_image_undo_group_start(image) # for single history undo step
for layer in image.layers[:-1]: # from top to second last
mask = pdb.gimp_layer_create_mask(layer, ADD_MASK_SELECTION)
pdb.gimp_layer_add_mask(layer, mask)
pdb.gimp_image_undo_group_end(image)
register(
"python-fu-layer-selection-mask-all-except-first",
"Create masks from current selection on all layers except first",
"Create masks from current selection on all layers except first. Plugin will stop when it encounters a layer with a mask.",
"scribbleed", "scribbleed", "2020",
"Selection to mask all layers except first",
"*",
[(PF_IMAGE, "image", "Input image", None)],
[],
layer_selection_mask_all_except_first, menu="<Image>/Layer")
main()
Anyway, make sure the Playback and Export settings are set at ‘Cumulative layers (combine)’ and not at ‘One frame per layer (replace)’ for the masked layers to work. See the notes below if you are exporting it to other formats when you have masked layers. With a mask, you can reduce the keypoints, see (iv), by carefully placing some at the edge of the selection. You can also place text on the first layer outside the masked area. With (iii) and (iv), you will get the image at the start of this tutorial. Yay! (OK, I need to work harder to make a better mask).
Keypoint image:
You can also try to make a ‘walkalator’ effect. For this last example, I used the image ‘Abbey Road London.JPG’ from Wikimedia (straightened and cropped) with the keypoints and selection mask in (v) and (vi). I didn’t need fixed keypoints for this. But I placed some of the keypoints outside moving in and inside moving out of the selection area to make the movement more effective.
I hope you all will try this and create ever more stunning ‘gimpgraphs’ (‘gmicgraphs’?). Apologies as I could only post 4 images, and couldn’t get into more detailed images. Please improve on it and feel free to make your own tutorials from this. Just want to say a big ‘Thank You’ to the coders of GIMP and G’MIC (especially David), for keeping up the good work.
Notes:
- As of this tutorial, keypoints of Morph [Interactive] are not saved with the image (feature request?). You will lose them if you reset or close GIMP.
- The keypoints are proportionally placed on the picture. Therefore, you can work on a smaller image first, before committing to a bigger one.
- You might want to use the animation in other programs instead of a 256-color gif, so you might need individual frames or export to a movie from GIMP. Here are some options:
- MNG will loop like an animated GIF. If you Export as MNG, each transparent layer will already be merged in the exported file, and you can use ImageMagick to split it into frames (
convert animation.mng image%03d.png
). - WebP will also loop, but you have to first merge the transparent layers with a copy of the first layer before exporting.
- ORA, not a movie format, is basically a zip file of the layers in PNG format. You need to merge the transparent layers, otherwise, you will get unmasked layers without a mask. Do note the names in the data folder in the ORA file are reversed, e.g. 000.png = Morphing #15.
Here’s a script to merge the layers:
#!/usr/bin/python
from gimpfu import *
def layer_merge_all_with_first(image):
pdb.gimp_image_undo_group_start(image) # for single history undo step
n = len(image.layers) # no. of layers
if n > 1: # only if at least 2 layers
bottomlayer = image.layers[n-1]
pdb.gimp_item_set_visible(bottomlayer, TRUE) # to avoid merge errors
for i in range(n-1):
layercopy = pdb.gimp_layer_copy(bottomlayer, TRUE)
pdb.gimp_image_insert_layer(image, layercopy, None, i + 1) # insert copy below target
pdb.gimp_item_set_visible(image.layers[i], TRUE) # to avoid merge errors
layername = pdb.gimp_item_get_name(image.layers[i]) # to keep layer name
pdb.gimp_image_merge_down(image, image.layers[i], EXPAND_AS_NECESSARY)
pdb.gimp_item_set_name(image.layers[i], layername)
pdb.gimp_image_undo_group_end(image)
register(
"python-fu-layer-merge-all-with-first",
"Merge down each layer with a copy of the first layer",
"Merge down each layer with a copy of the first layer. All layers will be made visible. Layer names will be maintained.",
"scribbleed", "scribbleed", "2020",
"Merge each layer with first layer",
"*",
[(PF_IMAGE, "image", "Input image", None)],
[],
layer_merge_all_with_first, menu="<Image>/Layer")
main()
Have fun and be kind.