GIF transition from image to transparent

Questions and postings pertaining to the usage of ImageMagick regardless of the interface. This includes the command-line utilities, as well as the C and C++ APIs. Usage questions are like "How do I use ImageMagick to create drop shadows?".
Post Reply
flashydra
Posts: 2
Joined: 2019-07-21T07:43:09-07:00
Authentication code: 1152

GIF transition from image to transparent

Post by flashydra »

Setup:
  • CentOS release 6.10 (Final)
  • ImageMagick (version 7.0.8-55)
  • VipLibs-8.8.1
I'm trying to produce a GIF animation from an input image (PNG, JPEG, etc). A "disintegration" effect is applied to the input image. This effect is achieved using Fred's transition script shown here. I am using the one all the way at the bottom, where it says

Code: Select all

-m dissolve -f 21 -d 10 -p 10 -e
With a white background, it looks okay:
Image

But the effect simply isn't the same if the background doesn't match. For example:
Image

Yikes! So, I want the transition image to be transparent. In other words, I want the original image to look like it's "disappearing". I'm still new to IM (only 2 days in so far, but I'm picking it up fast!), so I don't fully understand compositing and the likes. I've been scouring over the usage guide to learn as much as I can, but I've hit a wall.

One idea I've had is that maybe I could generate the transition image using the default:

Code: Select all

-transparent-color #00000000
and using

Code: Select all

magick -size 50x50 canvas:"#00000000" alpha.png
with the intent of transitioning from the original image to this transparent black image (which, as a GIF, will be transparent) giving the appearance that it is "disappearing".

I don't know if this is the best solution, or is even a rational way to do this. In any case, I haven't had any luck, as the GIF does not appear to have any effects. However, ExifTool reports that the GIF does contain all 50 frames. My theory is that the transparent image is first being converted to its transparent form, then composited with the original frame and therefore no effect is displayed. But, it's just a theory.

I would greatly appreciate some help figuring out what's going on and how to achieve the effect I'm looking for. :D
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: GIF transition from image to transparent

Post by fmw42 »

Please post your full imagemagick command line and your original GIF animation. GIF does not support partial transparency. So that will not work to save as GIF. It will be either all one image or the other.

I can get this to work saving as multipage TIFF, but not with GIF. It uses subshell processing to avoid saving multiple temp files.

Code: Select all

(
for ((i=0; i<20; i++)); do
j=$((100*i/19))
convert lena.png \( -size 256x256 xc:none \) -alpha on -channel rgba -define compose:args=$j -compose blend -composite miff:-
done 
) | convert - x.tiff
Bodhi579
Posts: 1
Joined: 2019-07-21T22:42:31-07:00
Authentication code: 1152

Re: GIF transition from image to transparent

Post by Bodhi579 »

That code does work perfectly.
flashydra
Posts: 2
Joined: 2019-07-21T07:43:09-07:00
Authentication code: 1152

Re: GIF transition from image to transparent

Post by flashydra »

TIFF will not work at all for what I am doing, and does not even produce what the desired effect which is an animation. I also understand that GIF does not support partial transparency. I don't want partial transparency. I want the supplied image, to appear like it is crumbling to dust. The final frame of the GIF should be completely transparent. Did you see the GIFs I posted?

I used the following PNG image:
Image

Here is the script I am using to transform the above PNG:

Code: Select all

#!/bin/bash
mode="wipe"
frames=50
delay=2
pause=5
mask="linear"
reverse="no"
view="no"

# set directory for temporary files
dir="."    # suggestions are dir="." or dir="/tmp"

# get infile and outfile
infile1="thanos3.png"
infile2="alpha.png"
maskfile="maskfile3.png"
outfile="snapped2.gif"

# set temporary files
tmpA="$dir/transitions_1_$$.mpc"
tmpB="$dir/transitions_1_$$.cache"
tmpC="$dir/transitions_2_$$.mpc"
tmpD="$dir/transitions_2_$$.cache"
tmpE="$dir/transitions_3_$$.mpc"
tmpF="$dir/transitions_3_$$.cache"
tmp0="$dir/transitions_0_$$.gif"
trap "rm -f $tmpA $tmpB $tmpC $tmpD $tmpE $tmpF $tmp0;" 0
trap "rm -f $tmpA $tmpB $tmpC $tmpD $tmpE $tmpF $tmp0; exit 1" 1 2 3 15
trap "rm -f $tmpA $tmpB $tmpC $tmpD $tmpE $tmpF $tmp0; exit 1" ERR

if magick -quiet "$infile1" +repage "$tmpA"
	then
	: ' Do Nothing '
else
	errMsg "--- FILE $infile DOES NOT EXIST OR IS NOT AN ORDINARY FILE, NOT READABLE OR HAS ZERO SIZE ---"
fi

if magick -quiet "$infile2" +repage "$tmpC"
	then
	: ' Do Nothing '
else
	errMsg "--- FILE $infile DOES NOT EXIST OR IS NOT AN ORDINARY FILE, NOT READABLE OR HAS ZERO SIZE ---"
fi

if [ "$mask" = "exponential" ]
	then
	# exponentiate mask so that transition does not show much of second image too early
	if magick -quiet "$maskfile" -fx "(10^(u)-1)/9" +repage "$tmpE"
		then
		: ' Do Nothing '
	else
		errMsg "--- FILE $infile DOES NOT EXIST OR IS NOT AN ORDINARY FILE, NOT READABLE OR HAS ZERO SIZE ---"
	fi
elif [ "$mask" = "linear" ]
	then
	if magick -quiet "$maskfile" +repage "$tmpE"
		then
		: ' Do Nothing '
	else
		errMsg "--- FILE $infile DOES NOT EXIST OR IS NOT AN ORDINARY FILE, NOT READABLE OR HAS ZERO SIZE ---"
	fi
fi

# check image sizes
w1=`magick $tmpA -format "%w" info:`
h1=`magick $tmpA -format "%h" info:`
w2=`magick $tmpC -format "%w" info:`
h2=`magick $tmpC -format "%h" info:`
w3=`magick $tmpE -format "%w" info:`
h3=`magick $tmpE -format "%h" info:`
[ $w1 -ne $w2 -a $h1 -ne $h2 -a $w1 -ne $w3 -a $h1 -ne $h3 ] && errMsg "--- IMAGE SIZES DO NOT MATCH ---"

# test if hdri and if so limit addition to 100% (white)
is_hdri=`magick -list configure | \
	sed -n 's/^.*--enable-hdri.*$/1/p'`
if [ "$is_hdri" != "" ]
	then
	min="-evaluate min 100%"
else
	min=""
fi
echo "min=$min"

echo ""
echo "Generating $frames Frames:"
echo ""

frames=`expr $frames - 1`
echo "0"
i=1
magick $tmpA $tmp0
while [ $i -le $frames ]
	do
	echo $i
	tt=`magick xc: -format "%[fx:100($frames-$i)/$frames]" info:`
	magick $tmpA $tmpC \( $tmpE -threshold $tt% \) -composite miff:- |\
		magick -delay $delay $tmp0 -page +0+0 - -page +0+0 $tmp0
	i=`expr $i + 1`
done

# change delay of first and last image
if [ $pause -ne $delay ]
	then
	magick $tmp0 -coalesce \
		\( -clone 0 -set delay $pause \) -swap 0,-1 +delete \
		\( +clone  -set delay $pause \) -swap -1,-2 +delete \
		-quiet -layers Optimize $tmp0
fi

magick $tmp0 -loop 0 "$outfile"
exit 0
That produces the following GIF image:
Image
Not what I want. What I'm looking for is a GIF that removes pixels frame by frame, in the pattern supplied by the mask file, with the end frame fully transparent, so something like this:
Image
User avatar
GeeMack
Posts: 718
Joined: 2015-12-01T22:09:46-07:00
Authentication code: 1151
Location: Central Illinois, USA

Re: GIF transition from image to transparent

Post by GeeMack »

flashydra wrote: 2019-07-22T00:34:03-07:00I want the supplied image, to appear like it is crumbling to dust. The final frame of the GIF should be completely transparent.
This command will start with your image of the face, create a multi-step mask using a "plasma:" canvas to simulate the crumbling, and composite those masks sequentially over the main input to create increasing amounts of transparency.

Code: Select all

magick input.png -background none -size %[w]x%[h] null: \
   \( plasma:gray-gray -duplicate 11 -threshold %[fx:t*100/n]% \) -alpha off \
   -compose copyalpha -layers composite -set delay 20 -set dispose background output.gif
The animation will be 12 frames. Increase the "-duplicate N" to increase the number of steps in the mask. The first frame will be the entire input image. The last frame will be completely transparent.

Edited to add: Within the same command you can easily set different delays for the first and last frames. To set the delay individually for the first frame, add this after the "-set delay N"...

Code: Select all

 \( -clone 0 -set delay N \) -delete 0 -insert 0 
To set the delay of the last frame, add this after the "-set delay N"...

Code: Select all

 \( -clone -1 -set delay N \) -delete -2 
Substitute whatever delay values you like for the "N" in the above settings.
Last edited by GeeMack on 2019-07-22T14:09:03-07:00, edited 2 times in total.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: GIF transition from image to transparent

Post by fmw42 »

Seems like my correction post got lost. Here is pretty much what you want, I think. Let me know.

All I do is threshold the randomized image at increments and put it into the alpha channel of the input.

Input:
Image

Randomized grayscale Image:
Image

Subshell Processing to avoid saving tmp files:

Code: Select all

(
for ((i=0; i<20; i++)); do
j=$((100*i/19))
convert flower.jpg  \( random.jpg -threshold $j% \) -alpha off -compose copy_opacity -composite miff:-
done 
) | convert -dispose background -delay 20 - -loop 0 flower_random_anim.gif
Image

Please reply to my private message to you on this forum.
Post Reply