Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/bin/sh
- #-------------------------------------------------------------------------------
- # PARAMS
- #-------------------------------------------------------------------------------
- # povray exe path, space separated include directories (simple paths ONLY)
- # the directory of the input file is included automatically
- HERE="`readlink -f "$0"`" && HERE="`dirname "$HERE"`"
- POVEXE="$HERE/povray"
- POVINC="$HERE/include $HERE/demo"
- # ImageMagick or GraphicsMagick exe (typically `magick` or `gm`)
- MAGICK="magick"
- # render options
- W=640 # output image width
- H=480 # output image height
- CHUNK=240 # chunk width & height (240)
- MAXPROCS=16 # maximum number of parallel processes
- MARGIN=4 # safety margin around each chunk (4)
- Q=9 # quality (9)
- R=3 # number of rays (3)
- V=2 # major POV-Ray version (1 or 2)
- #-------------------------------------------------------------------------------
- # INPUT
- #-------------------------------------------------------------------------------
- # check for ImageMagick
- if ! which $MAGICK >/dev/null 2>&1; then
- echo "Error: \`$MAGICK\` not found, please install ImageMagick."
- exit 1
- fi
- # get input file name
- if [ -z "$1" ]; then # if no argument was provided ask user for input...
- echo -n "Input POV file ($W x $H, Q=$Q, R=$R): "
- read f
- f="${f#"'"}" && f="${f%"'"}"
- else f="`realpath "$1"`" # ...otherwise use first argument as input
- fi
- # symlink directory of input file to temp directory without spaces
- fdir_o="`dirname "$f"`"
- fdir="`mktemp -tu povincXXXXXX`"
- ln -s "$fdir_o" "$fdir"
- # generate include flags
- INCDIR="+L$fdir"
- for i in $POVINC; do INCDIR="$INCDIR +L$i"; done
- # generate input and output file names
- INFILE="$fdir/`basename "$f"`"
- OUTFILE="${INFILE%.pov}" && OUTFILE="${OUTFILE%.POV}.png"
- # generate chunk information
- step=$(( CHUNK - 1 )) # 1 -> 119+1
- SC=0 # start column
- EC=0 # end column
- SR=0 # start row
- ER=0 # end row
- COLS=$(( (W + CHUNK - 1) / CHUNK )) # total columns rounded up
- ROWS=$(( (H + CHUNK - 1) / CHUNK )) # total rows rounded up
- TOTAL=$(( COLS * ROWS )) # total number of chunks
- # create temporary working directory
- POVTMP=`mktemp -td povtmpXXXXXX`
- # create empty scene for padding chunks
- BLKPOV="$POVTMP/black.pov"
- echo 'light_source {<0,0,0> color red 0}' > "$BLKPOV"
- # create lists for started and finished render jobs
- J0="$POVTMP/j0"
- J1="$POVTMP/j1"
- > $J0 && > $J1
- # start timer
- start_time=`date +%s`
- #-------------------------------------------------------------------------------
- # RENDER
- #-------------------------------------------------------------------------------
- # iterate over rows from top to bottom
- i=0
- while [ $i -lt $ROWS ]; do
- # start at last iteration's end + 1, stop if start row is out of bounds
- SR=$(( ER + 1 ))
- if [ $SR -gt $H ]; then break; fi
- # end at <step> rows after start, keep end row within image bounds
- ER=$(( SR + step ))
- if [ $ER -gt $H ]; then ER=$H; fi
- # iterate over columns from left to right
- j=0
- while [ $j -lt $COLS ]; do
- # same thing we did for rows
- SC=$(( EC + 1 ))
- if [ $SC -gt $W ]; then break; fi
- EC=$(( SC + step ))
- if [ $EC -gt $W ]; then EC=$W; fi
- # add safety margin around each chunk...
- SR1=$(( SR - MARGIN ))
- SC1=$(( SC - MARGIN ))
- ER1=$(( ER + MARGIN ))
- EC1=$(( EC + MARGIN ))
- # ...but stay within bounds
- if [ $SR1 -lt 1 ]; then SR1=1; fi
- if [ $SC1 -lt 1 ]; then SC1=1; fi
- if [ $EC1 -gt $W ]; then EC1=$W; fi
- if [ $ER1 -gt $H ]; then ER1=$H; fi
- # wait until background job count is under maximum allowed
- while true; do
- started=`cat $J0 | wc -c`
- ended=`cat $J1 | wc -c`
- procs=$(( started - ended ))
- echo "$procs render jobs running (maximum $MAXPROCS)"
- if [ $procs -lt $MAXPROCS ]
- then break # under capacity, proceed
- else sleep 1s # over capacity, wait
- fi
- done
- # use numbered file names for the chunks
- counter="`printf "%04d" $i``printf "%04d" $j`"
- TMPTGA="$POVTMP/${counter}_${SR}+${ER}+${SC}+${EC}.tga"
- # render TGA chunk, pad it with black, compress into PNG, delete TGA
- # all in background { ... } &
- echo -n "0" >> $J0
- {
- $POVEXE +I$INFILE +O$TMPTGA $INCDIR \
- +FT -P -V +A0.1 +W$W +H$H +Q$Q +R$R +MV$V.0 \
- +SC$SC1 +EC$EC1 +SR$SR1 +ER$ER1 ;
- $POVEXE +I$BLKPOV +O$TMPTGA \
- +FT -P -V -A +C +W$W +H$H +Q0 ;
- $MAGICK convert -quality 100 $TMPTGA ${TMPTGA%tga}png ;
- rm $TMPTGA ;
- echo -n "1" >> $J1 ;
- } &
- j=$(( j + 1 ))
- done
- # reset column number for upcoming row
- EC=0
- i=$(( i + 1 ))
- done
- # wait for all render jobs to finish
- while [ `cat $J1 | wc -c` -lt $TOTAL ]; do
- started=`cat $J0 | wc -c`
- ended=`cat $J1 | wc -c`
- procs=$(( started - ended ))
- echo "Waiting for $procs render jobs to finish..."
- sleep 1s
- done
- #-------------------------------------------------------------------------------
- # CONCAT
- #-------------------------------------------------------------------------------
- # crop chunks using info from file name
- echo "Concatenating rendered chunks..."
- for cfile in $POVTMP/*.png
- do
- bname="`basename "$cfile"`"
- bname="${bname%.*}"
- counter="${bname%_*}"
- bname="${bname#*_}"
- SR="${bname%%+*}"
- bname="${bname#*+}"
- ER="${bname%%+*}"
- bname="${bname#*+}"
- SC="${bname%%+*}"
- bname="${bname#*+}"
- EC="${bname%%+*}"
- # define coordinates for crop, ignore top margin for first row
- x=$(( SC - 1 ))
- if [ $SR -eq 1 ]; then y=0; else y=$MARGIN; fi
- w=$(( EC - SC + 1 ))
- h=$(( ER - SR + 1 ))
- # crop chunk, delete uncropped one
- $MAGICK convert $cfile -crop ${w}x${h}+${x}+${y} $POVTMP/o_$counter.png
- rm $cfile
- done
- # concatenate chunks into final image
- $MAGICK montage -mode concatenate -tile ${COLS}x${ROWS} $POVTMP/o_*png $OUTFILE
- #-------------------------------------------------------------------------------
- # FINALIZE
- #-------------------------------------------------------------------------------
- # clean up temporary files
- rm -r $POVTMP
- rm $fdir
- echo "Finished"
- # calculate time elapsed
- end_time="`date +%s`"
- seconds=$(( end_time - start_time ))
- hours=$(( seconds / 3600 ))
- seconds=$(( seconds - hours * 3600 ))
- minutes=$(( seconds / 60 ))
- seconds=$(( seconds - minutes * 60 ))
- echo "Time elapsed: $hours hours, $minutes minutes, $seconds seconds"
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement