Guest User

Untitled

a guest
Jul 5th, 2016
146
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 17.50 KB | None | 0 0
  1. #!/bin/bash
  2. #
  3. # Developed by Fred Weinhaus revised 6/9/2012 .......... revised 4/25/2015
  4. #
  5. # ------------------------------------------------------------------------------
  6. #
  7. # Licensing:
  8. #
  9. # Copyright © Fred Weinhaus
  10. #
  11. # My scripts are available free of charge for non-commercial use, ONLY.
  12. #
  13. # For use of my scripts in commercial (for-profit) environments or
  14. # non-free applications, please contact me (Fred Weinhaus) for
  15. # licensing arrangements. My email address is fmw at alink dot net.
  16. #
  17. # If you: 1) redistribute, 2) incorporate any of these scripts into other
  18. # free applications or 3) reprogram them in another scripting language,
  19. # then you must contact me for permission, especially if the result might
  20. # be used in a commercial or for-profit environment.
  21. #
  22. # My scripts are also subject, in a subordinate manner, to the ImageMagick
  23. # license, which can be found at: http://www.imagemagick.org/script/license.php
  24. #
  25. # ------------------------------------------------------------------------------
  26. #
  27. ####
  28. #
  29. # USAGE: overlapcrop [-s size] [-o overlap] [-m mode] [-u]
  30. # [-i initnum] [-z zeropad] [-d delay] [-l loop] [-c canvas]
  31. # [-M] [-L] [-F frame] [-S spacing] [-R] infile outfile
  32. # USAGE: overlapcrop [-h or -help]
  33. #
  34. # OPTIONS:
  35. #
  36. # -s size crop subsection dimensions in pixels; one or two
  37. # integers>0 with "x" separator; default=128x128
  38. # -o overlap overlap of subsections; pixels or percent
  39. # as one or two integers with "x" separator;
  40. # if percent sign included, then it will be converted to
  41. # pixels in range 0<=integer<subsection size;
  42. # default="50%x50%"
  43. # -m mode mode of output; choices are matrix (numbered),
  44. # sequential (numbered), frames or animation;
  45. # default=matrix
  46. # -u (uniform) flag to keep only same size crop sections and discard
  47. # smaller pieces on the right and bottom; default is to
  48. # keep all crop pieces
  49. # -i initnum initial number for output naming; integer>=0; default=1
  50. # -z zeropad number of digits with zero padding for sequential mode;
  51. # integer>=0; default=0 (no zero padding)
  52. # -d delay delay for animation mode; integer>=0; default=50
  53. # -l loop number of loops for animation mode; integer>=0;
  54. # default=0 (endless looping)
  55. # -c (canvas) leave the virtual canvas in the meta data for the images;
  56. # default is to remove the virtual canvas
  57. # -M (montage) create single montage image; applicable only to matrix
  58. # or sequential mode; default is no montage
  59. # -L (label) flag to add filename labels to each image in the montage;
  60. # default is no filename labels
  61. # -F frame frame size around each image in the montage; integers>=0;
  62. # default=5
  63. # -S spacing spacing between images in the montage; integers>=0;
  64. # default=0
  65. # -R (remove) flag to remove/delete all individual images generated
  66. # prior to creating the montage. Default is leave
  67. # all individual images.
  68. #
  69. ###
  70. #
  71. # NAME: OVERLAPCROP
  72. #
  73. # PURPOSE: To create a sequence of cropped subsections permitting optional
  74. # overlap of the subsections.
  75. #
  76. # DESCRIPTION: OVERLAPCROP creates a sequence of cropped subsections permitting
  77. # optional overlap of the subsections. The output images may be numbered either
  78. # sequentially or in matrix mode (column and row). The images may also be
  79. # output to a single file with multiple frames, to an animation or to a
  80. # montage.
  81. #
  82. # OPTIONS:
  83. #
  84. # -s size ... SIZE is the crop subsection WidthxHeight dimensions in pixels.
  85. # Either one or two non-negative integers may be used with "x" separator if two.
  86. # If only one is provided (with no separator), then it will be used for both
  87. # width and height. The default="128x128".
  88. #
  89. # -o overlap ... OVERLAP is the amount of overlap of subsections. Overlap may
  90. # be specified as pixels or percent of subsection size. Values are either one
  91. # or two non-negative integers with "x" separator. If a percent sign is
  92. # included, then the overlap will be converted to pixels. Values must be
  93. # specified (or convert) in the range of zero to the subsection size. The
  94. # default="50%x50%".
  95. #
  96. # -m mode ... MODE of the output. Choices are matrix (numbered) or m,
  97. # sequential (numbered) or s, frames (mode) or f and animation (mode) or a.
  98. # The default=matrix.
  99. #
  100. # -u (uniform) ... Flag to keep only same size crop sections and discard
  101. # smaller pieces on the right and bottom. The default is to keep all pieces.
  102. #
  103. # -i initnum ... INITNUM is the initial (starting) number for output naming.
  104. # Values are non-negative integers. The default=1.
  105. #
  106. # -z zeropad ... ZEROPAD is the number of digits with zero padding for
  107. # numbering the output images in sequential mode. Values are non-negative
  108. # integers. The default=0 (no zero padding).
  109. #
  110. # -d delay ... DELAY for animation mode. Values are non-negative integers. The
  111. # default=50.
  112. #
  113. # -l loop ... LOOP is the number of times to loop the animation. Values are
  114. # non-negative integers. The default=0 (endless looping).
  115. #
  116. # -c (canvas) ... Flag to leave the virtual canvas in the meta data for the
  117. # images. This is useful when making an animation so that the subsections keep
  118. # their position relative to the original image. The default is to remove the
  119. # virtual canvas, which then just has each frame of the animation replacing the
  120. # previous one.
  121. #
  122. # -M (montage) ... Flag to create a single montage image for matrix or
  123. # sequential modes only. The default is no montage.
  124. #
  125. # -L (label) ... Flag to add filename labels to each image in the montage.
  126. # The default is no filename labels.
  127. #
  128. # -F frame ... FRAME is the size of the frame-like border in pixels placed
  129. # around each image in the montage. Values are non-negative integers.
  130. # The default=5.
  131. #
  132. # -S spacing ... SPACING is the amount of space in pixels to put between each
  133. # images in the montage. Values are non-negative integers. The default=0.
  134. #
  135. # -R (remove) ... Flag to remove/delete all individual images generated
  136. # prior to creating the montage. Th default is to leave all individual images,
  137. # i.e, no deletion.
  138. #
  139. # CAVEAT: No guarantee that this script will work on all platforms,
  140. # nor that trapping of inconsistent parameters is complete and
  141. # foolproof. Use At Your Own Risk.
  142. #
  143. ######
  144. #
  145.  
  146. # set default values
  147. size="128x128"
  148. overlap="50%x50%" # percent or pixels, must not be 100% or size of subsection
  149. mode="matrix" # matrix or sequential or frames or animation
  150. uniform="no" # uniform size only, skip small sections at right and bottom; yes or no
  151. initnum=1 # initial number for sequential or matrix mode; integer>=0
  152. zeropad=0 # number of digits with zero padding for sequential mode; integer>=0
  153. delay=50 # delay for animation mode; integer>=0
  154. loop=0 # looping for animation mode; integer>=0
  155. canvas="off" # on or off to keep virtual canvas; on is useful for animation
  156. montage="no" # montage images, applicable only to matrix or sequential mode
  157. label="no" # montage label with filename; yes or no
  158. frame=5 # montage frame size in pixels; integer>=0
  159. spacing=0 # montage spacing in pixels; integer>=0
  160. remove="no" # remove individual images if montage
  161.  
  162. echo "1"
  163.  
  164. # set directory for temporary files
  165. dir="." # suggestions are dir="." or dir="/tmp"
  166.  
  167. echo "2"
  168.  
  169. # set up functions to report Usage and Usage with Description
  170. PROGNAME=`type $0 | awk '{print $3}'` # search for executable on path
  171. PROGDIR=`dirname $PROGNAME` # extract directory of program
  172. PROGNAME=`basename $PROGNAME` # base name of program
  173. usage1()
  174. {
  175. echo >&2 ""
  176. echo >&2 "$PROGNAME:" "$@"
  177. sed >&2 -e '1,/^####/d; /^###/g; /^#/!q; s/^#//; s/^ //; 4,$p' "$PROGDIR/$PROGNAME"
  178. }
  179. usage2()
  180. {
  181. echo >&2 ""
  182. echo >&2 "$PROGNAME:" "$@"
  183. sed >&2 -e '1,/^####/d; /^######/g; /^#/!q; s/^#*//; s/^ //; 4,$p' "$PROGDIR/$PROGNAME"
  184. }
  185.  
  186. echo "3"
  187.  
  188. # function to report error messages
  189. errMsg()
  190. {
  191. echo ""
  192. echo $1
  193. echo ""
  194. usage1
  195. exit 1
  196. }
  197.  
  198. echo "4"
  199.  
  200. # function to test for minus at start of value of second part of option 1 or 2
  201. checkMinus()
  202. {
  203. test=`echo "$1" | grep -c '^-.*$'` # returns 1 if match; 0 otherwise
  204. [ $test -eq 1 ] && errMsg "$errorMsg"
  205. }
  206.  
  207. echo "5"
  208.  
  209. # test for correct number of arguments and get values
  210. if [ $# -eq 0 ]
  211. then
  212. # help information
  213. echo ""
  214. usage2
  215. exit 0
  216. elif [ $# -gt 24 ]
  217. then
  218. errMsg "--- TOO MANY ARGUMENTS WERE PROVIDED ---"
  219. else
  220. while [ $# -gt 0 ]
  221. do
  222. # get parameter values
  223. case "$1" in
  224. -h|-help) # help information
  225. echo ""
  226. usage2
  227. exit 0
  228. ;;
  229. -s) # get size
  230. shift # to get the next parameter
  231. # test if parameter starts with minus sign
  232. errorMsg="--- INVALID SIZE SPECIFICATION ---"
  233. checkMinus "$1"
  234. size=`expr "$1" : '\([0-9]*x*[0-9]*\)'`
  235. [ "$size" = "" ] && errMsg "--- SIZE=$size MUST BE ONE OR TWO x SEPARATED NON-NEGATIVE INTEGERS ---"
  236. ;;
  237. -o) # get overlap
  238. shift # to get the next parameter
  239. # test if parameter starts with minus sign
  240. errorMsg="--- INVALID OVERLAP SPECIFICATION ---"
  241. checkMinus "$1"
  242. overlap=`expr "$1" : '\([0-9]*%*x*[0-9]*%*\)'`
  243. [ "$overlap" = "" ] && errMsg "--- OVERLAP=$overlap MUST BE ONE OR TWO x SEPARATED NON-NEGATIVE INTEGERS ---"
  244. ;;
  245. -m) # get mode
  246. shift # to get the next parameter
  247. # test if parameter starts with minus sign
  248. errorMsg="--- INVALID MODE SPECIFICATION ---"
  249. checkMinus "$1"
  250. mode=`echo "$1" | tr "[:upper:]" "[:lower:]"`
  251. case "$mode" in
  252. matrix|m) mode="matrix" ;;
  253. sequential|s) mode="sequential" ;;
  254. frames|f) mode="frames" ;;
  255. animation|a) mode="animation" ;;
  256. *) errMsg "--- MODE=$mode IS AN INVALID VALUE ---"
  257. esac
  258. ;;
  259. -u) # set uniform
  260. uniform="yes"
  261. ;;
  262. -i) # get initnum
  263. shift # to get the next parameter
  264. # test if parameter starts with minus sign
  265. errorMsg="--- INVALID INITNUM SPECIFICATION ---"
  266. checkMinus "$1"
  267. initnum=`expr "$1" : '\([0-9]*\)'`
  268. [ "$initnum" = "" ] && errMsg "--- INITNUM=$initnum MUST BE A NON-NEGATIVE INTEGER ---"
  269. ;;
  270. -z) # get zeropad
  271. shift # to get the next parameter
  272. # test if parameter starts with minus sign
  273. errorMsg="--- INVALID ZEROPAD SPECIFICATION ---"
  274. checkMinus "$1"
  275. zeropad=`expr "$1" : '\([0-9]*\)'`
  276. [ "$zeropad" = "" ] && errMsg "--- ZEROPAD=$zeropad MUST BE A NON-NEGATIVE INTEGER ---"
  277. ;;
  278. -d) # get delay
  279. shift # to get the next parameter
  280. # test if parameter starts with minus sign
  281. errorMsg="--- INVALID DELAY SPECIFICATION ---"
  282. checkMinus "$1"
  283. delay=`expr "$1" : '\([0-9]*\)'`
  284. [ "$delay" = "" ] && errMsg "--- DELAY=$delay MUST BE A NON-NEGATIVE INTEGER ---"
  285. ;;
  286. -l) # get loop
  287. shift # to get the next parameter
  288. # test if parameter starts with minus sign
  289. errorMsg="--- INVALID LOOP SPECIFICATION ---"
  290. checkMinus "$1"
  291. loop=`expr "$1" : '\([0-9]*\)'`
  292. [ "$loop" = "" ] && errMsg "--- LOOP=$loop MUST BE A NON-NEGATIVE INTEGER ---"
  293. ;;
  294. -c) # set canvas
  295. canvas="on"
  296. ;;
  297. -M) # set montage
  298. montage="yes"
  299. ;;
  300. -L) # set label
  301. label="yes"
  302. ;;
  303. -F) # get frame
  304. shift # to get the next parameter
  305. # test if parameter starts with minus sign
  306. errorMsg="--- INVALID FRAME SPECIFICATION ---"
  307. checkMinus "$1"
  308. frame=`expr "$1" : '\([0-9]*\)'`
  309. [ "$frame" = "" ] && errMsg "--- FRAME=$frame MUST BE A NON-NEGATIVE INTEGER ---"
  310. ;;
  311. -S) # get spacing
  312. shift # to get the next parameter
  313. # test if parameter starts with minus sign
  314. errorMsg="--- INVALID SPACING SPECIFICATION ---"
  315. checkMinus "$1"
  316. spacing=`expr "$1" : '\([0-9]*\)'`
  317. [ "$spacing" = "" ] && errMsg "--- SPACING=$spacing MUST BE A NON-NEGATIVE INTEGER ---"
  318. ;;
  319. -R) # set remove
  320. remove="yes"
  321. ;;
  322. -) # STDIN and end of arguments
  323. break
  324. ;;
  325. -*) # any other - argument
  326. errMsg "--- UNKNOWN OPTION ---"
  327. ;;
  328. *) # end of arguments
  329. break
  330. ;;
  331. esac
  332. shift # next option
  333. done
  334. #
  335. # get infile and outfile
  336. infile="$1"
  337. outfile="$2"
  338. fi
  339.  
  340. echo "6"
  341.  
  342. # test that infile provided
  343. [ "$infile" = "" ] && errMsg "NO INPUT FILE SPECIFIED"
  344.  
  345. # test that outfile provided
  346. [ "$outfile" = "" ] && errMsg "NO OUTPUT FILE SPECIFIED"
  347.  
  348. outname=`echo "$outfile" | sed -n 's/^\(.*\)[\.].*$/\1/p'`
  349. suffix=`echo "$outfile" | sed -n 's/^.*[\.]\(.*\)$/\1/p'`
  350.  
  351. sfx=`echo "$suffix" | tr "[:upper:]" "[:lower:]"`
  352. if [ "$mode" = "animation" -a "$sfx" != "gif" -a "$sfx" != "miff" ]; then
  353. errMsg "--- ANIMATION REQUIRES SUFFIX OF GIF OR MIFF ---"
  354. fi
  355.  
  356. # setup temporary images
  357. tmpA1="$dir/overlapcrop_A_$$.mpc"
  358. tmpA2="$dir/overlapcrop_A_$$.cache"
  359. tmp1="$dir/overlapcrop_1_$$.miff"
  360. trap "rm -f $tmpA1 $tmpA2 $tmp1;" 0
  361. trap "rm -f $tmpA1 $tmpA2 $tmp1; exit 1" 1 2 3 15
  362. trap "rm -f $tmpA1 $tmpA2 $tmp1; exit 1" ERR
  363.  
  364. # read the input image and filter image into the temp files and test validity.
  365. convert -quiet "$infile" $gray +repage "$tmpA1" ||
  366. errMsg "--- FILE $infile DOES NOT EXIST OR IS NOT AN ORDINARY FILE, NOT READABLE OR HAS ZERO SIZE ---"
  367.  
  368. echo "7"
  369.  
  370. # get width and height of image
  371. ww=`identify -ping -format "%w" $tmpA1`
  372. hh=`identify -ping -format "%h" $tmpA1`
  373.  
  374. # get width and height of subsection
  375. sw=`echo "${size}" | cut -dx -f1`
  376. sh=`echo "${size}" | cut -dx -f2`
  377. #echo "sw=$sw; sh=$sh"
  378.  
  379. # test that subsection smaller than image
  380. [ $sw -ge $ww -o $sh -ge $hh ] && errMsg "--- SUBSECTION SIZE MUST BE SMALLER THAN INFILE SIZE ---"
  381.  
  382. echo "8"
  383. # get offset amount in pixels for subsection taking into account overlap
  384. test=`echo "$overlap" | grep "%"`
  385. #echo "test=$test"
  386. if [ "$test" = "" ]; then
  387. # overlap in pixels
  388. ox=`echo "${overlap}" | cut -dx -f1`
  389. oy=`echo "${overlap}" | cut -dx -f2`
  390. else
  391. # overlap in percent
  392. overlap=`echo "$overlap" | sed 's/%//g'`
  393. ox=`echo "${overlap}" | cut -dx -f1`
  394. oy=`echo "${overlap}" | cut -dx -f2`
  395. # convert to pixels
  396. ox=`convert xc: -format "%[fx:floor($ox*$sw/100)]" info:`
  397. oy=`convert xc: -format "%[fx:floor($oy*$sh/100)]" info:`
  398. fi
  399. ow=`convert xc: -format "%[fx:$sw-$ox]" info:`
  400. oh=`convert xc: -format "%[fx:$sh-$oy]" info:`
  401.  
  402. # test if overlap is sw or sh
  403. [ $ox -eq $sw ] && errMsg "--- X OVERLAP CANNOT EQUAL THE WIDTH OF THE SUBSECTION ---"
  404. [ $oy -eq $sh ] && errMsg "--- Y OVERLAP CANNOT EQUAL THE HEIGHT OF THE SUBSECTION ---"
  405.  
  406. echo "9"
  407. # get ending pixel for stopping loops
  408. if [ "$uniform" = "no" ]; then
  409. ew=`convert xc: -format "%[fx:$ww-$sw+$ox-1]" info:`
  410. eh=`convert xc: -format "%[fx:$hh-$sh+$oy-1]" info:`
  411. elif [ "$uniform" = "yes" ]; then
  412. ew=`convert xc: -format "%[fx:$ww-$sw]" info:`
  413. eh=`convert xc: -format "%[fx:$hh-$sh]" info:`
  414. fi
  415. echo "9.1"
  416. #echo "ww=$ww; hh=$hh; sw=$sw; sh=$sh; ow=$ow; oh=$oh; ew=$ew; eh=$eh"
  417.  
  418. # set up to keep virtual canvas
  419. if [ "$canvas" = "off" ]; then
  420. repaging="+repage"
  421. else
  422. repaging=""
  423. fi
  424. echo "9.2"
  425. # compute number of sections
  426. k=0
  427. for ((i=0;i<=eh;i+=oh)); do
  428. for ((j=0;j<=ew;j+=ow)); do
  429. ((k++))
  430. done
  431. done
  432. num=$k
  433.  
  434. echo "10"
  435.  
  436. echo "mode=$mode"
  437.  
  438. if [ "$mode" = "frames" -o "$mode" = "animation" ]; then
  439. convert -size $size xc: $tmp1
  440. fi
  441.  
  442. echo ""
  443. # process subsections
  444. filelist=""
  445. t=1
  446. k=$initnum
  447. m=$initnum
  448. dh=0
  449. for ((i=0;i<=eh;i+=oh)); do
  450. dw=0
  451. n=$initnum
  452. for ((j=0;j<=ew;j+=ow)); do
  453. echo "Subsection: $t out of $num (${sw}x${sh}+${dw}+${dh}) row=$m col=$n"
  454. if [ "$mode" = "frames" ]; then
  455. convert $tmpA1[${sw}x${sh}+${dw}+${dh}] $repaging miff:- | convert $tmp1 - $tmp1
  456. elif [ "$mode" = "animation" ]; then
  457. convert $tmpA1[${sw}x${sh}+${dw}+${dh}] $repaging miff:- | convert $tmp1 - $tmp1
  458. elif [ "$mode" = "sequential" ]; then
  459. kk=`printf "%0${zeropad}d" $k`
  460. convert $tmpA1[${sw}x${sh}+${dw}+${dh}] $repaging ${outname}_$kk.$suffix
  461. filelist="$filelist ${outname}_$kk.$suffix"
  462. elif [ "$mode" = "matrix" ]; then
  463. convert $tmpA1[${sw}x${sh}+${dw}+${dh}] $repaging ${outname}_r${m}_c${n}.$suffix
  464. filelist="$filelist ${outname}_r${m}_c${n}.$suffix"
  465. fi
  466. dw=$(($dw+$ow))
  467. ((t++))
  468. ((k++))
  469. ((n++))
  470. done
  471. dh=$(($dh+$oh))
  472. ((m++))
  473. done
  474. echo ""
  475.  
  476. echo "11"
  477.  
  478. if [ "$mode" = "frames" ]; then
  479. convert $tmp1 -delete 0 ${outname}.$suffix
  480. elif [ "$mode" = "animation" ]; then
  481. convert -delay $delay -dispose Background $tmp1 -delete 0 -loop $loop "${outname}_animation.$suffix"
  482. fi
  483.  
  484. echo "12"
  485.  
  486. if [ "$mode" != "frames" -a "$mode" != "animation" -a "$montage" = "yes" ]; then
  487. if [ "$label" = "yes" ]; then
  488. labeling="-label %t"
  489. else
  490. labeling=""
  491. fi
  492. montage $labeling $filelist -tile $((n-initnum))x$((m-initnum)) \
  493. -frame $frame -geometry +${spacing}+${spacing} \
  494. "${outname}_montage.$suffix"
  495. if [ "$remove" = "yes" ]; then
  496. rm $filelist
  497. fi
  498. fi
  499.  
  500. echo "13"
  501.  
  502. exit 0
Advertisement
Add Comment
Please, Sign In to add comment