forked from dyslexic-charactersheets/scripts
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmagicwand
More file actions
329 lines (303 loc) · 11.7 KB
/
magicwand
File metadata and controls
329 lines (303 loc) · 11.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
#!/bin/bash
#
# Developed by Fred Weinhaus 11/2/2007 .......... revised 8/23/2012
#
# USAGE: magicwand x,y [-t threshold] [-f format] [-r region] [-m mask] [-c color] [-o opacity] infile outfile
# USAGE: magicwand [-h or -help]
#
# OPTIONS:
#
# x,y x,y location to get color and seed floodfill
# -t threshold percent color disimilarity threshold (fuzz factor);
# values from 0 to 100; A value of 0 is an exact
# match and a value of 100 is any color; default=10
# -f format output format; image or mask; default=image
# -r region region to display; inside or outside; default=inside
# -m mask mask type; transparent, binary, edge, overlay, layer;
# default=transparent
# -c color color for background, edge outline or translucent layer;
# color="none" indicates use opacity;
# color="trans" indicates make background transparent;
# default="black"
# -o opacity opacity for transparent, overlay or layer mask;
# values from 0 to 100; default=0
#
###
#
# NAME: MAGICWAND
#
# PURPOSE: To isolate a contiguous region of an image based upon a color determined
# from a user specified image coordinate.
#
# DESCRIPTION: MAGICWAND determines a contiguous region of an image based
# upon a color determined from a user specified image coordinate and a color
# similarity threshold value (fuzz factor). The output can be either an
# image or a mask. If the region is set to inside, then the image can be
# made to mask out the background as transparent, mask out the background
# using an opacity channel, fill the background with a color, display a
# boundary (outline) edge for the region or apply a translucent color layer
# over the background. If the region is set to outside, then the inside will
# be masked and the outside area will show normally. Alternately, the output
# can be a mask which is either binary (black and white), transparent
# (transparent and white) or a boundary edge (white on black background).
# The boundary edge can be made to match the interior or exterior depending
# upon the region setting.
#
#
# OPTIONS:
#
# x,y ... x,y are the coordinates in the image where the color is to be
# extracted and the floodfill is to be seeded.
#
# -f format ... FORMAT specifies whether the output will be the modified
# input image or a mask image. The choices are image or mask. The default
# is image.
#
# -r region ... REGION specifies whether the inside or outside are of the
# image will show and the other be masked. The choices are inside or
# outside. The default is inside.
#
# -m mask ... MASK specifies the type of mask to use or create. The choices
# are transparent, binary, edge, overlay or layer. Only transparent, binary or edge
# masks will be allowed as output. With a transparent mask, the image will be
# modified to mask out the complement of the regions specified according to the
# color setting. Specify the color setting to 1) "trans" to make the background
# transparent, 2) "none" to mask by multiplying by the opacity setting or
# 3) a color value to use a fill color. With an overlay mask, which will only
# be effective on PNG format output images, the masking is done via the opacity
# channel using the opacity setting. With a layer mask, a translucent color will
# be layered over the background according to the color and opacity values. The
# larger the opacity, the lighter the color overlay and the more the image will
# show.
#
# -c color ... COLOR is the color to be used for the background fill or
# the boundary edge overlaid on the image. Any IM color specification is
# valid or a value of none. Be sure to enclose them in double quotes.
# The color value over-rides the opacity for mask=transparent, so use
# color="none" to allow the opacity to work or use color="trans" to make
# the background transparent. The default="black".
#
# -o opacity ... OPACITY controls the degree of transparency for the area
# that is masked out using a mask setting of transparent, overlay or layer.
# A value of zero is fully transparent and a value of 100 is fully opaque.
#
# CAVEAT: No guarantee that this script will work on all platforms,
# nor that trapping of inconsistent parameters is complete and
# foolproof. Use At Your Own Risk.
#
######
#
# set default values
threshold=10
format="image" # image or mask
region="inside" # inside or outside
mask="trans" # trans or binary or edge or overlay (overlay only if png)
bgcolor="black" # color or none when format=image
opacity=0
# set directory for temporary files
dir="." # suggestions are dir="." or dir="/tmp"
# set up functions to report Usage and Usage with Description
PROGNAME=`type "$0" | awk '{print $3}'` # search for executable on path
PROGDIR=`dirname "$PROGNAME"` # extract directory of program
PROGNAME=`basename "$PROGNAME"` # base name of program
usage1()
{
echo >&2 ""
echo >&2 "$PROGNAME:" "$@"
sed >&2 -n '/^###/q; /^#/!q; s/^#//; s/^ //; 4,$p' "$PROGDIR/$PROGNAME"
}
usage2()
{
echo >&2 ""
echo >&2 "$PROGNAME:" "$@"
sed >&2 -n '/^######/q; /^#/!q; s/^#*//; s/^ //; 4,$p' "$PROGDIR/$PROGNAME"
}
# function to report error messages
errMsg()
{
echo ""
echo $1
echo ""
usage1
exit 1
}
# function to test for minus at start of value of second part of option 1 or 2
checkMinus()
{
test=`echo "$1" | grep -c '^-.*$'` # returns 1 if match; 0 otherwise
[ $test -eq 1 ] && errMsg "$errorMsg"
}
# test for correct number of arguments and get values
if [ $# -eq 0 ]
then
# help information
echo ""
usage2
exit 0
elif [ $# -gt 15 ]
then
errMsg "--- TOO MANY ARGUMENTS WERE PROVIDED ---"
else
while [ $# -gt 0 ]
do
# get parameter values
case "$1" in
-h|-help) # help information
echo ""
usage2
exit 0
;;
-f) # format
shift # to get the next parameter - format
# test if parameter starts with minus sign
errorMsg="--- INVALID FORMAT SPECIFICATION ---"
checkMinus "$1"
# test region values
format="$1"
[ "$format" != "image" -a "$format" != "mask" ] && errMsg "--- FORMAT=$format IS NOT A VALID VALUE ---"
;;
-r) # region
shift # to get the next parameter - region
# test if parameter starts with minus sign
errorMsg="--- INVALID REGION SPECIFICATION ---"
checkMinus "$1"
# test region values
region="$1"
[ "$region" != "inside" -a "$region" != "outside" ] && errMsg "--- REGION=$region IS NOT A VALID VALUE ---"
;;
-m) # mask
shift # to get the next parameter - mask
# test if parameter starts with minus sign
errorMsg="--- INVALID MASK SPECIFICATION ---"
checkMinus "$1"
# test mask values
mask="$1"
[ "$mask" != "transparent" -a "$mask" != "binary" -a "$mask" != "edge" -a "$mask" != "overlay" -a "$mask" != "layer" ] && errMsg "--- MASK=$mask IS NOT A VALID VALUE ---"
[ "$mask" = "transparent" ] && mask="trans"
;;
-c) # get color
shift # to get the next parameter - lineval
# test if parameter starts with minus sign
errorMsg="--- INVALID COLOR SPECIFICATION ---"
checkMinus "$1"
bgcolor="$1"
;;
-t) # get threshold
shift # to get the next parameter - threshold
# test if parameter starts with minus sign
errorMsg="--- INVALID THRESHOLD SPECIFICATION ---"
checkMinus "$1"
# test threshold values
threshold=`expr "$1" : '\([.0-9]*\)'`
[ "$threshold" = "" ] && errMsg "THRESHOLD=$threshold IS NOT A NON-NEGATIVE FLOATING POINT NUMBER"
thresholdtestA=`echo "$threshold < 0" | bc`
thresholdtestB=`echo "$threshold > 100" | bc`
[ $thresholdtestA -eq 1 -o $thresholdtestB -eq 1 ] && errMsg "--- THRESHOLD=$threshold MUST BE GREATER THAN OR EQUAL 0 AND LESS THAN OR EQUAL 100 ---"
;;
-o) # get opacity
shift # to get the next parameter - opacity
# test if parameter starts with minus sign
errorMsg="--- INVALID OPACITY SPECIFICATION ---"
checkMinus "$1"
# test width values
opacity=`expr "$1" : '\([.0-9]*\)'`
[ "$opacity" = "" ] && errMsg "OPACITY=$opacity IS NOT A NON-NEGATIVE FLOATING POINT NUMBER"
opacitytestA=`echo "$opacity < 0" | bc`
opacitytestB=`echo "$opacity > 100" | bc`
[ $opacitytestA -eq 1 -o $opacitytestB -eq 1 ] && errMsg "--- OPACITY=$opacity MUST BE GREATER THAN OR EQUAL 0 AND LESS THAN OR EQUAL 100 ---"
;;
-) # STDIN, end of arguments
break
;;
-*) # any other - argument
errMsg "--- UNKNOWN OPTION ---"
;;
[0-9]*,[0-9]*) # Values supplied for coordinates
coords="$1"
;;
.*,.*) # Bogus Values supplied
errMsg "--- COORDINATES ARE NOT VALID ---"
;;
*) # end of arguments
break
;;
esac
shift # next option
done
#
# get infile and outfile
infile=$1
outfile=$2
fi
# test that infile provided
[ "$infile" = "" ] && errMsg "NO INPUT FILE SPECIFIED"
# test that outfile provided
[ "$outfile" = "" ] && errMsg "NO OUTPUT FILE SPECIFIED"
tmpA="$dir/magicwand_$$.mpc"
tmpB="$dir/magicwand_$$.cache"
tmp0="$dir/magicwand_0_$$.png"
trap "rm -f $tmpA $tmpB $tmp0; exit 0" 0
trap "rm -f $tmpA $tmpB $tmp0; exit 1" 1 2 3 15
if convert -quiet -regard-warnings "$infile" +repage "$tmpA"
then
width=`identify -format %w $tmpA`
height=`identify -format %h $tmpA`
[ "$coords" = "" ] && errMsg "--- NO COORDINATES PROVIDED ---"
else
errMsg "--- FILE $infile DOES NOT EXIST OR IS NOT AN ORDINARY FILE, NOT READABLE OR HAS ZERO SIZE ---"
fi
# create transparent mask for region=inside
# make interior transparent and outside black
convert $tmpA -fuzz $threshold% -fill none -draw "matte $coords floodfill" \
-fill black +opaque none $tmp0
# create negative mask - for region=outside
if [ "$region" = "outside" ]
then
convert $tmp0 -channel rgba \
-fill white -opaque none \
-transparent black \
-fill black -opaque white $tmp0
fi
# convert mask to binary if appropriate
if [ "$mask" != "trans" -a "$mask" != "layer" ]
then
# make transparent go to white
convert \( -size ${width}x${height} xc:white \) $tmp0 \
-composite $tmp0
fi
#convert mask to edge if appropriate
if [ "$mask" = "edge" ]
then
convert $tmp0 -convolve "-1,-1,-1,-1,8,-1,-1,-1,-1" -clamp $tmp0
fi
# process image if appropriate
if [ "$format" = "image" -a "$mask" = "edge" ]
then
convert $tmpA \( $tmp0 -transparent black -fill $bgcolor -opaque white \) -composite $tmp0
elif [ "$format" = "image" -a "$mask" = "trans" ]
then
# composite with input and set background
if [ "$bgcolor" = "trans" ]
then
convert $tmpA $tmp0 -composite -transparent black $tmp0
elif [ "$bgcolor" = "none" ]
then
convert $tmpA \( $tmp0 -fill "rgb($opacity%,$opacity%,$opacity%)" -opaque black \) -compose Multiply -composite $tmp0
else
convert $tmpA $tmp0 -composite -fill $bgcolor -opaque black $tmp0
fi
elif [ "$format" = "image" -a "$mask" = "overlay" ]
then
convert $tmpA \( $tmp0 -fill "rgb($opacity%,$opacity%,$opacity%)" -opaque black \) -compose Copy_Opacity -composite $tmp0
elif [ "$format" = "image" -a "$mask" = "layer" ]
then
opacity=`expr 100 - $opacity`
convert $tmp0 -fill $bgcolor -opaque black $tmp0
if [ "$im_version" -lt "06050304" ]; then
composite -dissolve $opacity% $tmp0 $tmpA $tmp0
else
convert $tmpA $tmp0 -define compose:args=$opacity% -compose dissolve -composite $tmp0
fi
fi
convert $tmp0 $outfile
exit 0