0

I have a folder with hundreds (possibly thousands) of images in it that I use to cycle the wallpaper in Xfce. The only problem is, they look best when the image is set to "scaled," which for some images will have a "letterbox" effect, which fills the rest of the region with a solid background color.

My question is, is it possible for said background color to dynamically change with the image so that it doesn't look so void and fits in with the image, such as how many comic viewers like mcomix do? If you don't know what I'm talking about, the short explanation is: if the image is mostly white, I want the solid background color to be white; if the image is mostly black, I want the solid background color to be black; etc.

  • Would editing the images in GIMP out of the question? You could just increase the canvas size to screen resolution, put whatever fill color you want behind it, save the enlarged image over the original. It's not as elegant as Win10 does it with window decorations, but it saves attempting to replace xfdesktop. – user881561 Apr 1 '18 at 16:05
  • Definitely out of the question as I have hundreds, if not thousands in this folder, and I'd rather preserve originals and not have to make copies. – tayoung Apr 1 '18 at 16:11
  • You should edit the question: "...folder with several images..." – user881561 Apr 1 '18 at 16:15
  • Done, I'm wondering if I can write a python script or something that does the image randomization, calculates the dominant color, and modifies the file that determines the background. That may be what I have to do. – tayoung Apr 1 '18 at 16:20
  • 1
    That's what I was thinking. I found the config on my system at ~/.config/xfce4/xfconf/xfce-perchannel-xml/xfce4-desktop.xml – user881561 Apr 1 '18 at 16:34
0

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!

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.