ConwayLife.com - A community for Conway's Game of Life and related cellular automata
Home  •  LifeWiki  •  Forums  •  Download Golly

Script for making animated gifs

For discussion directly related to ConwayLife.com, such as requesting changes to how the forums or wiki function.

Script for making animated gifs

Postby codeholic » March 13th, 2015, 6:06 pm

Mostly @Flipper77: which script did you use to make an animated gif of the pufferfish? Would you share it please?
Ivan Fomichev
User avatar
codeholic
Moderator
 
Posts: 1140
Joined: September 13th, 2011, 8:23 am
Location: Hamburg, Germany

Re: Script for making animated gifs

Postby flipper77 » March 13th, 2015, 6:37 pm

I wish I had a script to do such a thing, all I'm doing is using an online gif maker to make them using "prt sc" for each frame, which isn't an ideal way to do it, since it takes a lot of time to do it, there's one in the golly scripts thread, but I doesn't have gridlines, which is why I'm not using that.
User avatar
flipper77
 
Posts: 197
Joined: October 24th, 2010, 3:25 am
Location: Spokane, WA

Re: Script for making animated gifs

Postby codeholic » March 13th, 2015, 6:41 pm

Would you please give a link? Adding gridlines should not be that hard.
Ivan Fomichev
User avatar
codeholic
Moderator
 
Posts: 1140
Joined: September 13th, 2011, 8:23 am
Location: Hamburg, Germany

Re: Script for making animated gifs

Postby flipper77 » March 13th, 2015, 6:44 pm

Here it is, Scorbie made it based off the perl version: http://www.conwaylife.com/forums/viewtopic.php?f=9&t=45&start=100#p17015
User avatar
flipper77
 
Posts: 197
Joined: October 24th, 2010, 3:25 am
Location: Spokane, WA

Re: Script for making animated gifs

Postby Scorbie » March 13th, 2015, 8:35 pm

There's a URL link in the script that could help you when you're stuck.
Velcrorex's avatar seems to deal well with moving objects. Maybe he might have something too.
By the way, how did people make all those gifs in LifeWiki? A script? Is there a source?
Best wishes to you, Scorbie
User avatar
Scorbie
 
Posts: 1350
Joined: December 7th, 2013, 1:05 am

Re: Script for making animated gifs

Postby velcrorex » March 13th, 2015, 9:40 pm

I took the animated gif from the lifewiki page on the loafer and resized it using an online service so the file would be small enough to use for my avatar.
-Josh Ball.
User avatar
velcrorex
 
Posts: 339
Joined: November 1st, 2009, 1:33 pm

Re: Script for making animated gifs

Postby calcyman » March 13th, 2015, 10:24 pm

I opted for animated SVGs for Catagolue since they're inline, scalable and efficient.

If your object fits into a 40-by-40 box (and is an oscillator or spaceship), the easiest way to retrieve it is to run canonise() and look at the corresponding object page, such as:

http://catagolue.appspot.com/object/xq7 ... 6952/b3s23

You can then click 'view source' and embed the HTML (demarcated by the svg tags) into any webpage.

I suppose I could create a Golly script to perform a similar function if necessary.
What do you do with ill crystallographers? Take them to the mono-clinic!
User avatar
calcyman
 
Posts: 1628
Joined: June 1st, 2009, 4:32 pm

Re: Script for making animated gifs

Postby Extrementhusiast » March 13th, 2015, 11:22 pm

Scorbie wrote:By the way, how did people make all those gifs in LifeWiki? A script? Is there a source?


Those, including mine, were made during the time that conwaylife.com had a Java applet. The applet had contained an option to save a pattern animation as a GIF.
I Like My Heisenburps! (and others)
User avatar
Extrementhusiast
 
Posts: 1700
Joined: June 16th, 2009, 11:24 pm
Location: USA

Re: Script for making animated gifs

Postby codeholic » March 14th, 2015, 3:35 am

calcyman wrote:I opted for animated SVGs for Catagolue since they're inline, scalable and efficient.

It is actually a very nice idea. I guess, generating SVG must be easier than making animated GIFs. I will try to restyle it so than it has the same look as other uploaded patterns on LifeWiki (i. e. black-on-white with gray gridlines). Then we just need to ask Nathaniel to allow uploading of SVG on the wiki.
Ivan Fomichev
User avatar
codeholic
Moderator
 
Posts: 1140
Joined: September 13th, 2011, 8:23 am
Location: Hamburg, Germany

Re: Script for making animated gifs

Postby Scorbie » March 14th, 2015, 10:33 am

codeholic wrote:Then we just need to ask Nathaniel to allow uploading of SVG on the wiki.
And possibly our avatars.

On the other hand, I wonder if I could get a source code of the gif part of the java applet. Maybe we could possibly translate it into python. (Mostly because IE doesn't support SVG animation. Darn!)

Oh and one more thing. Is it possible to display the pattern animation/glider synth/rle etc on the same window of the pattern page or a small popup dialog? I think that's MUCH better than clicking a link to the rle and going back again to browse other patterns.
Best wishes to you, Scorbie
User avatar
Scorbie
 
Posts: 1350
Joined: December 7th, 2013, 1:05 am

Re: Script for making animated gifs

Postby Scorbie » March 15th, 2015, 2:41 am

I proudly present the new version of the giffer.py with support of gridlines and moving objects.
EDIT: The signs of the velocity follows the golly convention.
EDIT2: Changed the grid width to 2px and gray color to C6C6C6(LifeWiki Gray) as flipper77's suggestion.
# Runs the current selection for a given number of steps and
# creates a black and white animated GIF file.
# Based on giffer.pl, which is based on code by Tony Smith.

import golly as g
import os
import struct

rect=g.getselrect()
if len(rect)==0:
    g.exit("Nothing in selection.")
[x,y,width,height]=rect
if(width>=65536 or height>=65536):
    g.exit("The width or height of the GIF file must be less than 65536 pixels.")

frames = pause = cellsize = gridwidth = vx = vy = filename = "?"
gridwidth = "2"
def getparam(msg):
    info = "Current parameters:\n"\
        +"The number of frames: "+frames+"\n"\
        +"The pause time of each frame: "+pause+"centisecs\n"\
        +"The size of each cell: "+cellsize+"px\n"\
        +"(The width of gridlines: "+gridwidth+"px -- fixed)\n"\
        +"The speed of the pattern: "+"("+vx+","+vy+")px/frame\n"\
        +"The file name: "+filename+"\n\n"
    return g.getstring(info+msg, "", "Create animated GIF")
frames = getparam("Enter the number of frames.")         
pause = getparam("Enter the pause time of each frame (in centisecs.)")
cellsize = getparam("Enter the size of each cell (in pixels.)")
# GridLines are 2 pixels in LifeWiki gif format.
# gridwidth = getparam("Enter the width of gridlines (in pixels, 0 to disable.)")
vx, vy = getparam("Enter the speed of the pattern (in pixels per frame.)\n ex)(-3,5)px/frame -> -3 5").split()
filename = getparam("Enter the file name. ex)out.gif")
   
def tryint(var, name):
    try:
        return int(var)
    except:
        g.exit(name + " is not an integer: " + var)
frames = tryint(frames, "Number of frames")
pause = tryint(pause, "Pause time")
cellsize = tryint(cellsize, "Cell Size")
gridwidth = tryint(gridwidth, "Grid Width")
vx = tryint(vx, "X velocity")
vy = tryint(vy, "Y velocity")
canvasheight = (cellsize+gridwidth)*height+gridwidth
canvaswidth = (cellsize+gridwidth)*width+gridwidth
if(canvaswidth>=65536 or canvasheight>=65536):
    g.exit("The width or height of the GIF file must be less than 65536 pixels."
            + "Width: " + canvaswidth + "Height: " + canvasheight)
# ------------------------------------------------------------------------------
def getpx(xrel, yrel, frameidx):
    xabs = xrel + vx * frameidx
    yabs = yrel + vy * frameidx
    if(xabs%(cellsize+gridwidth)<gridwidth or yabs%(cellsize+gridwidth)<gridwidth):
        return "2"
    else: return str(g.getcell(x+xabs/(cellsize+gridwidth), y+yabs/(cellsize+gridwidth)))

def getdata(frameidx):
    lines = []
    # Each array element is a line of 0 and 1 characters
    for ypx in xrange(canvasheight):
        line = ""
        for xpx in xrange(canvaswidth):
            line += getpx(xpx, ypx, frameidx)
        lines += line
    return lines
# ------------------------------------------------------------------------------
def compress(lines):
    table = {'0': 0, '1': 1, '2': 2, '3': 3}
    curr = cc = 4
    used = eoi = 5
    bits = size = 3
    mask = 7
    output = code = ""
    for line in lines:
        for i in xrange(len(line)):
            next = line[i]
            if (code + next) in table:
                code += next
            else:
                used += 1
                table[(code + next)] = used
                curr += table[code] << bits
                bits += size
                while(bits >= 8):
                    output += chr(curr & 255)
                    curr >>= 8
                    bits -= 8
                if(used > mask):
                    if(size < 12):
                        size += 1
                        mask = mask*2 + 1
                    else:
                        curr += cc << bits # output cc in current width
                        bits += size
                        while(bits >= 8):
                            output += chr(curr & 255)
                            curr >>= 8
                            bits -= 8
                        table = {'0': 0, '1': 1} #reset table
                        used = 5
                        bits = 3
                        mask = 7
                code = next
    curr += table[code] << bits
    bits += size
    while(bits >= 8):
        output += chr(curr & 255)
        curr >>= 8
        bits -= 8
    output += chr(curr)
    subbed = ""
    while(len(output) > 255):
        subbed += chr(255) + output[:255]
        output = output[255:]
    return subbed + chr(len(output)) + output + chr(0)
# ----------------------------------------------------------------------
# GIF formatting
# Useful information of GIF formats in:
# http://www.matthewflickinger.com/lab/whatsinagif/bits_and_bytes.asp
# ----------------------------------------------------------------------
header = "GIF89a"
screendesc = struct.pack("<2HB2b", canvaswidth, canvasheight, 0x91, 0, 0)
# Colors in colortable: White, Black, LifeWiki Gray, and Black(Unused) (3 bytes each)
colortable = "\xFF\xFF\xFF\x00\x00\x00\xC6\xC6\xC6\x00\x00\x00"
applic = "\x21\xFF\x0B" + "NETSCAPE2.0" + struct.pack("<2bHb", 3, 1, 0, 0)
imagedesc = struct.pack("<4HB", 0, 0, canvaswidth, canvasheight, 0x00)

try:
    gif = open(os.path.join(os.getcwd(), filename),"wb")
except:
    g.exit("Unable to open file.")

gif.write(header + screendesc + colortable + applic)
for f in xrange(frames):
    # Graphics control extension
    gif.write("\x21\xF9" + struct.pack("<bBH2b", 4, 0x00, pause, 0, 0))
    # Get data for this frame
    gif.write("," + imagedesc + chr(2) + compress(getdata(f)))
    g.show(str(f+1)+"/"+str(frames))
    if(f+1 < frames):
        g.run(1)
        g.update()
gif.close()
g.show("GIF animation saved in " + filename)
Attachments
myosc.gif
LifeWiki Syntax, 0.32s interval
I'm not sure what causes the choppy delays in chrome.
If you rightclick ->view image in new tab,
You can see that the gif works well. It's a mystery...
myosc.gif (7.36 KiB) Viewed 9518 times
Last edited by Scorbie on March 15th, 2015, 8:36 am, edited 8 times in total.
Best wishes to you, Scorbie
User avatar
Scorbie
 
Posts: 1350
Joined: December 7th, 2013, 1:05 am

Re: Script for making animated gifs

Postby Scorbie » March 15th, 2015, 3:21 am

calcyman wrote:I opted for animated SVGs for Catagolue since they're inline, scalable and efficient.

codeholic wrote:I will try to restyle it so than it has the same look as other uploaded patterns on LifeWiki (i. e. black-on-white with gray gridlines).

Still, I think SVG making scripts are worth publishing, because it's scalable, and because I just found out that gifs don't work so nicely on some browsers like chrome and smartphones.
Best wishes to you, Scorbie
User avatar
Scorbie
 
Posts: 1350
Joined: December 7th, 2013, 1:05 am

Re: Script for making animated gifs

Postby flipper77 » March 15th, 2015, 3:35 am

Scorbie wrote:Still, I think SVG making scripts are worth publishing, because it's scalable, and because I just found out that gifs don't work so nicely on some browsers like chrome and smartphones.

I use chrome pretty much exclusively, and the only gifs that have trouble showing properly are the ones that have short delays between frames. Anyways, the script is great, but a few things I want to mention:

  • Grid lines should be 2 pixels wide with a color of #C6C6C6 to match other images on LifeWiki
  • Spaceship gifs are a bit choppy with delays that fit LifeWiki's other ones
I may mess around with the script to get smoother gifs for spaceships, since there are some that lack one at this time.
User avatar
flipper77
 
Posts: 197
Joined: October 24th, 2010, 3:25 am
Location: Spokane, WA

Re: Script for making animated gifs

Postby Scorbie » March 15th, 2015, 6:35 am

flipper77 wrote:Grid lines should be 2 pixels wide with a color of #C6C6C6 to match other images on LifeWiki
Thanks, that seems easy enough to change.
flipper77 wrote:Spaceship gifs are a bit choppy with delays that fit LifeWiki's other ones

I would have to study more about gifs to figure that out. --Which might take some time.
EDIT: That's strange. When I open the gif file in my local computer -- with chrome-- there aren't any problems.

Well, I think SVGs don't have choppy delays, which is a good plus.
Best wishes to you, Scorbie
User avatar
Scorbie
 
Posts: 1350
Joined: December 7th, 2013, 1:05 am

Re: Script for making animated gifs

Postby flipper77 » March 15th, 2015, 7:20 am

Well, I've modified Scorbies script to allow for smoother spaceship gifs:
# Runs the current selection for a given number of steps and
# creates a black and white animated GIF file.
# Based on giffer.pl, which is based on code by Tony Smith.

import golly as g
import os
import struct

rect=g.getselrect()
if len(rect)==0:
    g.exit("Nothing in selection.")
[x,y,width,height]=rect
if(width>=65536 or height>=65536):
    g.exit("The width or height of the GIF file must be less than 65536 pixels.")

gens = pause = cellsize = gridwidth = vx = vy = fpg = filename = "?"
def getparam(msg, init = ""):
    info = "Current parameters:\n"\
        +"The number of gens: "+gens+"\n"\
        +"The pause time of each frame: "+pause+"centisecs\n"\
        +"The size of each cell: "+cellsize+"px\n"\
        +"The width of gridlines: "+gridwidth+"px\n"\
        +"The speed of the pattern: "+"("+vx+","+vy+")cells/frame\n"\
        +"The number of frames per gen: "+fpg+" per gen\n"\
        +"The file name: "+filename+"\n\n"
    return g.getstring(info+msg, init, "Create animated GIF")
gens = getparam("Enter the number of gens.", "4")         
pause = getparam("Enter the pause time of each frame (in centisecs.)", "50")
cellsize = getparam("Enter the size of each cell (in pixels.)", "14")
gridwidth = getparam("Enter the width of gridlines (in pixels, 0 to disable.)", "2")
vx, vy = getparam("Enter the speed of the pattern (in cells per frame.)\n ex)(-3,5)cells/frame -> -3 5", "0 0").split()
fpg = getparam("Enter the frames per gen(1 for oscillators).", "4")
filename = getparam("Enter the file name. ex)out.gif", "out.gif")
getparam("Press OK to continue.")
   
def tryint(var, name):
    try:
        return int(var)
    except:
        g.exit(name + " is not an integer: " + var)


gens = tryint(gens, "Number of gens")
pause = tryint(pause, "Pause time")
cellsize = tryint(cellsize, "Cell Size")
gridwidth = tryint(gridwidth, "Grid Width")
vx = tryint(vx, "X velocity")
vy = tryint(vy, "Y velocity")
fpg = tryint(fpg, "Frames/gen")
canvasheight = (cellsize+gridwidth)*height+gridwidth
canvaswidth = (cellsize+gridwidth)*width+gridwidth

if (cellsize+gridwidth)%(fpg*gens) != 0:
    g.exit("%s won't be smooth: (%d + %d)/(%d * %d) isn't an integer." % (filename, cellsize, gridwidth, fpg, gens))
else:
    modifier = (cellsize+gridwidth)/(fpg*gens)

if(canvaswidth>=65536 or canvasheight>=65536):
    g.exit("The width or height of the GIF file must be less than 65536 pixels."
            + "Width: " + canvaswidth + "Height: " + canvasheight)
# ------------------------------------------------------------------------------
def getpx(xrel, yrel, frameidx):
    xabs = xrel + vx * frameidx * modifier
    yabs = yrel + vy * frameidx * modifier
    if(xabs%(cellsize+gridwidth)<gridwidth or yabs%(cellsize+gridwidth)<gridwidth):
        return "2"
    else: return str(g.getcell(x+xabs/(cellsize+gridwidth), y+yabs/(cellsize+gridwidth)))

def getdata(frameidx):
    lines = []
    # Each array element is a line of 0 and 1 characters
    for ypx in xrange(canvasheight):
        line = ""
        for xpx in xrange(canvaswidth):
            line += getpx(xpx, ypx, frameidx)
        lines += line
    return lines
# ------------------------------------------------------------------------------
def compress(lines):
    table = {'0': 0, '1': 1, '2': 2, '3': 3}
    curr = cc = 4
    used = eoi = 5
    bits = size = 3
    mask = 7
    output = code = ""
    for line in lines:
        for i in xrange(len(line)):
            next = line[i]
            if (code + next) in table:
                code += next
            else:
                used += 1
                table[(code + next)] = used
                curr += table[code] << bits
                bits += size
                while(bits >= 8):
                    output += chr(curr & 255)
                    curr >>= 8
                    bits -= 8
                if(used > mask):
                    if(size < 12):
                        size += 1
                        mask = mask*2 + 1
                    else:
                        curr += cc << bits # output cc in current width
                        bits += size
                        while(bits >= 8):
                            output += chr(curr & 255)
                            curr >>= 8
                            bits -= 8
                        table = {'0': 0, '1': 1} #reset table
                        used = 5
                        bits = 3
                        mask = 7
                code = next
    curr += table[code] << bits
    bits += size
    while(bits >= 8):
        output += chr(curr & 255)
        curr >>= 8
        bits -= 8
    output += chr(curr)
    subbed = ""
    while(len(output) > 255):
        subbed += chr(255) + output[:255]
        output = output[255:]
    return subbed + chr(len(output)) + output + chr(0)
# ----------------------------------------------------------------------
# GIF formatting
# Useful information of GIF formats in:
# http://www.matthewflickinger.com/lab/whatsinagif/bits_and_bytes.asp
# ----------------------------------------------------------------------
header = "GIF89a"
screendesc = struct.pack("<2HB2b", canvaswidth, canvasheight, 0x91, 0, 0)
# Colors in colortable: White, Black, Gray, and Black(Unused) (3 bytes each)
colortable = "\xFF\xFF\xFF\x00\x00\x00\xC6\xC6\xC6\x00\x00\x00"
applic = "\x21\xFF\x0B" + "NETSCAPE2.0" + struct.pack("<2bHb", 3, 1, 0, 0)
imagedesc = struct.pack("<4HB", 0, 0, canvaswidth, canvasheight, 0x00)

try:
    gif = open(os.path.join(os.getcwd(), filename),"wb")
except:
    g.exit("Unable to open file.")

gif.write(header + screendesc + colortable + applic)
for f in xrange(gens*fpg):
    # Graphics control extension
    gif.write("\x21\xF9" + struct.pack("<bBH2b", 4, 0x00, pause, 0, 0))
    # Get data for this frame
    gif.write("," + imagedesc + chr(2) + compress(getdata(f)))
    g.show(str(f+1)+"/"+str(gens*fpg))
    if ((fpg == 1) | (f % fpg == fpg - 1)):
        g.run(1)
        g.update()
gif.close()
g.show("GIF animation saved in " + filename)

I used the code before his last edit, so you can still modify gridwidth if you like, most animations on LifeWiki have 2 pixel wide gridlines, but some look better with other options. Test it on a glider and compare to LifeWikis version to see how they compare.

EDIT: The code that wants smooth gifs is only there to show that the output gif may not be perfectly smooth, but that's hard to avoid if said gif is a spaceship type. A small bit of the code can be changed to make it better suited.

EDIT2: For some reason, the script I posted has problems with patterns with several frames, hopefully someone can find the problem.
User avatar
flipper77
 
Posts: 197
Joined: October 24th, 2010, 3:25 am
Location: Spokane, WA

Re: Script for making animated gifs

Postby codeholic » March 27th, 2015, 5:40 pm

After I fixed a small glitch it works pretty fine for me: https://github.com/conwaylife/giffer

Thanks to all who participated.
Ivan Fomichev
User avatar
codeholic
Moderator
 
Posts: 1140
Joined: September 13th, 2011, 8:23 am
Location: Hamburg, Germany

Re: Script for making animated gifs

Postby Namesnipe » May 7th, 2015, 3:56 am

Whoopity-doo, I sniped myself a name!
Namesnipe
 
Posts: 1
Joined: May 7th, 2015, 3:54 am

Re: Script for making animated gifs

Postby Freywa » May 7th, 2015, 7:34 am

Namesnipe wrote:Whoopity-doo, I sniped myself a name!

What are you doing here? Is it related to cellular automata?
User avatar
Freywa
 
Posts: 274
Joined: June 23rd, 2011, 3:20 am
Location: Singapore


Return to Website Discussion

Who is online

Users browsing this forum: No registered users and 1 guest