0

Working on Python code to read the contents of periodically changed file (information on an MP3) and create a specific animated gif based on the information at hand, using Wand. I have however been having a significant problem with the gif refusing to save after a few passes; after two or three passes, either the image.save() runs infinitely or the processing time increases dramatically. I see no reason for the sudden change.

The code here is a test case built to verify that the problem was not with the file reading, which it is not.

# coding=latin-1

from wand.image import Image        # ImageMagick
from wand.font import Font          # IM Font Handler
from wand.drawing import Drawing    # IM Drawing API
from wand.color import Color        # IM Colour definitions
from watchdog.observers import Observer             # Event monitors
from watchdog.events import FileSystemEventHandler  # Event handlers

import time                         # for the stopwatch
import sys, os

FONT_NAME =  'c://windows//fonts//alarm clock.ttf';
FONT_SIZE = 80;
SPACING = 1;

def ImageMaker(title, album, composer, playtime):
    print("DEBUG: Entering ImageMaker()");
    start = time.time();

    title = title.ljust(60,' '); # these strings are space-padded to work properly in draw.text()
    album = album.ljust(60,' ');
    composer = composer.ljust(60,' ');
    details = [title, album, composer];

    counter = 0;
    frame_counter = 0;

    bg = Image(filename="nowplaying_background.png");   # this is a static, pre-generated file
    gif = Image(background=Color('rgb(0,0,0)'), height=200, width=1440);

    if (int(playtime) > 45):    # the script takes so long, very short MP3s finish before the script does
        for x in details:
            while (counter <= len(x)+1 and counter < 30 and len(x) != 0):
                with Image(height=200, width=1440, depth=8) as img:
                    with Drawing() as draw:
                        draw.font = FONT_NAME;
                        draw.font_size = FONT_SIZE;
                        draw.text_interline_spacing = SPACING;
                        draw.fill_color = Color('rgb(255, 194, 0)');
                        draw.stroke_width = 0;
                        a = x[(29-counter):30];     # start at 30, step back to 0
                        b = x[59-counter:len(x)];   # start at 60, step back to 30
                        draw.text(20, 65, a);   # top line text
                        draw.text(20, 130, b);  # bottom line text
                        draw(img);
                    with Image(height=200, width=1440) as final:
                        final.composite(bg);        # draw static bg on the image context
                        final.composite(img);       # draw the current fg over the bg
                        if(frame_counter > 0):
                            gif.sequence.append(final);
                        else:
                            gif.sequence[0] = final;
                        final.clear();
                        gif.sequence[frame_counter].delay = 30;
                        img.clear();
                counter += 1; 
                frame_counter += 1;
            counter = 0;
            print("DEBUG: Exiting frame generator");
        gif.sequence[29].delay = 200;       # these set the delays between the three elements longer
        gif.sequence[59].delay = 200;       # so they're more readable
        gif.sequence[89].delay = 200;
        gif.type = 'optimize';              
        gif.save(filename="c://users/magni/desktop/nowplaying.gif");
        gif.destroy();
        bg.destroy();
    else:
        print("DEBUG: Skipping image generation, song is too short");

    end = time.time();
    elapsed = end - start;
    print("Time to completition: ", elapsed);

# These are simulated samples
ImageMaker("ABCDEF", "GHIJKLMNO", "QRSTUVWXYZ", "60");
ImageMaker("ABCDEF", "GHIJKLMNO", "QRSTUVWXYZ", "60");
ImageMaker("QRSTUVWXYZ", "ABCDEF", "GHIJKLMNO", "90");
ImageMaker("QRSTUVWXYZ", "ABCDEF", "GHIJKLMNO", "90");
ImageMaker("American Meeting", "Teitoku no Ketsudan 2", "Yoichiro Yoshikawa", "133");
ImageMaker("American Meeting", "Teitoku no Ketsudan 2", "Yoichiro Yoshikawa", "133");

Example output:

DEBUG: Entering ImageMaker()
DEBUG: Exiting frame generator
DEBUG: Exiting frame generator
DEBUG: Exiting frame generator
Time to completition:  22.29582381248474
DEBUG: Entering ImageMaker()
DEBUG: Exiting frame generator
DEBUG: Exiting frame generator
DEBUG: Exiting frame generator
Time to completition:  23.027299642562866
DEBUG: Entering ImageMaker()
DEBUG: Exiting frame generator
DEBUG: Exiting frame generator
DEBUG: Exiting frame generator
Time to completition:  21.273354291915894
DEBUG: Entering ImageMaker() on a modified file
DEBUG: Exiting frame generator
DEBUG: Exiting frame generator
DEBUG: Exiting frame generator
Time to completition:  139.14677023887634
DEBUG: Entering ImageMaker()
DEBUG: Exiting frame generator
DEBUG: Exiting frame generator
DEBUG: Exiting frame generator

After fifteen minutes, the fifth cycle hadn't finished and was manually terminated. The destination file (nowplaying.gif) continued to grow during that time, and was nearly 2 megabytes in size when the process was killed. The final gif is broken, which makes sense as it wasn't completely saved.

I'm unsure if I've done something wrong or I've stumbled on a bug in the Wand implementation (version 0.6.1, the latest available). My Python skills are not extremely good, but I have perused bug reports and documentation, and I see nothing on this particular issue.

1 Answers1

1

Issue appears to be related to an out-of-date Wand version; the python interpreter being used was running 0.5.8, not 0.6.1 (I have two installations of python and was referencing the wrong one with pip). Updating to 0.6.1 resolved the issue, possibly as part of a memory referencing rewrite.

Considering this question answered.