Skip to content

Instantly share code, notes, and snippets.

@zezic
Last active December 27, 2019 12:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zezic/9f24d706dc390ff528b33e64322e7e1b to your computer and use it in GitHub Desktop.
Save zezic/9f24d706dc390ff528b33e64322e7e1b to your computer and use it in GitHub Desktop.
Fake chameleon Plank themer and top panel background blur tool
import os
from string import Template
from PIL import Image
from PIL.ImageStat import Stat
from PIL.ImageFilter import GaussianBlur
from PIL import ImageEnhance
from time import sleep
def flat( *nums ):
'Build a tuple of ints from float or integer arguments. Useful because PIL crop and resize require integer points.'
return tuple(int(round(n)) for n in nums)
class Size(object):
def __init__(self, pair):
self.width = float(pair[0])
self.height = float(pair[1])
@property
def aspect_ratio(self):
return self.width / self.height
@property
def size(self):
return flat(self.width, self.height)
def cropped_thumbnail(img, size):
'''
Builds a thumbnail by cropping out a maximal region from the center of the original with
the same aspect ratio as the target size, and then resizing. The result is a thumbnail which is
always EXACTLY the requested size and with no aspect ratio distortion (although two edges, either
top/bottom or left/right depending whether the image is too tall or too wide, may be trimmed off.)
'''
original = Size(img.size)
target = Size(size)
if target.aspect_ratio > original.aspect_ratio:
# image is too tall: take some off the top and bottom
scale_factor = target.width / original.width
crop_size = Size( (original.width, target.height / scale_factor) )
top_cut_line = (original.height - crop_size.height) / 2
img = img.crop( flat(0, top_cut_line, crop_size.width, top_cut_line + crop_size.height) )
elif target.aspect_ratio < original.aspect_ratio:
# image is too wide: take some off the sides
scale_factor = target.height / original.height
crop_size = Size( (target.width/scale_factor, original.height) )
side_cut_line = (original.width - crop_size.width) / 2
img = img.crop( flat(side_cut_line, 0, side_cut_line + crop_size.width, crop_size.height) )
return img.resize(target.size, Image.ANTIALIAS)
with os.popen('dconf watch /org/mate/desktop/background/picture-filename') as pipe:
for line in pipe:
value = line.strip()
if not value.startswith("'/home"):
continue
path = value[1:-1] # strip quotes
image = Image.open(path)
image = cropped_thumbnail(image, (3840, 2160))
bottom = image.crop((1200, 2160 - 64, 2640, 2160))
rgb = Stat(bottom).mean[:3]
dark = tuple([int(comp / 1.3) for comp in rgb])
border = tuple([int(comp / 1.1) for comp in dark])
dark_s = ';;'.join([str(comp) for comp in dark])
border_s = ';;'.join([str(comp) for comp in border])
top = image.crop((0, 0, 3840, 24))
top_blurred = top.filter(GaussianBlur(100))
enhancer = ImageEnhance.Brightness(top_blurred)
top_blurred = enhancer.enhance(0.5)
os.popen('dconf write /org/mate/panel/toplevels/top/background/type "\'none\'"')
top_blurred.save(os.path.expanduser('~/Pictures/DE/panel.png'))
sleep(1)
os.popen('dconf write /org/mate/panel/toplevels/top/background/type "\'image\'"')
# rgb = Stat(top).mean
# panel = tuple([int(comp / 2.0) for comp in rgb])
# panel_s = ','.join([str(comp) for comp in dark])
with open(os.path.expanduser('~/.local/share/plank/themes/dt-2/template')) as template_fd:
template = Template(template_fd.read())
new_theme = template.substitute(
dark_s=dark_s,
border_s=border_s
)
with open(os.path.expanduser('~/.local/share/plank/themes/dt-2/dock.theme'), 'w') as theme_fd:
theme_fd.write(new_theme)
# os.popen('dconf write /org/mate/panel/toplevels/top/background/color "\'rgb({})\'"'.format(
# panel_s
# ))
#This file auto-generated by Plank.
#2019-07-12T15:37:07+0000
[PlankTheme]
#The roundness of the top corners.
TopRoundness=5
#The roundness of the bottom corners.
BottomRoundness=0
#The thickness (in pixels) of lines drawn.
LineWidth=1
#The color (RGBA) of the outer stroke.
OuterStrokeColor=$border_s;;255
#The starting color (RGBA) of the fill gradient.
FillStartColor=$dark_s;;255
#The ending color (RGBA) of the fill gradient.
FillEndColor=$dark_s;;255
#The color (RGBA) of the inner stroke.
InnerStrokeColor=$dark_s;;255
[PlankDockTheme]
#The padding on the left/right dock edges, in tenths of a percent of IconSize.
HorizPadding=1.0
#The padding on the top dock edge, in tenths of a percent of IconSize.
TopPadding=1.2
#The padding on the bottom dock edge, in tenths of a percent of IconSize.
BottomPadding=1.6
#The padding between items on the dock, in tenths of a percent of IconSize.
ItemPadding=1
#The size of item indicators, in tenths of a percent of IconSize.
IndicatorSize=7
#The size of the icon-shadow behind every item, in tenths of a percent of IconSize.
IconShadowSize=0
#The height (in percent of IconSize) to bounce an icon when the application sets urgent.
UrgentBounceHeight=1.5
#The height (in percent of IconSize) to bounce an icon when launching an application.
LaunchBounceHeight=0.29999999999999999
#The opacity value (0 to 1) to fade the dock to when hiding it.
FadeOpacity=1
#The amount of time (in ms) for click animations.
ClickTime=600
#The amount of time (in ms) to bounce an urgent icon.
UrgentBounceTime=600
#The amount of time (in ms) to bounce an icon when launching an application.
LaunchBounceTime=600
#The amount of time (in ms) for active window indicator animations.
ActiveTime=600
#The amount of time (in ms) to slide icons into/out of the dock.
SlideTime=600
#The time (in ms) to fade the dock in/out on a hide (if FadeOpacity is < 1).
FadeTime=250
#The time (in ms) to slide the dock in/out on a hide (if FadeOpacity is 1).
HideTime=150
#The size of the urgent glow (shown when dock is hidden), in tenths of a percent of IconSize.
GlowSize=30
#The total time (in ms) to show the hidden-dock urgent glow.
GlowTime=10000
#The time (in ms) of each pulse of the hidden-dock urgent glow.
GlowPulseTime=2000
#The hue-shift (-180 to 180) of the urgent indicator color.
UrgentHueShift=150
#The time (in ms) to move an item to its new position or its addition/removal to/from the dock.
ItemMoveTime=150
#Whether background and icons will unhide/hide with different speeds. The top-border of both will leave/hit the screen-edge at the same time.
CascadeHide=true
[Desktop Entry]
Name[en_US]=template
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment