Home

Make centred wallpaper with blurred background

Click to download script

This is a short Bash script for creating a centred image with a blurred background. This is good for artworks that were not created in the aspect ratio of your screen, e.g. a painting. The total image should be displayed, and the blurred background is harmonious witht the image. Similar options are available in KDE.

Note that makeBackground.sh only creates the images that can then be set as the background. There are example scripts below that can be used to remove old backgrounds, use the script to make new ones, to set the newly created backgrounds and to open the currently-set background.

Before and after

Requisites

  • ImageMagick to do the image processing
  • feh to set the wallpaper

Instructions

  1. Download the makeBackground.sh file from the top of the page or copy the code from below into a file named makeBackground.sh.
  2. Navigate to the folder containing makeBackground.sh and chmod +x ./makeBackground.sh
  3. Run ./makeBackground.sh -h to see how to use the script.

Script

#!/bin/bash

# Default images directory. If image not supplied, will choose a random
# image from this folder. 
imagesDir="$HOME/Pictures/"
# Default resolution of image. Format: WWWWxHHHH, e.g. 1920x1080
resolution="1920x1080"
# Location that created image will be in
outputDir="$HOME/Pictures/"
plain=0
number=1

display_help() {
    echo "Usage: $0 [options] [image...]" >&2
    echo
    echo "   image...                    zero or more paths to images. If none are provided"
    echo "                               the images will be randomly chosen from --directory"
    echo "   -r, --resolution=           make image of resolution WxH (set to monitor size)"
    echo "   -d, --directory=            directory from which to select random image (if "
    echo "                               image not provided). Default: \"\$HOME/Pictures/\""
    echo "   -o, --output=               directory which the created image will be written to."
    echo "                               Default: \"\$HOME/Pictures/\""
    echo "   -b, --blur                  if this option, then the image will have a "
    echo "                               blurred version of the same image behind. Note: this"
    echo "                               option is mutually exclusive with -p|--plain, and is"
    echo "                               the default option"
    echo "   -p, --plain                 if this option, then the image will not have a"
    echo "                               blurred image behind, but rather a shadow and a"
    echo "                               transparent background"
    echo "   -n, --number=               the number of images to choose randomly if image is"
    echo "                               not provided. By default, number=1. This is ignored
                                         if image... is not blank"
    exit 1
}

images=()

while [ "$#" -gt 0 ]; do
  case "$1" in
    -h|--help) display_help;;

    -r) resolution="$2"; shift 2;;
    -i) image="$2"; shift 2;;
    -d) imagesDir="$2"; shift 2;;
    -o) outputDir="$2"; shift 2;;
    -b) plain=0; shift 1;; 
    -p) plain=1; shift 1;; 
    -n) number="$2"; shift 2;;

    --resolution=*) resolution="${1#*=}"; shift 1;;
    --image=*) image="${1#*=}"; shift 1;;
    --directory=*) imagesDir="${1#*=}"; shift 1;;
    --output=*) outputDir="${1#*=}"; shift 1;;
    --resolution|--image|--directory|--output) echo "$1 requires an argument" >&2; exit 1;;
    --blur) plain=0; shift 1;;
    --plain) plain=1; shift 1;;
    --number=*) number="${1#*=}"; shift 1;;
    
    -*) echo "unknown option: $1" >&2; display_help;;
    *) images+=( "$1" ); shift 1;;
  esac
done

imagesDir="${imagesDir/#\~/$HOME}"
outputDir=${outputDir%/}/
outputDir="${outputDir/#\~/$HOME}"

if [ ${#images[@]} -eq 0 ]; then
  while IFS= read -r line; do
    images+=( "$line" )
  done < <( find "${imagesDir}" -type f | sort -R | tail -"$number" )
fi

for imageMaybePartial in "${images[@]}"; do
  image="$(readlink -f "$imageMaybePartial")"

  imageNameContainingPath=${image//"/"/"|"}
  newimageWithExt="${outputDir}BACKGROUND-${imageNameContainingPath}"
  newimage=${newimageWithExt%.*}".png"
  echo "Making \"$(basename "${image}")\" for background."

  if [ $plain -eq 1 ]; then
    new_width=$(( ${resolution%x*} * 9 / 10 ))
    new_height=$(( ${resolution#*x} * 9 / 10 ))
    new_resolution="${new_width}x${new_height}"

    convert "${image}" -resize "${new_resolution}>"  resized.png 
    convert resized.png \( +clone -background black -shadow 70x10+0+4 \) +swap -background transparent -layers merge +repage "${newimage}"

    rm resized.png
  else
    convert "${image}" -resize "${resolution}"^ resized.png
    convert resized.png -gravity center -crop "${resolution}"+0+0 +repage cropped.png
    convert cropped.png -blur 0x25 blurred.png
    convert "${image}" -resize "${resolution}>" resized.png
    composite resized.png -gravity center blurred.png "${newimage}"

    rm resized.png
    rm cropped.png
    rm blurred.png
  fi

  echo "Created " "${newimage}"
done

Applications

Here is a short script to remove the old backgrounds and create new ones, a background per monitor in use:

#!/bin/bash

rm ~/Pictures/BACKGROUND-*

~/Downloads/makeBackground.sh \
  -n "$(xrandr --listmonitors | grep '+' | wc -l)" # This is number of monitors

Here is a script to set the backgrounds.

#!/bin/bash

# Default background is white
background_colour="#ffffff"
# This is the expansion of a glob that contains the images (unless overwritten
# as an option)
imagesGlob=( ~/Pictures/BACKGROUND-* )

display_help() {
    echo "Usage: $0 [options...]" >&2
    echo
    echo "   -g, --glob=                 glob to search for images to use. Must not contain"
    echo "                               quotation marks. Use escape characters (i.e. \ ) if"
    echo "                               need be. Note that this can be the path to an image."
    echo "                               Default: ~/Pictures/BACKGROUND-*"
    echo "   -b, --background=           background colour in hex. Default: \"#ffffff\""
    exit 1
}

while [ "$#" -gt 0 ]; do
  case "$1" in
    -h|--help) display_help;;

    -g) imagesGlob="$2"; shift 2;;
    -b) background_colour="$2"; shift 2;;

    --glob=*) imagesGlob="${1#*=}"; shift 1;;
    --background=*) background_colour="${1#*=}"; shift 1;;
    
    *) echo "unknown option: $1" >&2; display_help;;
  esac
done

backgrounds="$(ls "$imagesGlob")"
set -o noglob
IFS=$'\n' bg_array=("$backgrounds")
set +o noglob

feh --bg-center --image-bg "$background_colour" "${bg_array[@]}"

Here is a script to open the backgrounds. nsxiv can be changed to another image viewer.

#!/bin/bash

# This is the expansion of a glob that contains the images (unless overwritten
# as an option)
imagesGlob=( ~/Pictures/BACKGROUND-* )

display_help() {
    echo "Usage: $0 [options...]" >&2
    echo
    echo "   -g, --glob=                 glob to search for images to use. Must not contain"
    echo "                               quotation marks. Use escape characters (i.e. \ ) if"
    echo "                               need be. Note that this can be the path to an image."
    echo "                               Default: ~/Pictures/BACKGROUND-*"
    exit 1
}

while [ "$#" -gt 0 ]; do
  case "$1" in
    -h|--help) display_help;;

    -g) imagesGlob="$2"; shift 2;;

    --glob=*) imagesGlob="${1#*=}"; shift 1;;
    
    *) echo "unknown option: $1" >&2; display_help;;
  esac
done

backgrounds="$(ls "$imagesGlob")"
set -o noglob
IFS=$'\n' bg_array=("$backgrounds")
set +o noglob

for filename in  "${bg_array[@]}" ; do
  filename="${filename%.*}"
  filename="${filename//|/"/"}"
  filename="$(sed -e 's/.*BACKGROUND-//' <<< "$filename")"
  nsxiv "$filename"* &
done

An Extra Suggestion

This script works well with another script for selecting images from the terminal with previews (see instructions here). Here is an example, once the Bash alias fzfimg has been set up:

alias background='
  rm -f ~/Pictures/BACKGROUND-* && \
  ~/Downloads/makeBackground.sh -p "$(fd . ~/Pictures/ | sort -R | fzfimg --bind=\"enter:accept\")" && \
  ~/Downloads/setBackgrounds.sh'

Tags

Categories

If you have questions, you can email me at jeremy.w.cains at gmail.com. View page source here.