Erroneous Calculation in Blend Animation Script-Fu
Submitted by Thomas Schustek
Link to original bug (#696562)
Description
Created attachment 239776 blend-anim.scm.patch
Abstract
The GIMP extension coded in scheme script blend-anim.scm for creating an animation by blending key frames does a good job but in a little erroneous way. This can easily be demonstated by blending two identical layers over a highly contrasting background. Therefore I have implemented a new blending procedure into the original script, which may be accessed via image layer menu when uncommenting its framework procedure along with its register procedures calls.
Description
It may sound weird when someone tells you that he has found a fundamental mistake in a piece of software that has been written 14 years ago, distributed as readable code millions of times, and experienced of at least tens of thousands of users since then. But indeed, I do.
The Script-Fu-procedure script-fu-blend-anim coded in the scheme script blend-anim.scm that I have got as part of the GIMP 2.6.12 package on an Ubuntu 12.04.1 LTS give-away-dvd and which seems not to have changed up to now ought to blend two key frames of an animation over a background layer weighted by a blend value named opacity and 100 minus the blend value respectively:
(gimp-drawable-set-visible upper-copy TRUE) (gimp-drawable-set-visible lower-copy TRUE) (gimp-drawable-set-visible bg-copy TRUE)
(...)
(gimp-layer-set-opacity upper-copy (- 100 opacity)) (gimp-layer-set-opacity lower-copy opacity) (gimp-layer-set-opacity bg-copy 100)
(...)
(let* ((merged-layer (car (gimp-image-merge-visible-layers image CLIP-TO-IMAGE)))) (gimp-drawable-set-visible merged-layer FALSE))
But merging these three layers in this way results in a pixel value of ( ( 100 - blend-value ) x upper-layer-pixel-value + blend-value x ( blend-value x lower-layer-pixel-value + ( 100 - blend-value ) x background-pixel-value ) / 100 ) / 100 which differs from the intended combination. This can be easily demonstrated with two identical layers blended over a background of high contrast, e.g. a dark sprite before a bright or transparent plane or vice versa a bright sprite over a dark background.
Merging the upper layer whose opacity value is set to the desired blend value with a layer beneath set to an opacity value of 100 gives the correct result and works fine as long as there are no transparent regions to deal with. Merging a transparent upper layer or area within this layer with a entirely opaque lower layer gives the latter or its corresponding area no matter what opacity value you choose for the upper layer.
Since I could not find a compute-image-function like in Adobe Photoshop to get a linear combination of two layers handling the alpha channel in the same way as the GRAY or RGB channels, not even a procedure to access the fade function of the GIMP image edit menu I have written a new procedure which blends the alpha channels of two layers as masks separately from the other channels and recombines the resulting mask with the merged layers which have become wholly opaque after they have been stripped off of their alpha channels. Beside this, the blending operation is now commutative and also can be used without a background layer to create partially transparent sprite animations.
It may be in some way irritating that if fading in a first sprite animation key frame beginning with an entirely transparent key frame the effective pixel intensities rise quadratic with respect to time but this is exactly what it is expected to do since the pixels' opacity values in the alpha channels increase linear in time as well as their color values in the RGB channels do. This effect does only show up in regions where the pixels' opacity values vary from frame to frame.
The new blending procedure named blend-down has been implemented into the original code with only as much as changes as necessary and can be accessed via image layer menu when the framework procedure script-fu-image-blend-down and its register procedures calls are uncommented.
Patch 239776, "blend-anim.scm.patch":
blend-anim.scm.patch
Version: 2.8.14