Advertisement
rhowaldt

moarsaic-v1

Jun 28th, 2015
281
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 5.59 KB | None | 0 0
  1. #!/bin/bash
  2. #
  3. # GTFO license:
  4. # this program is provided with NO GUARANTEE and NO SUPPORT
  5. # if it breaks or does not do what you want, FIX IT YOURSELF
  6. #
  7. # a script for building a screen-size tile-mosaic-thingy out of the 16 colours extracted from an image.
  8. # tile-divisor is args[2], so you can decide the size of the tiles, somewhat.
  9. # by rhowaldt
  10. #
  11. # depends: xdpyinfo, imagemagick
  12.  
  13. #FUNCTIONS AND SHIT
  14.  
  15. # SHUFFLE FUNCTION based on Knufth-Fisher-Yayes shuffle algorithm
  16. # http://mywiki.wooledge.org/BashFAQ/026 thank you!
  17. # takes an array[@] as input through 'shuffle ARRAY[@]', outputs arr[@]
  18. shuffle() {
  19.    local i tmp size max rand
  20.    arr=("${!1}") # retrieve array from $1
  21.    # $RANDOM % (i+1) is biased because of the limited range of $RANDOM
  22.    # Compensate by using a range which is a multiple of the array size.
  23.    size=${#arr[*]}
  24.    max=$(( 1600 / size * size ))
  25.  
  26.    for ((i=size-1; i>0; i--)); do
  27.       while (( (rand=$RANDOM) >= max )); do :; done
  28.       rand=$(( rand % (i+1) ))
  29.       tmp=${arr[i]} arr[i]=${arr[rand]} arr[rand]=$tmp
  30.    done
  31. }
  32.  
  33. #VARIABLES AND SUCH
  34. if [[ $# -ne 2 ]]; then
  35.    echo
  36.    echo "Your arguments are wrong."
  37.    echo "Usage: moarsaic [image] [divisor (integer)]"
  38.    exit 1
  39. fi
  40.  
  41. IMAGE="$1"
  42. DIVISOR=$2
  43. x="x" #this is pathetic, but who cares?
  44. MAXTILES=1000 # the amount of tiles needed to receive a prompt
  45. COLAMOUNT=16
  46.  
  47. # TODO: create flags for
  48. # --cols [NUM] # amount of colours to grab from original
  49. # --resize # resize image before processing (faster)
  50. # --view # open resulting image in feh
  51. # --compare # open original + resulting image in feh side-by-side
  52. # --output # filename
  53. # --filter # send output through filter (separate script)
  54.  
  55.  
  56. #THE WORKINGS
  57. echo
  58. echo "* * * * * M O A R S A I C * * * * *"
  59. echo
  60.  
  61. # 1. wanna know how many tiles
  62. 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
  63.  
  64. SMALLEST=$(( RES_X < RES_Y ? RES_X : RES_Y )) #find the smallest side
  65. if [[ $SMALLEST -eq $RES_X ]]; then
  66.    TILESIZE_X=$(( SMALLEST/DIVISOR )) #make sure still X=X
  67.    TILESIZE_Y=$TILESIZE_X # make them square
  68. else [[ $SMALLEST -eq $RES_Y ]]
  69.    TILESIZE_Y=$(( SMALLEST/DIVISOR ))
  70.    TILESIZE_X=$TILESIZE_Y
  71. fi
  72. 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
  73. TILES_Y=$(( ( RES_Y/TILESIZE_Y ) + 1 )) #because what happens when it fits exactly...
  74. TILES=$(( TILES_X * TILES_Y ))
  75.  
  76. echo
  77. echo "Image: $1"
  78. echo "Screen Resolution: $RES_X$x$RES_Y"
  79. echo "Tilesize: $TILESIZE_X$x$TILESIZE_Y"
  80. echo "Tiles: $TILES ($TILES_X$x$TILES_Y)"
  81. echo
  82.  
  83. # make sure you really want to hang your terminal
  84. if [ "$TILES" -ge "$MAXTILES" ]
  85. then
  86.     while true; do
  87.         read -p "Mate, this will create $TILES tiles. That's quite a lot. Proceed? " yn
  88.         case $yn in
  89.             [Yy]* ) echo "Splendid Superninja, let'ssssssss do it!"; echo; break;;
  90.             [Nn]* ) echo "Baibai."; exit;;
  91.             * ) echo "Answer yes or no. It's not that difficult. Let's try again."; echo;;
  92.         esac
  93.     done
  94. fi
  95.  
  96. # 2. create a 16 colour palette from the temporary image
  97.  
  98. # resize the image to save loads on speed with wallpapers etc
  99. convert "$IMAGE" -resize 800 tmp_image.png
  100. # comment this out if you just want to use the full image without downsizing.
  101. # downsizing reduces the number of pixels and thus induces a loss of colours
  102. # this is easiest seen when comparing between different resizings, and noting the vibrancy of colours
  103. #IMAGE=tmp_image.png
  104.  
  105. echo "Creating colour palette..."
  106. PALETTE=$(convert "$IMAGE" -colors $COLAMOUNT -format "%c" histogram:info:)
  107. rm tmp_image.png
  108. HEXLIST=$(echo "$PALETTE" | sed 's/^.*\#\(.*\) srgb.*/\1/g') #grab just the numbers
  109. 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
  110. q=0
  111.  
  112. declare -a COLOURS
  113.  
  114. while read line; do
  115.       COLOURS=("${COLOURS[@]}" "$line"); #concatenate the shit.
  116.       let q=q+1
  117. done <<< "$HEXLIST"
  118.  
  119. # 3. get enough colours to fill all the tiles
  120. # pick randomly from the 16-colour list, removing each pick until none are left. repeat until all tiles are filled.
  121. declare -a COLOURTILES
  122. while [[ ${#COLOURTILES[@]} -lt $TILES ]] #check whether we are at $TILES yet.
  123. do
  124.    for index in `shuf --input-range=0-$(( ${#COLOURS[*]} - 1 )) | head -${TILES}`
  125.     do
  126.         COLOURTILES=("${COLOURTILES[@]}" "${COLOURS[$index]}")
  127.     done
  128. done
  129.  
  130. # 4. build a tile-mosaic-thingy out of the colours
  131. echo "Grab the lube in eager anticipation. Placing colours..."
  132. echo
  133.  
  134. # convert into imagemagick xc-tags (xc:#222222) and arrange in grid through append+/-
  135. COLLINE="(" # the line with the colour setup
  136. xcount=1
  137. ycount=1
  138. for (( i=0; i<${#COLOURTILES[@]}; i++ ))
  139. do
  140.     # echo "ycount: $ycount - xcount: $xcount" #debug for correct iteration
  141.     if [ $ycount -lt $TILES_Y ]
  142.     then
  143.         if [ $xcount -lt $TILES_X ]
  144.             then
  145.             COLLINE+=" xc:#${COLOURTILES[i]}"
  146.             xcount=$((xcount + 1))
  147.         else
  148.             COLLINE+=" xc:#${COLOURTILES[i]} +append ) -append ("
  149.             xcount=1
  150.             ycount=$((ycount + 1))
  151.         fi
  152.        
  153.     else # final row, final column
  154.        
  155.         if [ $xcount -lt $TILES_X ]
  156.             then
  157.             COLLINE+=" xc:#${COLOURTILES[i]}"
  158.             xcount=$((xcount + 1))
  159.         else # final colour
  160.             COLLINE+=" xc:#${COLOURTILES[i]} +append ) -append"
  161.             break
  162.         fi
  163.     fi
  164. done
  165.  
  166. # echo "$COLLINE" # debug for correct imagemagick syntax
  167.  
  168. convert $COLLINE -filter point -resize "$RES_X$x$RES_Y"\! moarsaic-result.jpg
  169.  
  170. # (temp) feh for viewing the result
  171. feh -m -H 410 -W 800 -E 400 -y 400 $1 moarsaic-result.jpg
  172.  
  173. echo "C'est fini."
  174. exit
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement