~q3cpma/scripts

ref: dfd8669b987f10271c4884c05764539540e96a9d scripts/manga_convert_ereader.sh -rwxr-xr-x 6.6 KiB
dfd8669bq3cpma Fix selfdir sed 8 months ago
                                                                                
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
#!/bin/sh -eu
# Dependencies: util.sh, archive_extract.sh, archive_create.sh, optipng,
#               imagemagick-7, parallel, waifu2x-converter-cpp
# Optional:     img2pdf, natsort (both for PDF output)
# Portability:  GNU, *BSD, MacOS, Illumos
# +-------------+-----+---------+--------+--------------+---------+-------+---------+-------+-----+------+-------+
# | cmd/OS      | GNU | OpenBSD | NetBSD | DragonflyBSD | FreeBSD | MacOS | Illumos | HP-UX | AIX | IRIX | Tru64 |
# +-------------+-----+---------+--------+--------------+---------+-------+---------+-------+-----+------+-------+
# | find -iname | o   | o       | o      | o            | o       | o     | o       |       |     |      |       |
# +-------------+-----+---------+--------+--------------+---------+-------+---------+-------+-----+------+-------+
# | mktemp -d   | o   | o       | o      | o            | o       | o     | o       | X     |     |      | o     |
# +-------------+-----+---------+--------+--------------+---------+-------+---------+-------+-----+------+-------+
# | xargs -0    | o   | o       | o      | o            | o       | o     | o       |       |     |      |       |
# +-------------+-----+---------+--------+--------------+---------+-------+---------+-------+-----+------+-------+

# Check if local or typeset is available
if ! sh -c 'fun() { local a=1; }; fun'
then
	if sh -c 'fun() { typeset a=1; }; fun'
	then
		alias local=typeset
	else
		echo "local/typeset not supported by sh, aborting"
		exit 1
	fi
fi

if command readlink --version 2>/dev/null | grep -qF '^readlink (GNU coreutils)'
then
	alias preadlinkf='readlink -f --'
elif command -v greadlink >/dev/null
then
	alias preadlinkf='greadlink -f --'
else
	# Portable readlink -f using GNU's semantics (last component need not exist)
	# Currently passes the tests from https://github.com/ko1nksm/preadlinkf
	# except loop detection (`getconf SYMLOOP_MAX` is undefined here, anyway)
	preadlinkf()
	{
		[ $# -eq 0 ] && return 1
		local i= status=0 pwd="$(pwd -P)" base= dir=
		for i
		do
			! [ "$i" ] && { status=1; continue; }
			if [ -d "$i" ]
			then
				CDPATH= cd -P -- "$i" >/dev/null 2>&1 || return 1
				pwd -P
			else
				case "$i" in */) [ -e "${i%/}" ] && return 1;; esac
				while true
				do
					CDPATH= cd -P -- "$(dirname -- "$i")" >/dev/null 2>&1 || return 1
					base=${i%/}
					base=${base##*/}
					if [ -L "$base" ]
					then
						i=$(ls -l -- "$base")
						i=${i#*"$base -> "}
					else
						dir=$(pwd -P)
						dir=${dir%/}
						printf '%s/%s\n' "$dir" "$base"
						break
					fi
				done
			fi
			cd -- "$pwd"
		done
		return $status
	}
fi
selfdir=$(dirname -- "$(preadlinkf "$0")")
PATH=$PATH:$selfdir
. "$selfdir"/util.sh

requirebin optipng magick parallel waifu2x-converter-cpp


usage()
{
	name=$(basename "$(preadlinkf "$0")")
	cat <<EOF | text_format
**NAME**
    $name - Convert an archived manga for ereader usage

**SYNOPSIS**
    $name [**-hsnw**] [**-d** __DIMENSIONS__] \
[**-g** __GREYLEVELS__] __ARCHIVE_IN__ __OUT__

**DESCRIPTION**
    The pictures composing __ARCHIVE_IN__ will be converted to grayscale,
    rotated to maximize screen usage, resized using quality filters, posterized
    and dithered to save space then archived to __OUT__ (cbz, cbr, cbt or pdf).

    **-d** __DIMENSIONS__
        Set the target screen dimensions to "WIDTHxHEIGHT" (defaults to
        $outdim).

    **-g** __GREYLEVELS__
        Set the number of levels of grey that the target screen can display
        (defaults to $greylevels).

    **-h**
        Print this notice and exit.

    **-n**
        Normalize levels.

    **-s**
        Apply some light sharpening after resizing.

    **-w**
        Remove JPEG artifacts using waifu2x before resizing.

EOF
	exit $1
}

outdim=1404x1872
greylevels=16
denoise=false
sharpen=false
normalize=false
while getopts "d:hg:nsw" OPT
do
	case "$OPT" in
		d)  outdim=$OPTARG;;
		g)  greylevels=$OPTARG;;
		n)  normalize=true;;
		s)  sharpen=true;;
		w)  denoise=true;;
		h)  usage 0;;
		\?) usage 1;;
	esac
done
shift $((OPTIND - 1))

[ $# -ne 2 ] && usage 1
! match "$outdim" '[0-9]+x[0-9]+' && die "$outdim: invalid dimension format"

in=$1
out=$2
requirefile -f "$in"
forbidfile "$out"
match "$out" '.*\.pdf' && requirebin img2pdf natsort

outw=${outdim%x*}
outh=${outdim#*x}
depth=$(pecho "l($greylevels)/l(2)" | bc -l | cut -d. -f1)

workdir=$(mktemp -d)
tempscript=$(pmktemp)

trap 'rm -f -- "$out"; exit 1' HUP INT QUIT ABRT ALRM TERM
trap 'rm -rf -- "$workdir" "$tempscript"' EXIT


# Can't export functions in POSIX sh, so use a temp file
cat <<- EOF >"$tempscript"
	#!/bin/sh
	w=\$(magick identify -format '%w' "\$1")
	h=\$(magick identify -format '%h' "\$1")
	out=\${1%.*}.png
	upscale=false
	rot=
	sharp=
	norm=

	if [ \$w -gt \$h ]
	then
		rot="-rotate -90"
		tmp=\$h
		h=\$w
		w=\$tmp
	fi

	if [ \$w -lt $outw ] || [ \$h -lt $outh ]
	then
		r=\$(echo "w=$outw / \$w; h=$outh / \$h; if (h > w) h else w" | bc)
		upscale=true
	fi

EOF

if $sharpen
then
	cat <<- EOF >>"$tempscript"
	sharp="-unsharp 0x3+0.15+0.5"
EOF
fi

if $normalize
then
	cat <<- EOF >>"$tempscript"
	norm=-normalize
EOF
fi

if $denoise
then
	cat <<- EOF >>"$tempscript"
	if [ "\${1%.jpeg}" != "\$1" ] || [ "\${1%.jpg}" != "\$1" ]
	then
		if \$upscale
		then
			waifu2x-converter-cpp --jobs 1 --log-level 0 --png-compression 0 \
				--mode noise-scale --noise-level 1 --scale-ratio \$r \
				--input "\$1" --output "\$out"
		else
			waifu2x-converter-cpp --jobs 1 --log-level 0 --png-compression 0 \
				--mode noise --noise-level 1 \
				--input "\$1" --output "\$out"
		fi
		rm -- "\$1"
		set -- "\$out"
	fi
EOF
else
	cat <<- EOF >>"$tempscript"
	if \$upscale
	then
		waifu2x-converter-cpp --jobs 1 --log-level 0 --png-compression 0 \
			--mode scale --scale-ratio \$r --input "\$1" --output "\$out"
		if [ "\$out" != "\$1" ]
		then
			rm -- "\$1"
			set -- "\$out"
		fi
	fi
EOF
fi

cat <<EOF >>"$tempscript"
	magick convert -limit thread 1 -colorspace Gray \$norm \$rot \
		-filter RobidouxSharp -distort Resize "${outw}x${outh}" \$sharp \
		-dither FloydSteinberg -colors "$greylevels" -depth "$depth" \
		"\$1" "\$out"

	if [ "\$out" != "\$1" ]
	then
		rm -- "\$1"
	fi
	optipng -o2 -quiet "\$out"
EOF
chmod u+x -- "$tempscript"

archive_extract.sh -d "$workdir" "$in" >/dev/null
find "$workdir" -type f ! \( -iname '*.jpg' -o -iname '*.jpeg' \
	-o -iname '*.png' \) -exec rm -- {} +
find "$workdir" -type f \( -iname '*.jpg' -o -iname '*.jpeg' -o \
	-iname '*.png' \) | parallel "$tempscript" {}

out=$(preadlinkf "$out")
cd -- "$workdir"
listfiles . | sed 's#^\./##' | \
	case "$out" in
		*.cbz|*.cbt|*.cbr)
			xargsnl archive_create.sh "$out"
			;;
		*.pdf)
			natsort | xargsnl img2pdf >"$out"
			;;
		*)
			die "$out: unknown format"
			;;
	esac