Piston to change Actiontiles Media image on Raspberry Pi


#1

As the tittle says. I’m wondering if any clever folks have a script to do this. I’m hoping to change a Media image tile to reflect the logo of the radio station being played. A piston that would call a script on a Raspberry Pi to swap/rename an image?

The closest I’ve come across is this https://www.sleepyweim.com/2019/06/08/actiontiles-picture-tiles-that-change/


#2

Honestly, that is not a bad writeup… Thankfully, much of his code can be ignored by you.

You will have your own (perfectly sized) images, so no need to check EXIF for landscape or portrait… (78x78 is ideal for webCoRE’s Dashboard, but ActionTiles can stretch, so just keep them proportional) Also, you do not need to focus on a slideshow, since it will simply be one file copied at time of execution. No need to filter out videos either.

Really, the whole script can likely be just a few lines of code to copy “blues.jpg” to “static.jpg”.
(Later on, another similar script can copy “jazz.jpg” to “static.jpg” etc)


Pro Tip:

Make sure all of your images are the same file types
(jpg is great or png if you want transparency, but don’t use both)
The final output must be uniform… No need to waste time converting during the script.

Also, I would probably backup my master images, just in case one gets over written during testing, LOL


#3

Thank you.

import os
import random
from random import shuffle
from shutil import copyfile
from PIL import Image
from PIL import ExifTags

#
# path: The complete path; function will navigate up one folder
#
def stepUp(path):
    pathLength = len(path)
    loc = path.rfind('/')
    
    if pathLength == (loc + 1):
        #print 'Found the trailing slash.  Remove and repeat.'
        
        tempPath = path[:(-1 * (pathLength - loc))]
        loc = tempPath.rfind('/')
        pathLength = len(tempPath)

    tempPath = path[:(-1 * (pathLength - loc))]
    #print 'New Path: ', tempPath
    
    return tempPath

#
# img: the image object we want to inspect and manipulate
#
def correctRotation(img):
    #
    # Check orientation, and rotate if needed
    # This looks for EXIF data in the file and determines if the camera was rotated when the picture was taken
    # This can throw off the check we do for portrait vs landscape
    # 
    for orientation in ExifTags.TAGS.keys() : 
        if ExifTags.TAGS[orientation]=='Orientation' : break 

    try:
        exif=dict(img._getexif().items())

        if   exif[orientation] == 3 : 
            img=img.rotate(180, expand=True)
            #print ' -- 180'
        elif exif[orientation] == 6 : 
            img=img.rotate(270, expand=True)
            #print ' -- 270'
        elif exif[orientation] == 8 : 
            img=img.rotate(90, expand=True)
            #print ' -- 90'
    except:
        print " -- File contains no EXIF data."
    
    return img

#
# thePath: the subfolder we want to search in; the full path will be 'path_src + thePath'
# theFile: the filename we will use to save the file out to, into the the 'path_dst' location
#
def selectImageFrom(thePath, theFile):
    #
    # Get the combined path and the list of files
    #
    print 'New Loop: ', thePath
    random.seed(os.urandom(4))
    
    path_temp = path_src + thePath
    files = os.listdir(path_temp)
    
    #
    # Loop in case we keep getting invalid files
    #
    for x in range (0, 200):
        #print ' -- count: ', x, file

        file = random.choice(files)
        files.remove(file)
        
        if not files: print "-- WARNING: File list is now empty."
        
        #
        # Check if we have a file or a directory
        #
        if os.path.isdir(path_temp + file):
            print " -- found directory: PATH: ", path_temp, " FILE: ",file
            
            #
            # If dir, then descend into subdir
            # -- Adding and ignoring system folders that are bad
            #
            if file != '@eaDir':
                path_temp = path_temp + file + '/'
                files = os.listdir(path_temp)
            
        else:
            #
            # If file, then check the extension and process, or restart the loop
            #
            filename, file_extension = os.path.splitext(file)

            if file_extension.lower() == '.jpg' or file_extension.lower() == '.jpeg' or file_extension.lower() == '.png':
                #
                # The types of files we are looking for
                #
                img = Image.open(path_temp + file)
                
                img = correctRotation(img)

                #
                # For our display, we only want landscape pictures for better display
                #
                width, height = img.size
                
                if width >= height:
                    print " -- Good File: Landscape ", path_temp + file, ' Width: ', width, 'Height: ', height
                    break
                else:
                    print " --  Bad File: Portrait  ", path_temp + file, ' Width: ', width, 'Height: ', height
            else:
                #
                # The types of files we are NOT looking for
                #
                print " --  Bad File: Not JPG   ", path_temp + file
                    
        if not files: 
            #print ' -- !!!! You should move up a directory at this point. !!!!'
            path_temp = stepUp(path_temp)
            files = os.listdir(path_temp)

    newFile = theFile + file_extension.lower()
    newPath = path_dst + newFile
    
    try:
        #copyfile(os.path.join(path_temp, file), newPath)
        img.save(newPath)
    except:
        print " -- No file was selected."

    return

#
# Path Source: The main location where all the files live; all my photo folders are under this location
# Path Destination: the location in the web folder structure I will use for my URLs
#
path_src = '/volume1/files/GoogleDrive/Pictures/'
path_dst = '/volume1/web/actiontiles/'

#
# Each directory I am using; in my case I have them organized by events
# You can skip this step, but for my 'friends' folder I call it twice, so you can define a folder once but reference it many times later
#
src_running = '# Running/'
src_disney = 'Disney/'
src_friends = '# Parties, Events, Trips/'

#
# We could just put the directories straight into the function calls, but I prefer to define them above
# Since each filename will need to be different, I add them as strings right into the function call
#
selectImageFrom(src_running, 'running')
selectImageFrom(src_disney, 'disney')
selectImageFrom(src_friends, 'friends')
selectImageFrom(src_friends, 'friends2')