1

I'm working on a small project to turn an old Raspberry Pi model A into a photo frame. I'm using slideshow.py. The script starts to run, shows the 1st photo and when transitioning to the 2nd photo it crashes and reports out of memory.

The same script runs fine on my laptop. The Pi and laptop both use Python 2.7), so looks like it is related to the small memory size of the Pi CPU.

I downloaded the script from: https://github.com/cgoldberg/py-slideshow.

Below is the code I'm using:

#!/usr/bin/env python
#
#  Copyright (c) 2013, 2015, Corey Goldberg
#
#  Dev: https://github.com/cgoldberg/py-slideshow
#  License: GPLv3


import argparsehttps://github.com/cgoldberg/py-slideshow
import random
import os

import pyglet


def update_pan_zoom_speeds():
    global _pan_speed_x
    global _pan_speed_y
    global _zoom_speed
    _pan_speed_x = random.randint(-8, 8)
    _pan_speed_y = random.randint(-8, 8)
    _zoom_speed = random.uniform(-0.02, 0.02)
    return _pan_speed_x, _pan_speed_y, _zoom_speed


def update_pan(dt):
    sprite.x += dt * _pan_speed_x
    sprite.y += dt * _pan_speed_y


def update_zoom(dt):
    sprite.scale += dt * _zoom_speed


def update_image(dt):
    img = pyglet.image.load(random.choice(image_paths))
    sprite.image = img
    sprite.scale = get_scale(window, img)
    sprite.x = 0
    sprite.y = 0
    update_pan_zoom_speeds()
    window.clear()


def get_image_paths(input_dir='.'):
    paths = []
    for root, dirs, files in os.walk(input_dir, topdown=True):
        for file in sorted(files):
            if file.endswith(('jpg', 'png', 'gif')):
                path = os.path.abspath(os.path.join(root, file))
                paths.append(path)
    return paths


def get_scale(window, image):
    if image.width > image.height:
        scale = float(window.width) / image.width
    else:
        scale = float(window.height) / image.height
    return scale


window = pyglet.window.Window(fullscreen=True)


@window.event
def on_draw():
    sprite.draw()


if __name__ == '__main__':
    _pan_speed_x, _pan_speed_y, _zoom_speed = update_pan_zoom_speeds()

    parser = argparse.ArgumentParser()
    parser.add_argument('dir', help='directory of images',
                        nargs='?', default=os.getcwd())
    args = parser.parse_args()

    image_paths = get_image_paths(args.dir)
    img = pyglet.image.load(random.choice(image_paths))
    sprite = pyglet.sprite.Sprite(img)
    sprite.scale = get_scale(window, img)

    pyglet.clock.schedule_interval(update_image, 6.0)

    pyglet.app.run()

Any ideas if this is solvable, or if it is asking too much from a Pi model A?

ADDED: - The images I copied direct from the SD card in my camera. They can go up to 2,5MB each with resolutions reaching 3264x1836 pixels. - Monitor resolution is 1600x900.

  • What do your images look like? Can you edit your question (don't use comments) to include some details on resolution, file size and format (jpg/png/etc.)? – goobering Jan 29 '17 at 17:14
  • 1
    How big are these images? It looks like you're opening a bunch of images, but never close them... Of course you'll run out of RAM. – Jacobm001 Jan 29 '17 at 19:53
  • Added size and resolution of images. – kxtronic Jan 30 '17 at 16:06
  • You should watch what happens when you run it in top (or htop). You could then shim in a pause (waiting on keyboard input) in between the loading of each image to step through it. – goldilocks Jan 30 '17 at 16:48
  • 1
    @DmitryGrigoryev: I don't know enough about pyglet to know if that's true or not. There's a nontrivial chance that pyglet is trying to keep all the images in memory. – Jacobm001 Jan 30 '17 at 17:13
2

Try discarding the old image with sprite.delete() before you load a new image with image.load(). That way, only one photo is loaded in RAM at any given moment, and since your code displays 1 photo just fine, it may just be enough.

Also, check how much free RAM you have. At 3264x1836 resolution, a decompressed image will take about 17 MB, and I would expect several of them to fit in the RAM before you're out of memory.

0

I did not find out why the original script runs out of memory. After all, it only loads one image at a time.

However, you guys gave me some clues so I ran a tool to compress all images to 1600x900 pixels, so the image size went down from about 2.5MB to between 500-600KB and now it works fine.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.