That generator is written on zsh and is aimed only to deal with JPEG XL
and WebP image formats solely. JPEG XL is superior to any other format
-both in lossy and lossless modes. The only exception is screenshots
-encoded in lossless WebP (VP8L) format.
+both in lossy and lossless modes. WebP just can not be losslessly
+transcoded to JPEG XL, so it is left for backward compatibility.
Just run that script inside the directory with .jxl/.webp files. For
each file the small preview will be generated in lossy WebP format. Also
included on the first page.
Following external utilities are called: djxl, jxlinfo, exiftool,
-pamtopng, pnmscale, pngcrush, advpng, webpinfo, dwebp, cwebp.
+pamtopng, pnmscale, pngcrush, advpng, webpinfo, dwebp, cwebp, parallel.
#!/usr/bin/env zsh
# Copyright (C) 2022-2023 Sergey Matveev <stargrave@stargrave.org>
-VERSION=0.2.0
+VERSION=0.3.0
set -e
FilePermissions
)
-djxl2ppm() {
- djxl $1 $1.ppm || {
- djxl $1 $1.pgm
- mv $1.pgm $1.ppm
- }
- [[ -r ${1}-ec0.ppm ]] || return 0
- mv ${1}-ec0.ppm $1.ppm
- rm ${1}-ec1.pgm
-}
-
[[ -z $style ]] || style="<link rel=\"stylesheet\" type=\"text/css\" href=\"$style\">"
+mkdir -p alt info preview
setopt EXTENDED_GLOB
-imgs=((*.jxl|*.webp~*.preview.webp)($ordering))
+
+imgs=()
+for img (*.jxl(N)) { [[ -r info/$img.img ]] || imgs=($imgs $img) }
+[[ ${#imgs} == 0 ]] || {
+ echo JPEG XL info... >&2
+ parallel "jxlinfo {} > info/{}.img" ::: $imgs
+}
+
+imgs=()
+for img (*.webp(N)) { [[ -r info/$img.img ]] || imgs=($imgs $img) }
+[[ ${#imgs} == 0 ]] || {
+ echo WebP info... >&2
+ parallel "webpinfo {} > info/{}.img" ::: $imgs
+}
+
+imgs=()
+src=((*.jxl|*.webp))
+for img ($src) { [[ -r info/$img.exif ]] || imgs=($imgs $img) }
+src=()
+[[ ${#imgs} == 0 ]] || {
+ echo Exif info... >&2
+ parallel "exiftool -escapeHTML -htmlFormat -groupHeadings --${=${(j/ --/)exifTagsOmit}} {} > info/{}.exif" ::: $imgs
+}
+
+imgs=((*.jxl|*.webp)($ordering))
pages=$(( ${#imgs} / $pagesize ))
[[ $(( $pages * $pagesize )) -lt ${#imgs} ]] && pages=$(( $pages + 1 ))
local tmp=`mktemp`
trap "rm -f $tmp" HUP PIPE INT QUIT TERM EXIT
+jpgs=()
+pngs=()
+ppms_jxl=()
+ppms_webp=()
+for img ($imgs) {
+ [[ -r info/$img.img ]]
+ if [[ $img:e = jxl ]] ; then
+ [[ -r alt/$img.jpg ]] || [[ -r alt/$img.png ]] && : || {
+ grep -q "JPEG bitstream reconstruction" info/$img.img &&
+ jpgs=($jpgs $img) || pngs=($pngs $img)
+ }
+ [[ -r preview/$img.webp ]] || ppms_jxl=($ppms_jxl $img)
+ else
+ [[ -r preview/$img.webp ]] || ppms_webp=($ppms_webp $img)
+ fi
+}
+
+[[ ${#jpgs} == 0 ]] || {
+ echo JPEG reconstruction... >&2
+ parallel "djxl --quiet {} alt/{}.jpg && touch -r {} alt/{}.jpg" ::: $jpgs
+}
+jpgs=()
+
+[[ ${#pngs} == 0 ]] || {
+ echo PNG generation... >&2
+ parallel "${0:h}/djxl2ppm {}" ::: $pngs
+ parallel "pamtopng < {}.ppm > {}.png && rm {}.ppm" ::: $pngs
+ parallel "pngcrush -warn -rem alla -rem allb -z 2 {}.png alt/{}.png && rm {}.png" ::: $pngs
+ parallel "advpng --quiet --recompress -4 alt/{}.png && touch -r {} alt/{}.png" ::: $pngs
+}
+pngs=()
+
+[[ ${#ppms_jxl} == 0 ]] || {
+ echo JPEG XL decompression for preview... >&2
+ parallel "${0:h}/djxl2ppm {}" ::: $ppms_jxl
+}
+[[ ${#ppms_webp} == 0 ]] || {
+ echo WebP decompression for preview... >&2
+ parallel "dwebp {} -ppm -o {}.ppm" ::: $ppms_webp
+}
+ppms=($ppms_jxl $ppms_webp)
+[[ ${#ppms} == 0 ]] || {
+ echo Preview scaling and WebP compression... >&2
+ parallel "pnmscale -w 100 < {}.ppm > {}.ppm.ppm && mv {}.ppm.ppm {}.ppm && cwebp -quiet -pass 10 -alpha_filter best -m 6 -o preview/{}.webp {}.ppm && rm {}.ppm && touch -r {} preview/{}.webp" ::: $ppms
+}
+ppms_jxl=()
+ppms_webp=()
+ppms=()
+
for (( i=1 ; i <= ${#imgs} ; i++ )) {
local img=${imgs[$i]}
echo $i $img
}
[[ -r ${img}.html ]] && cat ${img}.html >> $tmp
echo "<hr/>" >> $tmp
+ [[ -r info/$img.img ]]
+ echo "<pre>" >> $tmp
+ cat info/$img.img >> $tmp
+ echo "</pre>" >> $tmp
if [[ $img:e = jxl ]] ; then
- echo "<pre>" >> $tmp
- jxlinfo $img > $img.info
- cat $img.info >> $tmp
- echo "</pre>" >> $tmp
echo "Alternative formats:" >> $tmp
- if grep -q "JPEG bitstream reconstruction" $img.info ; then
- [[ -r $img.jpg ]] || {
- djxl $img $img.jpg
- touch -r $img $img.jpg
- }
- echo "<a href=\"$img.jpg\">JPEG</a>" >> $tmp
- else
- [[ -r $img.png ]] || {
- djxl2ppm $img
- pamtopng < $img.ppm > $img.png
- rm $img.ppm
- pngcrush -rem alla -rem allb -z 2 $img.png $img.png.png
- mv $img.png.png $img.png
- advpng -z -4 $img.png
- touch -r $img $img.png
- }
+ [[ -r alt/$img.jpg ]] && {
+ echo "<a href=\"alt/$img.jpg\">JPEG</a>" >> $tmp
+ } || {
echo "<a href=\"$img.png\">PNG</a>" >> $tmp
- fi
- rm $img.info
- [[ -r $img.preview.webp ]] || djxl2ppm $img
- else
- echo "<pre>" >> $tmp
- webpinfo $img >> $tmp
- echo "</pre>" >> $tmp
- [[ -r $img.preview.webp ]] || dwebp $img -ppm -o $img.ppm
+ }
fi
echo "<hr/>" >> $tmp
- exiftool -escapeHTML -htmlFormat -groupHeadings \
- --${=${(j/ --/)exifTagsOmit}} $img >> $tmp
- [[ -r $img.ppm ]] && {
- pnmscale -w 100 < $img.ppm > $img.ppm.ppm
- mv $img.ppm.ppm $img.ppm
- cwebp -pass 10 -alpha_filter best -m 6 -mt -o $img.preview.webp $img.ppm
- rm $img.ppm
- touch -r $img $img.preview.webp
- }
+ [[ -r info/$img.exif ]]
+ cat info/$img.exif >> $tmp
echo "</body></html>" >> $tmp
cmp -s $tmp $dst || {
cat $tmp > $dst
alt=`cat ${imgs[$img]}.txt`
title="title=\"$alt\""
}
- echo "<img alt=\"$alt\" $title src=\"${imgs[$img]}.preview.webp\"/></a>" >> $tmp
+ echo "<img alt=\"$alt\" $title src=\"preview/${imgs[$img]}.webp\"/></a>" >> $tmp
}
echo "</body></html>" >> $tmp
cmp -s $tmp $dst || {