Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/bin/bash
- #
- # GTFO license:
- # this program is provided with NO GUARANTEE and NO SUPPORT
- # if it breaks or does not do what you want, FIX IT YOURSELF
- #
- # a script for building a screen-size tile-mosaic-thingy out of the 16 colours extracted from an image.
- # tile-divisor is args[2], so you can decide the size of the tiles, somewhat.
- # by rhowaldt
- #
- # depends: xdpyinfo, imagemagick
- #FUNCTIONS AND SHIT
- # SHUFFLE FUNCTION based on Knufth-Fisher-Yayes shuffle algorithm
- # http://mywiki.wooledge.org/BashFAQ/026 thank you!
- # takes an array[@] as input through 'shuffle ARRAY[@]', outputs arr[@]
- shuffle() {
- local i tmp size max rand
- arr=("${!1}") # retrieve array from $1
- # $RANDOM % (i+1) is biased because of the limited range of $RANDOM
- # Compensate by using a range which is a multiple of the array size.
- size=${#arr[*]}
- max=$(( 1600 / size * size ))
- for ((i=size-1; i>0; i--)); do
- while (( (rand=$RANDOM) >= max )); do :; done
- rand=$(( rand % (i+1) ))
- tmp=${arr[i]} arr[i]=${arr[rand]} arr[rand]=$tmp
- done
- }
- #VARIABLES AND SUCH
- if [[ $# -ne 2 ]]; then
- echo
- echo "Your arguments are wrong."
- echo "Usage: moarsaic [image] [divisor (integer)]"
- exit 1
- fi
- IMAGE="$1"
- DIVISOR=$2
- x="x" #this is pathetic, but who cares?
- MAXTILES=1000 # the amount of tiles needed to receive a prompt
- COLAMOUNT=16
- # TODO: create flags for
- # --cols [NUM] # amount of colours to grab from original
- # --resize # resize image before processing (faster)
- # --view # open resulting image in feh
- # --compare # open original + resulting image in feh side-by-side
- # --output # filename
- # --filter # send output through filter (separate script)
- #THE WORKINGS
- echo
- echo "* * * * * M O A R S A I C * * * * *"
- echo
- # 1. wanna know how many tiles
- read RES_X RES_Y <<<$(xdpyinfo | grep dimensions | awk '{print $2}' | awk -Fx '{print $1, $2}') # determine screen resolution: thanksss http://superuser.com/questions/418699
- SMALLEST=$(( RES_X < RES_Y ? RES_X : RES_Y )) #find the smallest side
- if [[ $SMALLEST -eq $RES_X ]]; then
- TILESIZE_X=$(( SMALLEST/DIVISOR )) #make sure still X=X
- TILESIZE_Y=$TILESIZE_X # make them square
- else [[ $SMALLEST -eq $RES_Y ]]
- TILESIZE_Y=$(( SMALLEST/DIVISOR ))
- TILESIZE_X=$TILESIZE_Y
- fi
- TILES_X=$(( ( RES_X/TILESIZE_X ) + 1 )) #the amount of tiles along one side will always be 1 greater than the amount that fits - for now
- TILES_Y=$(( ( RES_Y/TILESIZE_Y ) + 1 )) #because what happens when it fits exactly...
- TILES=$(( TILES_X * TILES_Y ))
- echo
- echo "Image: $1"
- echo "Screen Resolution: $RES_X$x$RES_Y"
- echo "Tilesize: $TILESIZE_X$x$TILESIZE_Y"
- echo "Tiles: $TILES ($TILES_X$x$TILES_Y)"
- echo
- # make sure you really want to hang your terminal
- if [ "$TILES" -ge "$MAXTILES" ]
- then
- while true; do
- read -p "Mate, this will create $TILES tiles. That's quite a lot. Proceed? " yn
- case $yn in
- [Yy]* ) echo "Splendid Superninja, let'ssssssss do it!"; echo; break;;
- [Nn]* ) echo "Baibai."; exit;;
- * ) echo "Answer yes or no. It's not that difficult. Let's try again."; echo;;
- esac
- done
- fi
- # 2. create a 16 colour palette from the temporary image
- # resize the image to save loads on speed with wallpapers etc
- convert "$IMAGE" -resize 800 tmp_image.png
- # comment this out if you just want to use the full image without downsizing.
- # downsizing reduces the number of pixels and thus induces a loss of colours
- # this is easiest seen when comparing between different resizings, and noting the vibrancy of colours
- #IMAGE=tmp_image.png
- echo "Creating colour palette..."
- PALETTE=$(convert "$IMAGE" -colors $COLAMOUNT -format "%c" histogram:info:)
- rm tmp_image.png
- HEXLIST=$(echo "$PALETTE" | sed 's/^.*\#\(.*\) srgb.*/\1/g') #grab just the numbers
- COL=("0" "8" "1" "9" "2" "A" "3" "B" "4" "C" "5" "D" "6" "E" "7" "F"); #these numbers need to be added to the front of the previous
- q=0
- declare -a COLOURS
- while read line; do
- COLOURS=("${COLOURS[@]}" "$line"); #concatenate the shit.
- let q=q+1
- done <<< "$HEXLIST"
- # 3. get enough colours to fill all the tiles
- # pick randomly from the 16-colour list, removing each pick until none are left. repeat until all tiles are filled.
- declare -a COLOURTILES
- while [[ ${#COLOURTILES[@]} -lt $TILES ]] #check whether we are at $TILES yet.
- do
- for index in `shuf --input-range=0-$(( ${#COLOURS[*]} - 1 )) | head -${TILES}`
- do
- COLOURTILES=("${COLOURTILES[@]}" "${COLOURS[$index]}")
- done
- done
- # 4. build a tile-mosaic-thingy out of the colours
- echo "Grab the lube in eager anticipation. Placing colours..."
- echo
- # convert into imagemagick xc-tags (xc:#222222) and arrange in grid through append+/-
- COLLINE="(" # the line with the colour setup
- xcount=1
- ycount=1
- for (( i=0; i<${#COLOURTILES[@]}; i++ ))
- do
- # echo "ycount: $ycount - xcount: $xcount" #debug for correct iteration
- if [ $ycount -lt $TILES_Y ]
- then
- if [ $xcount -lt $TILES_X ]
- then
- COLLINE+=" xc:#${COLOURTILES[i]}"
- xcount=$((xcount + 1))
- else
- COLLINE+=" xc:#${COLOURTILES[i]} +append ) -append ("
- xcount=1
- ycount=$((ycount + 1))
- fi
- else # final row, final column
- if [ $xcount -lt $TILES_X ]
- then
- COLLINE+=" xc:#${COLOURTILES[i]}"
- xcount=$((xcount + 1))
- else # final colour
- COLLINE+=" xc:#${COLOURTILES[i]} +append ) -append"
- break
- fi
- fi
- done
- # echo "$COLLINE" # debug for correct imagemagick syntax
- convert $COLLINE -filter point -resize "$RES_X$x$RES_Y"\! moarsaic-result.jpg
- # (temp) feh for viewing the result
- feh -m -H 410 -W 800 -E 400 -y 400 $1 moarsaic-result.jpg
- echo "C'est fini."
- exit
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement