Error when running giffer.py

For scripts to aid with computation or simulation in cellular automata.
Post Reply
User avatar
Saka
Posts: 3627
Joined: June 19th, 2015, 8:50 pm
Location: Indonesia
Contact:

Error when running giffer.py

Post by Saka » July 29th, 2017, 12:09 am

So I dug around posts and found the old giffer script for spaceships! Unfortunately, I couldn't get it to work because of this error:

Code: Select all

[Window Title]
Python error:

[Content]
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "C:\Users\sakaf\Documents\Saka\scripts\giffer\giffer.py", line 10, in <module>
    from dialog import getstrings
  File "dialog.py", line 2, in <module>
    from Tkinter import *
  File "C:\Python27\Lib\lib-tk\Tkinter.py", line 38, in <module>
    import FixTk
  File "C:\Python27\Lib\lib-tk\FixTk.py", line 65, in <module>
    import _tkinter
ImportError: DLL load failed: The specified module could not be found.


[OK]
How do I fix this? I really want to make LTL gifs!

User avatar
Rhombic
Posts: 1072
Joined: June 1st, 2013, 5:41 pm

Re: Error when running giffer.py

Post by Rhombic » July 29th, 2017, 12:14 pm

You need the Tkinter module, apparently. For now, if you don't have it, download it (there should be quite a few mirrors online). It's one of the modules for Python to run things using the "visual" display of the computer, allowing you to get something apart from print str in the cmd.

I would imagine there's a way to do this without Tkinter though... maybe someone should give it a think.
SoL : FreeElectronics : DeadlyEnemies : 6a-ite : Rule X3VI
what is “sesame oil”?

User avatar
Saka
Posts: 3627
Joined: June 19th, 2015, 8:50 pm
Location: Indonesia
Contact:

Re: Error when running giffer.py

Post by Saka » July 29th, 2017, 8:03 pm

I have Tkinter. If you see my posts in yhe sandbox, I have mentioned working on a python program to run L-Systems, and there I ask Tkinter questions.

User avatar
Saka
Posts: 3627
Joined: June 19th, 2015, 8:50 pm
Location: Indonesia
Contact:

Re: Error when running giffer.py

Post by Saka » August 3rd, 2017, 8:49 am

Bump. Do I specifically need _tkinter ?

User avatar
Saka
Posts: 3627
Joined: June 19th, 2015, 8:50 pm
Location: Indonesia
Contact:

Re: Error when running giffer.py

Post by Saka » August 4th, 2017, 5:29 am

:D :D :D :D :D

Code: Select all

# Runs the 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
from collections import namedtuple


########################################################################
# Color schemes
########################################################################
ColorScheme = namedtuple('ColorScheme', 'size table')
"""Color scheme used in the gif file.
ColorScheme is merely a container for these two things:
size: Contains a "color table size" that goes to the logical screen
      descriptor.
      **Note**
      The number of colors used in the gif file is: 2 ** (size + 1).
table: Contains a table of the 2**(size+1) colors. As you can see
       below, the colors are represented as RGB, each color in which
       occupying 1 byte (values 0-255.) The 3-byte colors are simply
       concatenated to make the color table.
       **Note**
       The last color is used as the borderline color in this script.
"""


lifewiki = ColorScheme(size=1, table= (
    "\xFF\xFF\xFF" # State 0: white
    "\x00\x00\x00" # State 1: black
    "\x00\x00\x00" # (ignored)
    "\xC6\xC6\xC6" # Boundary: LifeWiki gray
    ))

lifehistory = ColorScheme(size=2, table=(
    "\x00\x00\x00" # State 0: black
    "\x00\xFF\x00" # State 1: green
    "\x00\x00\x80" # State 2: dark blue
    "\xD8\xFF\xD8" # State 3: light green
    "\xFF\x00\x00" # State 4: red
    "\xFF\xFF\x00" # State 5: yellow
    "\x60\x60\x60" # State 6: gray
    "\x00\x00\x00" # Boundary color
    ))

LTL = ColorScheme(size=1, table= (
    "\x30\x30\x30" # State 0: golly gray
    "\xFF\xFF\x00" # State 1: yellow
    "\x00\x00\x00" # (ignored)
    "\x50\x50\x50" # Boundary: LifeWiki gray
    ))

# Edit this to set the color scheme.
colors = LTL

########################################################################
# Parsing inputs
########################################################################

# Sanity check
rect = g.getselrect()
if rect == []:
    g.exit("Nothing in selection.")
[rectx,recty,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.")

def parseinputs():
    global gens
    global fpg
    global pause
    global purecellsize  # Cell size without borders
    global cellsize  # Cell size with borders
    global gridwidth  # Border width
    global vx
    global vy
    global filename
    global canvaswidth
    global canvasheight
    # Get params
    #gens, fpg, pause, purecellsize, gridwidth, v, filename = getstrings(entries=[
        #("Number of generations for the GIF file to run:", "4"),
        #("The number of frames per generation (1 for statonary patterns):", "1"),
       # ("The pause time of each generation in centisecs:", "50"),
      #  ("The size of each cell in pixels:", "14"),
       # ("The width of gridlines in pixels:", "2"),
      #  ("The offset of the total period:", "0 0"),
        #("The file name:", "out.gif")
        #])
    gens = g.getstring("Number of generations for the GIF file to run:", "4")
    fpg = g.getstring("The number of frames per generation (1 for statonary patterns):", "1")
    pause = g.getstring("The pause time of each generation in centisecs:", "50")
    purecellsize = g.getstring("The size of each cell in pixels:", "14")
    gridwidth = g.getstring("The width of gridlines in pixels:", "2")
    v = g.getstring("The offset of the total period:", "0 0")
    filename = g.getstring("The file name:", "out.gif")

    # Sanity check params

    def tryint(var, name):
        try:
            return int(var)
        except:
            g.exit("{} is not an integer: {}".format(name, var))

    try:
        vx, vy = v.split()
    except:
        g.exit("You should enter the speed as {x velocity} {y velocity}.\n"
               "ex1) 0 0\t ex2) -1 3")

    gens = tryint(gens, "Number of gens")
    pause = tryint(pause, "Pause time")
    purecellsize = tryint(purecellsize, "Cell size")
    gridwidth = tryint(gridwidth, "Grid width")
    vx = tryint(vx, "X velocity")
    vy = tryint(vy, "Y velocity")
    fpg = tryint(fpg, "Frames per gen")

    pause //= fpg
    cellsize = purecellsize + gridwidth
    canvasheight = cellsize*height + gridwidth
    canvaswidth = cellsize*width + gridwidth

    if(canvaswidth>=65536 or canvasheight>=65536):
        g.exit("The width or height of the GIF file must be less than 65536 pixels. "
               "Received width: {}, height: {}".format(canvaswidth, canvasheight))

########################################################################
# GIF formatting
# Useful information on GIF formats in:
# http://www.matthewflickinger.com/lab/whatsinagif/bits_and_bytes.asp
########################################################################

def makegif():

    header, trailer = "GIF89a", '\x3B'
    screendesc = struct.pack("<2HB2b", canvaswidth, canvasheight,
                             0x90+colors.size, 0, 0)
    applic = "\x21\xFF\x0B" + "NETSCAPE2.0" + struct.pack("<2bHb", 3, 1, 0, 0)
    imagedesc = "\x2C" + struct.pack("<4HB", 0, 0, canvaswidth, canvasheight, 0x00)

    bordercolor = 2 ** (colors.size + 1) - 1
    borderrow = [bordercolor] * (canvaswidth + cellsize)
    # Gather contents to write as gif file.
    gifcontent = [header, screendesc, colors.table, applic]
    for f in xrange(gens*fpg):
        # Graphics control extension
        gifcontent += ["\x21\xF9", struct.pack("<bBH2b", 4, 0x00, pause, 0, 0)]
        # Get data for this frame
        dx = int(vx * f * cellsize // (fpg * gens))
        dy = int(vy * f * cellsize // (fpg * gens))
        dx_cell, dx_px = divmod(dx, cellsize)
        dy_cell, dy_px = divmod(dy, cellsize)
        # Get cell states (shifted dx_cell, dy_cell)
        # The bounding box is [rectx+dx_cell, recty+dy_cell, width+1, height+1]
        cells = []
        # The image is made of cell rows (height purecellsize) sandwiched
        # by border rows (height gridwidth).
        for y in xrange(recty+dy_cell, recty+dy_cell+height+1):
            cells += [borderrow] * gridwidth
            row = []
            # Each row is made of cell pixels (width purecellsize)
            # sandwiched by border pixels (width gridwidth)
            for x in xrange(rectx+dx_cell, rectx+dx_cell+width+1):
                row += [bordercolor] * gridwidth
                row += [g.getcell(x, y)] * purecellsize
            row += [bordercolor] * gridwidth
            cells += [row] * purecellsize
        cells += [borderrow] * gridwidth
        #g.setclipstr('\n'.join(str(row) for row in cells).replace(', ', ''))
        #g.note('')
        # Cut a canvaswidth x canvasheight image starting from dx_px, dy_px.
        newcells = [row[dx_px:dx_px+canvaswidth] for row in
                    cells[dy_px:dy_px+canvasheight]]
        image = ''.join(''.join(chr(i) for i in row) for row in newcells)
        # Image descriptor + Image
        gifcontent += [imagedesc, compress(image, colors.size+1)]
        g.show("{}/{}".format(f+1, gens*fpg))
        if (f % fpg == fpg - 1):
            g.run(1)
            g.update()
    gifcontent.append(trailer)

    with open(os.path.join(os.getcwd(), filename),"wb") as gif:
        gif.write("".join(gifcontent))
    g.show("GIF animation saved in {}".format(filename))

########################################################################
# GIF compression
# Algorithm explained in detail in:
# http://www.matthewflickinger.com/lab/whatsinagif/lzw_image_data.asp
########################################################################

def compress(data, mincodesize):
    """Apply lzw compression to the given data and minimum code size."""

    ncolors = 2**mincodesize
    cc, eoi = ncolors, ncolors + 1

    table = {chr(i): i for i in xrange(ncolors)}
    codesize = mincodesize + 1
    newcode = ncolors + 2

    outputbuff, outputbuffsize, output = cc, codesize, []

    databuff = ''

    for next in data:
        newbuff = databuff + next
        if newbuff in table:
            databuff = newbuff
        else:
            table[newbuff] = newcode
            newcode += 1
            # Prepend table[databuff] to outputbuff (bitstrings)
            outputbuff += table[databuff] << outputbuffsize
            outputbuffsize += codesize
            databuff = next
            if newcode > 2**codesize:
                if codesize < 12:
                    codesize += 1
                else:
                    # Prepend clear code.
                    outputbuff += cc << outputbuffsize
                    outputbuffsize += codesize
                    # Reset table
                    table = {chr(i): i for i in xrange(ncolors)}
                    newcode = ncolors + 2
                    codesize = mincodesize + 1
            while outputbuffsize >= 8:
                output.append(outputbuff & 255)
                outputbuff >>= 8
                outputbuffsize -= 8
    outputbuff += table[databuff] << outputbuffsize
    outputbuffsize += codesize
    while outputbuffsize >= 8:
        output.append(outputbuff & 255)
        outputbuff >>= 8
        outputbuffsize -= 8
    output.append(outputbuff)
    # Slice outputbuff into 255-byte chunks
    words = []
    for start in xrange(0, len(output), 255):
        end = min(len(output), start+255)
        words.append(''.join(chr(i) for i in output[start:end]))
    contents = [chr(mincodesize)]
    for word in words:
        contents.append(chr(len(word)))
        contents.append(word)
    contents.append('\x00')
    return ''.join(contents)

########################################################################
# Main
########################################################################
def main():
    parseinputs()
    makegif()

main()

User avatar
Scorbie
Posts: 1692
Joined: December 7th, 2013, 1:05 am

Re: Error when running giffer.py

Post by Scorbie » October 28th, 2017, 9:13 am

O̶n̶e̶ ̶o̶f̶ ̶t̶h̶e̶ ̶c̶o̶r̶e̶ ̶d̶e̶v̶e̶l̶o̶p̶e̶r̶s̶ ̶(̶s̶h̶r̶u̶g̶)̶ ̶o̶f̶ ̶g̶i̶f̶f̶e̶r̶.̶p̶y̶ ̶h̶e̶r̶e̶.
Saka already solved the problem but here's my attempt on updating giffer.py to address this issue.
It fallbacks to g.getstring when there's an Error while importing tkinter.

https://github.com/Scorbie/giffer

As before, Run giffer.py.

GUYTU6J
Posts: 2200
Joined: August 5th, 2016, 10:27 am
Location: 拆哪!I repeat, CHINA! (a.k.a. 种花家)
Contact:

Re: Error when running giffer.py

Post by GUYTU6J » April 28th, 2022, 8:57 am

Bump for a different bug: Scorbie's June 27, 2021 version of giffer.py returns the following TypeError when the selection is 40×40 or above.
error.png
error.png (24.46 KiB) Viewed 1807 times
EDIT on May 7: oddly enough, it looks like the bug has something very complex to do with both the size of each cell (px) and the pattern. The original case used the default 15 pixels per cell on some random selection I don't remember. In the following pattern under the same settings, the two random 23×23 regions to the left works but the right one does not.

Code: Select all

x = 63, y = 53, rule = B3/S23
obo2bo3b3o6b2o2bo17bobo2bo3b3o6b2o2bo$6bobo3b4o3bo26bobo3b4o3bo$2b7obo
b2obo3b4o19b7obob2obo3b4o$3bobob2ob2obobo3b3o21bobob2ob2obobo3b3o$bob
3o5bob2ob3o3bo18bob3o5bob2ob3o3bo$11bobo2b3o32bobo2b3o$bo9bob4o2b2obo
18bo9bob4o2b2obo$bo9b4o5bobo18bo9b4o5bobo$2bobo6bo3bo2b3o21bobo6bo3bo
2b3o$obo3b2o3bo3bo2bo21bobo3b2o3bo3bo2bo$6b3o2b2o2b2ob2o2bo23b3o2b2o2b
2ob2o2bo$b2o2bob3obobo2bo3bo20b2o2bob3obobo2bo3bo$2bobo11bo5bo18b2obo
11bo5bo$o9bo29bo9bo$o5bob3o4bo2b2o20bo5bob3o4bo2b2o$o15b3o21bo15b3o$8b
o5b2o6bo25bo5b2o6bo$o4bo3bo2b2o2bo2b2obo17bo4bo3bo2b2o2bo2b2obo$o2bo2b
ob4o3bo24bo2bo2bob4o3bo$o2b2obo4bo3b3ob2o19bo2b2obo4bo3b3ob2o$2obo17bo
18b2obo17bo$3bo4bo6bo3b2o22bo4bo6bo3b2o$3bo3b2o4bo2bo2b2o22bo3b2o4bo2b
o2b2o8$obo2bo3b3o6b2o2bo$6bobo3b4o3bo$2b7obob2obo3b4o$3bobob2ob2obobo
3b3o$bob3o5bob2ob3o3bo$11bobo2b3o$bo9bob4o2b2obo$bo9b4o5bobo$2bobo6bo
3bo2b3o$obo3b2o3bo3bo2bo$6b3o2b2o2b2ob2o2bo$bobobob3obobo2bo3bo$b2obo
11bo5bo$o9bo$o5bob3o4bo2b2o$o15b3o$8bo5b2o6bo$o4bo3bo2b2o2bo2b2obo$o2b
o2bob4o3bo$o2b2obo4bo3b3ob2o$2obo17bo$3bo4bo6bo3b2o$3bo3b2o4bo2bo2b2o!
This unpredictability makes the bug quite annoying.

User avatar
Scorbie
Posts: 1692
Joined: December 7th, 2013, 1:05 am

Re: Error when running giffer.py

Post by Scorbie » May 11th, 2022, 4:50 am

GUYTU6J wrote:
April 28th, 2022, 8:57 am
Bump for a different bug:
Oops, I (years ago) forgot to cleanup some code while porting to Python 3.
In Line 270 of `giffer.py`, change `bchr(chr(i))` to `bchr(i)` and I think all should be good.
Let me know if that doesn't fix it.

Thank you for the report!

Edit: I've updated the original script for those interested.

Post Reply