After some thinking, I decided to write a Python script (Python 3) that monitors changes to last-image
using the handy xfconf-query
utility using some information I found here (slightly modified to get only the border pixels).
You will need to install (preferably using pip) numpy and Pillow:
pip3 install Pillow
pip3 install numpy
Next, make a .py file with this script in it; I call it "change-bg-with-color.py":
#!/usr/bin/python3
from PIL import Image
from subprocess import Popen, PIPE
import numpy as np
import os
import traceback
# Edit to point to your workspace
WORKSPACE = "/backdrop/screen0/monitor2/workspace0"
# Choose your flavor! Average...
def compute_average_image_color(img):
width, height = img.size
r_total = 0
g_total = 0
b_total = 0
a_total = 0
count = 0
# Get top and bottom borders
for y in [0,height-1]:
for x in range(0, width):
r, g, b, a = img.getpixel((x,y))
r_total += r
g_total += g
b_total += b
a_total += a
count += 1
# Get left and right borders
for x in [0,width-1]:
for y in range(0, height):
r, g, b, a = img.getpixel((x,y))
r_total += r
g_total += g
b_total += b
a_total += a
count += 1
return (np.uint16(r_total/count * 65535.0/255.0), np.uint16(g_total/count * 65535.0/255.0), np.uint16(b_total/count * 65535.0/255.0), np.uint16(a_total/count * 65535.0/255.0))
# or Mode
def compute_mode_image_color(img):
width, height = img.size
pixel_bins = {}
# Get top and bottom borders
for y in [0,height-1]:
for x in range(0, width):
pixel = img.getpixel((x,y))
if pixel in pixel_bins:
pixel_bins[pixel] += 1
else:
pixel_bins[pixel] = 1
# Get left and right borders
for x in [0,width-1]:
for y in range(0, height):
pixel = img.getpixel((x,y))
if pixel in pixel_bins:
pixel_bins[pixel] += 1
else:
pixel_bins[pixel] = 1
pixel = (255,255,255,255)
mode = 0
for p,m in pixel_bins.items():
if m > mode:
pixel = p
return (np.uint16(pixel[0] * 65535.0/255.0), np.uint16(pixel[1] * 65535.0/255.0), np.uint16(pixel[2] * 65535.0/255.0), np.uint16(pixel[3] * 65535.0/255.0))
# Start the monitor for changes to last-image
process = Popen(["xfconf-query", "-c", "xfce4-desktop", "-p", os.path.join(WORKSPACE, "last-image"), "-m"], stdout=PIPE)
while True:
try:
# Get the initial BG image from the workspace
p2 = Popen(["xfconf-query", "-c", "xfce4-desktop", "-p", os.path.join(WORKSPACE, "last-image")], stdout=PIPE)
(filename, err) = p2.communicate()
exit_code = p2.wait()
# Next, open the image
img = Image.open(filename.decode('utf-8').strip()).convert("RGBA")
# Determine and set the color (CHOOSE YOUR FLAVOR HERE)
color = compute_mode_image_color(img)
p2 = Popen(["xfconf-query", "-c", "xfce4-desktop", "-p", os.path.join(WORKSPACE, "color1"), "-s", str(color[0]) , "-s", str(color[1]), "-s", str(color[2]), "-s", str(color[3])], stdout=PIPE)
(output, err) = p2.communicate()
p2.wait()
# Wait for next line
line = process.stdout.readline()
if line == '' and process.poll() is not None:
break
except Exception as e:
print(e)
traceback.print_exc()
pass
Choose your flavor (average or mode). Be sure to modify the WORKSPACE
field to point to your workspace. You can typically find this out by looking in ~/.config/xfce4/xfconf/xfce-perchannel-xml/xfce4-desktop.xml (thanks Dial!)
Simply run the script, and bam, instant background color changes. You of course can configure this to run at startup, but those details are left out for the sake of simplicity. This works for me!