-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathinvertscan
executable file
·517 lines (445 loc) · 15.4 KB
/
invertscan
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
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
#!/bin/bash
#
# Licensing:
#
# Copyright © Laurence Lumi 2017
# Licensed GNU General Public License v3
# which can be found here https://www.gnu.org/licenses/gpl-3.0.en.html
#
progname=`basename $0`
usage()
{
echo >&2 ""
echo >&2 "$progname:" "$@"
cat << MESSAGE1
USAGE: $progname [-d] [-dd] [-m1] [-p name] [-fb R,G,B] [-dmax value] [-z] [+z] infile [outfile]
USAGE: $progname [-d] [-dd] [-m1] [-p name] [-fb R,G,B] [-dmax value] [-z] [+z] directory
USAGE: $progname [-h] [-help]
OPTIONS:
-d debug show intermediate working files for debugging
-dd debug show intermediate working files for debugging
-p profile saved profile with film base values
-m1 monochrome monochrome inversion results in a linear gamma similar to printing with 00 grade paper
-dmax dmax max expected density above the film base or use auto
-fb film base either a single value or three comma seperated values. e.e. .035 or .35,035,035
-z zip zip compress the output (the default is to use the same compression as the input)
+z remove zip do not compress the output regardless of input
MESSAGE1
exit 1
}
help()
{
echo >&2 ""
echo >&2 "$progname:" "$@"
cat >&2 << MESSAGE2
NAME: $progname
PURPOSE: to
Arguments:
TODO
MESSAGE2
exit 1
}
function DEBUG()
{
[ ! "$debug" -eq 0 ] && $@
}
function cleanup {
if [ ! -z "$tmpfileprefix" ] && [ "$debug" -eq 0 ]; then
rm -f "$tmpfileprefix"*
fi
exit 0
}
trap cleanup 0 1 2 3 6
tmpdir="./"
debug=0
tmpprefix=$tmpdir"_is_"
comment="Processed with invertscan"
DEBUG echo -set comment "$comment"
prof_dir=$HOME/.scantools
approach="m_printing_density"
dmax_default=1.81 #max value cineon
while [ $# -gt 0 ]
do
# get parameters
case "$1" in
-h|-help) # help information
echo ""
help
;;
-d) debug=1
;;
-dd) debug=2
;;
-c1) approach="c_printing_density"
options+=" -c1"
;;
-m1) approach="m_printing_density" #monochrome printing density current default
options+=" -m1"
;;
-p) # profile name
shift
profile_name="$1"
options+=" -p $1"
;;
-fb) # film base values
shift
foo=(`echo $1 |sed 's/,/\n/g'`)
if [[ "${#foo[*]}" -eq 1 ]]; then
r_base="${foo[0]}"
g_base="${foo[0]}"
b_base="${foo[0]}"
else
r_base="${foo[0]}"
g_base="${foo[1]}"
b_base="${foo[2]}"
fi
for ((i=0;i<${#foo[*]};i++)); do
if [[ ! "${foo[i]}" =~ ^[0-9]+\.?[0-9]*$ ]]; then
echo "--- fp=${foo[i]} must be a comma seperated positive float value ---"
usage
fi
done
options+=" -fb $1"
;;
-dmax) # dmax value
shift
dmax_input="$1"
if [[ ! "$dmax_input" =~ ^[0-9]+\.?[0-9]*$ ]] && [[ ! "$dmax_input" = "auto" ]];then
echo "--- dmax_input=$dmax_input must be a positive float value or auto---"
usage
fi
options+=" -dmax $1"
;;
-z)
zip="-compress zip"
options+=" -z"
;;
+z)
zip="+compress"
options+=" +z"
;;
-) # STDIN and end of arguments
break
;;
-*) # any other - argument
echo "--- UNKNOWN OPTION ---" $1
usage
;;
*) # end of arguments
break
;;
esac
shift # next option
done
infile=$1
outfile=$2
if [ -d $infile ]; then
echo "processing a directory"
DEBUG set -x
outdir=`basename ${infile%".tif"}`-P
DEBUG echo outdir: $outdir
mapfile files < <(ls $infile/*.tif)
for ((i=0;i<${#files[*]};i++)); do
echo "processing" ${files[i]}
DEBUG set -x
mkdir -p $outdir
outfile=`basename ${files[i]}`
outfile="$outdir"/${outfile%".tif"}-P.tif
invertscan $options $zip ${files[i]} $outfile
set +x
done
exit 0
fi
if [ -z $infile ]; then
echo "must provide a filename"
usage
fi
if [ ! -f "$infile" -o ! -r "$infile" ]; then
echo "Cannot open: $infile"
exit 1
fi
if [ -z $outfile ]; then
outfile=`basename ${infile%".tif"}`-P.tif
fi
DEBUG echo outfile: $outfile
if [[ $infile =~ .*.tif$ ]]; then
DEBUG echo assuming the input file being tif is saved in a linear colorspace, even though the metadata says otherwise
CSPACE="-set colorspace RGB"
fi
if [ "$debug" -eq 0 ]; then
tmpfileprefix="$tmpprefix"`date +%N`_`basename "${outfile%.tif}"`
else
tmpfileprefix="$tmpprefix"debug_`basename "${outfile%.tif}"`
fi
DEBUG echo tmpfileprefix $tmpfileprefix
if [ "$debug" -eq 2 ]; then
#this statement just shows the input that drivers the clup an input range 0 to (width)
convert -size 1024x1 xc: \
-fx "i/(w-1)" \
-set comment "$comment" +compress "$tmpfileprefix"_input_clut1024.tif
#this statement just shows the input that drivers the clup an input range 0 to (2^16) and how i/w-1 works perfectly
convert -size 65536x1 xc: \
-fx "i/(w-1)" \
-channel R -fx "debug(u*QuantumRange)" \
null:
fi
if [ $approach = "m_printing_density" ]; then
DEBUG echo approach = $approach
if [ "$debug" -eq 2 ]; then
convert "$infile[0]" $CSPACE -strip -blur 20x65355 \
-shave 100x100 \
-set comment "$comment" +compress "$tmpfileprefix"_input_for_calculations.tif
fi
# calculate the film min and maximum values
eval set -- `convert "$infile[0]" $CSPACE -strip -blur 20x65355 \
-shave 100x100 \
-format\
"%[fx: maxima.r ] %[fx: maxima.g ] %[fx: maxima.b ]\
%[fx: minima.r ] %[fx: minima.g ] %[fx: minima.b ]"\
info:`
echo "Normalised values are:"
echo " max min"
# Green: 0.358328 0.0297856
echo "Red: " $1 $4
echo "Green:" $2 $5
echo "Blue: " $3 $6
maxmins=($*)
if [[ -z $r_base ]];then
r_base=$1
fi
if [[ -z $g_base ]];then
g_base=$2
fi
if [[ -z $b_base ]];then
b_base=$3
fi
r_shadow=$1
g_shadow=$2
b_shadow=$3
r_max=$4
g_max=$5
b_max=$6
if [ ! -z $profile_name ]; then
set -- `tail -1 "$prof_dir"/"$profile_name"`
r_base=$2
g_base=$3
b_base=$4
echo using profile FB: $1 $r_base $g_base $b_base
else
echo using calculated FB: $r_base $g_base $b_base
fi
# calculate the film density values
eval set -- `convert xc: -format\
"%[fx: -log($r_base) ] \
%[fx: -log($g_base) ] \
%[fx: -log($b_base) ] \
%[fx: -log($r_shadow) - (-log($r_base)) ] \
%[fx: -log($g_shadow) - (-log($g_base)) ] \
%[fx: -log($b_shadow) - (-log($b_base)) ] \
%[fx: -log($r_max) - (-log($r_base)) ] \
%[fx: -log($g_max) - (-log($g_base)) ] \
%[fx: -log($b_max) - (-log($b_base)) ] "\
info:`
echo "log() values are:"
echo " base shadow DMax"
echo "Red: " $1 $4 $7
echo "Green:" $2 $5 $8
echo "Blue: " $3 $6 $9
dmax_measured=$9
densities=($*)
if [ "$dmax_input" = "auto" ]; then
dmax=$dmax_measured
echo using auto calculated dmax
elif [ -z "$dmax_input" ]; then
dmax=$dmax_default
echo using default dmax of:$dmax
else
dmax=$dmax_input
fi
eval set -- `convert xc: -format "%[fx: 2^16/(10^($dmax*.6)) ]" info:`
scale=$1
echo dmax: $dmax
echo scale: $scale
#convert per ideas dpx http://dicomp.arri.de/digital/digital_systems/DIcompanion/ch03.html#scene2digital_linfull
# convert $infile[0] -strip $CSPACE \
# -channel R -fx "dab=-log(u)-(-log($r_base));(((10^(dab*.6))*$scale)-$scale)/QuantumRange" \
# -channel G -fx "dab=-log(u)-(-log($g_base));(((10^(dab*.6))*$scale)-$scale)/QuantumRange" \
# -channel B -fx "dab=-log(u)-(-log($b_base));(((10^(dab*.6))*$scale)-$scale)/QuantumRange" \
# -colorspace sRGB \
# -set comment "$comment" $zip "$outfile"
#converting to a linear scale is rougly grade 00 paper for ilford
DEBUG set -x;
convert -size 65536x1 xc: \
-fx "i/(w-1)" \
-channel R -fx "dab=-log(u)-(-log($r_base));(((10^(dab*.6))*$scale)-$scale)/QuantumRange" \
-channel G -fx "dab=-log(u)-(-log($g_base));(((10^(dab*.6))*$scale)-$scale)/QuantumRange" \
-channel B -fx "dab=-log(u)-(-log($b_base));(((10^(dab*.6))*$scale)-$scale)/QuantumRange" \
-set comment "$comment" +compress "$tmpfileprefix"_clut.tif
if [ "$debug" -eq 2 ]; then
convert -size 65536x1 xc: \
-fx "i/(w-1)" \
-channel B -fx "debug(dab=-log(u)-(-log($b_base)));debug((((10^(dab*.6))*$scale)-$scale)/QuantumRange)" \
null:
fi
if [ ! -x "$(command -v exiftool)" ]; then
comment="film base:$r_base dmax:$dmax Processed with invertscan"
else
exiftool=1
fi
convert $infile[0] "$tmpfileprefix"_clut.tif -clut -strip $CSPACE \
-colorspace sRGB \
-set comment "$comment" $zip "$outfile"
if [ $exiftool -eq 1 ]; then
caption="fb used: $r_base, $g_base, $b_base\n"
caption+="max: ${maxmins[0]}, ${maxmins[1]}, ${maxmins[2]}\n"
caption+="min: ${maxmins[3]}, ${maxmins[4]}, ${maxmins[5]}\n"
caption+="FB D :${densities[0]}, ${densities[1]}, ${densities[2]}\n"
caption+="Shadow D:${densities[3]}, ${densities[4]}, ${densities[5]}\n"
caption+="D-Max :${densities[6]}, ${densities[7]}, ${densities[8]}"
caption=`printf "$caption"`
DEBUG echo "$caption"
exiftool -overwrite_original -Model="DMAX $dmax_input $dmax_measured"\
"-iptc:caption-abstract=$caption"\
"$outfile"
fi
echo inverting: "$outfile"
fi
if [ $approach = "c_printing_density" ]; then
DEBUG echo approach = $approach
echo "Expirmental code"
if [ "$debug" -eq 2 ]; then
convert "$infile[0]" $CSPACE -strip -blur 20x65355 \
-shave 100x100 \
-set comment "$comment" +compress "$tmpfileprefix"_input_for_calculations.tif
fi
# calculate the film min and maximum values
eval set -- `convert "$infile[0]" $CSPACE -strip -blur 20x65355 \
-shave 100x100 \
-format\
"%[fx: maxima.r ] %[fx: maxima.g ] %[fx: maxima.b ]\
%[fx: minima.r ] %[fx: minima.g ] %[fx: minima.b ]"\
info:`
echo "Normalised values are:"
echo " max min"
# Green: 0.358328 0.0297856
echo "Red: " $1 $4
echo "Green:" $2 $5
echo "Blue: " $3 $6
maxmins=($*)
if [[ -z $r_base ]];then
r_base=$1
fi
if [[ -z $g_base ]];then
g_base=$2
fi
if [[ -z $b_base ]];then
b_base=$3
fi
r_shadow=$1
g_shadow=$2
b_shadow=$3
r_max=$4
g_max=$5
b_max=$6
if [ ! -z $profile_name ]; then
set -- `tail -1 "$prof_dir"/"$profile_name"`
r_base=$2
g_base=$3
b_base=$4
echo using profile FB: $1 $r_base $g_base $b_base
else
echo using calculated FB: $r_base $g_base $b_base
fi
# calculate the film density values
eval set -- `convert xc: -format\
"%[fx: -log($r_base) ] \
%[fx: -log($g_base) ] \
%[fx: -log($b_base) ] \
%[fx: -log($r_shadow) - (-log($r_base)) ] \
%[fx: -log($g_shadow) - (-log($g_base)) ] \
%[fx: -log($b_shadow) - (-log($b_base)) ] \
%[fx: -log($r_max) - (-log($r_base)) ] \
%[fx: -log($g_max) - (-log($g_base)) ] \
%[fx: -log($b_max) - (-log($b_base)) ] "\
info:`
echo "log() values are:"
echo " base shadow DMax"
echo "Red: " $1 $4 $7
echo "Green:" $2 $5 $8
echo "Blue: " $3 $6 $9
dmax_measured=$9
densities=($*)
if [ "$dmax_input" = "auto" ]; then
echo TODO need to do check of all three maxes
dmax=$dmax_measured
echo using auto calculated dmax
elif [ -z "$dmax_input" ]; then
dmax=$dmax_default
echo using default dmax of:$dmax
else
dmax=$dmax_input
fi
#these worked for well for the big portra scans
#rscale=0.852
#gscale=1.063
#bscale=1.082
#rscale=1.082602577 #from page 8 "carlos aim"
rscale=1.3 #a stab in the dark for epson 4990
gscale=1
bscale=1
eval set -- `convert xc: -format "%[fx: 2^16/(10^($bscale*$dmax*.6)) ]" info:`
scale=$1
echo dmax: $dmax
echo scale: $scale
#convert per ideas dpx http://dicomp.arri.de/digital/digital_systems/DIcompanion/ch03.html#scene2digital_linfull
# convert $infile[0] -strip $CSPACE \
# -channel R -fx "dab=-log(u)-(-log($r_base));(((10^(dab*.6))*$scale)-$scale)/QuantumRange" \
# -channel G -fx "dab=-log(u)-(-log($g_base));(((10^(dab*.6))*$scale)-$scale)/QuantumRange" \
# -channel B -fx "dab=-log(u)-(-log($b_base));(((10^(dab*.6))*$scale)-$scale)/QuantumRange" \
# -colorspace sRGB \
# -set comment "$comment" $zip "$outfile"
DEBUG set -x;
convert -size 65536x1 xc: \
-fx "i/(w-1)" \
-channel R -fx "dab=-log(u)-(-log($r_base));(((10^($rscale*dab*.6))*$scale)-$scale)/QuantumRange" \
-channel G -fx "dab=-log(u)-(-log($g_base));(((10^($gscale*dab*.6))*$scale)-$scale)/QuantumRange" \
-channel B -fx "dab=-log(u)-(-log($b_base));(((10^($bscale*dab*.6))*$scale)-$scale)/QuantumRange" \
-set comment "$comment" +compress "$tmpfileprefix"_clut.tif
if [ "$debug" -eq 2 ]; then
convert -size 65536x1 xc: \
-fx "i/(w-1)" \
-channel B -fx "debug(dab=-log(u)-(-log($b_base)));debug((((10^(dab*.6))*$scale)-$scale)/QuantumRange)" \
null:
fi
if [ ! -x "$(command -v exiftool)" ]; then
comment="film base:$r_base dmax:$dmax Processed with invertscan"
else
exiftool=1
fi
convert $infile[0] "$tmpfileprefix"_clut.tif -clut -strip $CSPACE \
-colorspace sRGB \
-profile "$prof_dir"/ra4.icc \
-set comment "$comment" $zip "$outfile"
#convert $infile[0] "$tmpfileprefix"_clut.tif -clut -strip $CSPACE \
# -color-matrix \
# "1.4397684822 -0.3534344629 -0.0863340647
#-0.0818808588 1.1424821575 -0.06060129
#-0.0169540131 -0.0896409556 1.1065949943"\
# -colorspace sRGB \
# -set comment "$comment" $zip "$outfile"
if [ $exiftool -eq 1 ]; then
caption="fb used: $r_base, $g_base, $b_base\n"
caption+="max: ${maxmins[0]}, ${maxmins[1]}, ${maxmins[2]}\n"
caption+="min: ${maxmins[3]}, ${maxmins[4]}, ${maxmins[5]}\n"
caption+="FB D :${densities[0]}, ${densities[1]}, ${densities[2]}\n"
caption+="Shadow D:${densities[3]}, ${densities[4]}, ${densities[5]}\n"
caption+="D-Max :${densities[6]}, ${densities[7]}, ${densities[8]}\n"
caption+="R Den scaling :$rscale"
caption=`printf "$caption"`
DEBUG echo "$caption"
exiftool -overwrite_original -Model="DMAX $dmax_input $dmax_measured"\
"-iptc:caption-abstract=$caption"\
"$outfile"
fi
echo inverting: "$outfile"
fi