t* Simple Justified Gallery URI git clone git://git.codevoid.de/mkpicindex DIR Log DIR Files DIR Refs DIR README --- tmkpicindex-static.sh (7380B) --- 1 #!/bin/sh 2 3 printf '%s' \ 4 '/*! 5 * mkpicindex.sh - v0.1 6 * https://codevoid.de 7 * Copyright (c) 2019 Stefan Hagen 8 * Licensed under the ISC license. 9 */ 10 ' > LICENSE 11 12 # DEPENDENCIES 13 # - ImageMagic (identify, convert) 14 # - raw only: jhead 15 # - raw only: dcraw 16 17 # LIMITATIONS 18 # - leftover images on the last row won't be added 19 # - the thumbnail cache is not cleaned automaticall 20 21 22 # CONFIGURE 23 TITLE="My Gallery" # browser title 24 WIDTH=1000 # how wide will the gallery be 25 ROW_HEIGHT=180 # how high will the justified rows be? 26 THUMB_QUALITY=83 # quality for thumbnails 27 THUMB_PATH="thm" # relative path to thumbnail folder 28 THUMB_PADDING="6" # image padding 29 30 # TECHNICAL STUFF 31 DEBUG=0 # debug output 32 PROCS=8 33 34 # PRINT HELP / USAGE TEXT 35 usage() { 36 printf '%s\n' \ 37 'mkpicindex - Version: $Id$ 38 39 Usage: mkpicindex [arguments] > file.html 40 41 Arguments: 42 -t "My Gallery" Gallery title 43 -w 850 Gallery main area width 44 -h 180 Row height (thumbnail size) 45 -q 83 Thumbnail quality 46 -b 6 Thumbnail border (padding) 47 -p 8 Max. parallel conversion processes 48 -d Enable debug mode (verbose output) 49 -h Usage (this text) 50 ' 51 exit 2 52 } 53 54 # OVERIDE DEFAULTS 55 while getopts 't:w:h:b:q:p:d' c 56 do 57 case $c in 58 t) TITLE="$OPTARG" ;; 59 w) WIDTH="$OPTARG" ;; 60 h) ROW_HEIGHT="$OPTARG" ;; 61 q) QUALITY="$OPTARG" ;; 62 b) THUMB_PADDING="$OPTARG" ;; 63 p) PROCS="$OPTARG" ;; 64 d) DEBUG=1 ;; 65 ?|*) usage; ;; 66 esac 67 done 68 69 # PRINT USAGE IF OUTPUT IS NOT REDIRECTED 70 [ "$DEBUG" != 1 ] && test -t 1 && usage; 71 72 # GLOBAL TMP VARIABLES 73 G_ROW_WIDTH=0 # combined pic width < WIDTH @ ROW_HEIGHT 74 G_ROW_FILES="" # pipe separated files < WIDTH 75 MORE=1 # trigger next loop 76 77 # CREATE THUMBNAIL DIRECTORY 78 mkdir -p "$THUMB_PATH" 79 80 # OUTPUT HELPER 81 debug() { [ "$DEBUG" == "1" ] && printf '%s\n' "Debug: $1" >&2; } 82 console() { printf '%s\n' "$1" >&2; } 83 84 # CALCULATE BY ASPECT RATIO 85 get_width_by_height() { 86 # returns aspect ratio calculated width 87 local F="$1" # image file 88 local TH="$2" # target height 89 local R="$(identify -format ' %w %h ' "$1" | awk -vTH=$TH \ 90 '{ printf("%.0f", TH*($1/$2)) }')" 91 printf '%.0f' "$R" 92 debug "get_width_by_height: FILE=$F TARGET_HEIGHT=$TH RET_WIDTH=$R" 93 } 94 95 # TOO MANY CONVERT PROCSSES => WAIT 96 thread_check() { 97 while [ $(pgrep convert | wc -l | awk '{ print $1 }') -gt $(($PROCS-1)) ]; 98 do debug "Process Limit ($PROCS) reached. Waiting..."; sleep 2; done 99 } 100 101 # EXTACT CAMERA IMAGE FROM RAW 102 convert_raw() { 103 # XXX dcraw may export a PPM file. 104 F="$1" # raw image 105 if ! [ -f "${F%%.*}_preview.jpg" ]; then 106 dcraw -e -c "$F" > "${F%%.*}_preview.jpg" 107 jhead -q -autorot "${F%%.*}_preview.jpg" 108 console "Raw Conversion: ${F%%.*}_preview.jpg" 109 fi 110 } 111 112 # CREATE THUMBNAIL 113 create_thumb() { 114 local F="$1" # original 115 local W="$2" # width 116 local H="$3" # height 117 local T="${F%%.*}-$H" 118 if [ -f "$THUMB_PATH/$T.gif" ]; 119 then printf '%s' "$THUMB_PATH/$T.gif" 120 elif [ -f "$THUMB_PATH/$T.jpeg" ]; 121 then printf '%s' "$THUMB_PATH/$T.jpeg" 122 else 123 thread_check 124 case $(printf '%s' "${F##*.}" | tr '[:upper:]' '[:lower:]') in 125 gif) console "Creating Thumbnail: $THUMB_PATH/$T.gif" 126 nohup convert -quality $THUMB_QUALITY -sharpen 2x2 \ 127 -coalesce -resize 6000x$H\> \ 128 -deconstruct "$F" \ 129 "$THUMB_PATH/$T.gif" >/dev/null 2>&1 & 130 printf '%s' "$THUMB_PATH/$T.gif" ;; 131 *) console "Creating Thumbnail: $THUMB_PATH/$T.jpeg" 132 nohup convert -quality $THUMB_QUALITY -sharpen 2x2 \ 133 -auto-orient -resize 6000x$H\> "$F" \ 134 "$THUMB_PATH/$T.jpeg" >/dev/null 2>&1 & 135 printf '%s' "$THUMB_PATH/$T.jpeg" ;; 136 esac 137 fi 138 } 139 140 # ADD IMAGE LOOP 141 add_image() { 142 local F="$1" # image file 143 # How wide would the image be when we rescale it to $ROW_HEIGHT? 144 local NW=$(get_width_by_height "$F" "$ROW_HEIGHT") 145 debug "add_image: FILE=$F NW=${NW}x$ROW_HEIGHT" 146 147 # We add images and their width to $G_ROW_WIDTH until $WIDTH will 148 # be exceeded. 149 if [ "$(( $G_ROW_WIDTH + $NW ))" -gt "$WIDTH" ]; then 150 151 debug "add_image: max width reached with F=$F @ $G_ROW_WIDTH" 152 153 # we're building a row now 154 printf " <div class=\"row\">\n"; 155 156 # calculate how much we need to stretch images to fill the 157 # whole row. 158 local RFH=$(printf "$G_ROW_WIDTH $WIDTH $ROW_HEIGHT" \ 159 | awk '{ printf("%.0f",$3*($2/$1)) }') 160 debug "RFH=$RFH" 161 162 # loop through the images in this row and recalculate 163 # them with their new, real height. 164 local IFS='|'; for RF in $G_ROW_FILES; 165 do 166 local RFW=$(($(get_width_by_height "$RF" "$RFH") - 2*$THUMB_PADDING)) 167 debug "add_image: adding file: F=$RF with W=$RFW H=$RFH" 168 169 local T=$(create_thumb "$RF" "$RFW" "$RFH") 170 debug "add_image: created thumbnail $T" 171 172 # output HTML for image 173 console "Adding Image: $RF" 174 printf ' <div class="image">\n' 175 printf ' <a href="'$RF'">\n' 176 printf ' <img width="'$RFW'" height="'$RFH'" src="'$T'">\n' 177 printf ' </a>\n' 178 printf ' </div>\n' 179 done 180 181 # we're done with this row now. 182 printf " </div>\n"; 183 184 # set leftover file as for next iteration 185 G_ROW_WIDTH="$NW" 186 G_ROW_FILES="$F|" 187 else 188 # add more items... 189 debug "add_image: width has not been reached, continue loop." 190 G_ROW_WIDTH="$(( $G_ROW_WIDTH + $NW ))" 191 G_ROW_FILES="$F|$G_ROW_FILES" 192 fi 193 } 194 195 # HEADER 196 printf '%s\n' \ 197 '<html> 198 <head> 199 <meta name="viewport" content="width=device-width"> 200 <title>'"$TITLE"'</title> 201 <style> 202 html { 203 background: black; 204 color: orange; 205 } 206 .base { 207 margin-left: auto; 208 margin-right: auto; 209 width: min-content; 210 } 211 .row { 212 display: block; 213 float: clear; 214 width: max-content; 215 margin-left: auto; 216 margin-right: auto; 217 white-space: nowrap; 218 } 219 .image { 220 float: left; 221 width: fit-content; 222 height: fit-content; 223 padding: '"$THUMB_PADDING"'; 224 } 225 </style> 226 </head> 227 <body> 228 <div class="base"> 229 ' 230 ### MAIN LOOP ########################################################## 231 for F in *.*; 232 do 233 if [ -f "$F" ]; 234 then 235 case "$(printf '%s' ${F##*.} | tr '[:upper:]' '[:lower:]')" in 236 jpg|jpeg|png|gif) add_image "$F" ;; 237 cr2|dng|nef) convert_raw "$F" && \ 238 add_image "${F%%.*}_preview.jpg" ;; 239 *) console "Ignoring: $F" ;; 240 esac 241 fi 242 done 243 ### MAIN LOOP END ###################################################### 244 245 # FOOTER 246 printf '%s\n' \ 247 ' </div> 248 </body> 249 </html>'