Here's My Script I Put Together to Process My Pictures For The Website
For a long time, I’ve been wanting to make a script to generate the srcset
for this website. Hugo and Zola have ways to do it when it’s built, but that seemed to slow it down a little. Only by a few seconds, but I am impatient, and it seems wasteful. The other thing is that I still had to manually remove the location metadata from the photos because I didn’t want that included. I had to run jpegoptim too to optimize the picture.
I used srcset which is written in rust. I wanted to have a little more flexibility and wanted to practice sh since that’s been fun, so I saw this as the perfect opportunity to do just that.
This requires Imagemagick, jpegoptim, exiftran and exiftool to be installed.
The only options that it has right now is -c (--clear)
for clear, j (--jpeg)
to convert file to Jpg and -o (--overwrite)
. The -c (--clear)
option removes the location data. The -o (--overwrite)
option tells it to overwrite the files that exist in the output folder. I have added -q (--quiet)
which quiets the output. By default, it skips files that already exist. The script accepts a file, a list of files, or a directory or directories. It generates the various sized images to create the srcset then writes out the HTML
. My static site generator can just import that file and update the URLs of the images to the actual URL, and it’s good to go.
Imagemagick
handles the resizing itself.
jpegoptim
makes the files slightly smaller.
exiftool
is the one used if I wish to remove the location data.
If it’s useful to you feel free to use it and modify it to fit your needs. Thanks to the srcset
rust program that inspired me to create this for myself. It was a fun little project for me and I learned a lot from doing it.
It generates the images for the srcset
in eight sizes. In addition, it generates those eight sizes in three formats. It creates avif
, webp
and, of course, the universal jpeg
format.
I added a check to not erroneously tell me that the actual arguments for the command are not valid files. I also added the -j
option to convert the file to a jpeg first using Imagemagick. I changed the settings on my phone’s camera to save the pictures as heic to save space. Most browsers don’t seem to support that format right now.
#!/bin/sh
trap ctrl_c INT
ctrl_c () {
echo "Exiting"
exit 1
}
convert(){
set -e
outfile="${filename%.*}"
dirname=$(dirname "$filename")
outfile=$(basename "$outfile")
outfile=$(echo "$dirname/$outfile.jpg")
magick "$filename" -quality 100% "$outfile"
filename=$outfile
resize_file
}
resize_file() {
set -e
if $gpsclear; then
if [ ! $quiet ]; then
exiftool -overwrite_original -gps:all= "$filename"
else
exiftool -q -overwrite_original -gps:all= "$filename"
fi
fi
if [ ! $quiet ]; then
echo Optomizing "$filename"
fi
jpegoptim "$filename"
N="
"
if [ ! $quiet ]; then
echo $N$N$N$N
fi
outfile="${filename%.*}"
outfile=$(basename -- "$outfile")
dirname=$(dirname "$filename")
outfolder="$dirname/resized/"
type="${filename##*.}"
mkdir -p "$outfolder"
srcset=""
J="<source sizes=\"(min-width: 1024px) 50vw, 100vw\" type=\"image/jpeg\" srcset = \""
W="<source sizes=\"(min-width: 1024px) 50vw, 100vw\" type=\"image/webp\" srcset = \""
A="<source sizes=\"(min-width: 1024px) 50vw, 100vw\" type=\"image/avif\" srcset = \""
out=legacy
if [ $quiet ]; then
for out in 480 640 768 960 1024 1366 1600 1920; do
outw=$out"w"
outname="$outfolder$outfile-$outw.$type"
outnameavif="$outfolder$outfile-$outw.avif"
outnamewebp="$outfolder$outfile-$outw.webp"
if [ ! -f $outname ]; then
magick "$filename" -quiet -interlace Plane -quality 100 -adaptive-resize $out "$outname"
elif [ $overwrite ]; then
magick "$filename" -quiet -interlace Plane -quality 100 -adaptive-resize $out "$outname"
fi
if [ ! -f $outnameavif ]; then
magick "$filename" -quiet -define heic:speed=9 -adaptive-resize $out "$outnameavif"
elif [ $overwrite ]; then
magick "$filename" -quiet -define heic:speed=9 -adaptive-resize $out "$outnameavif"
fi
if [ ! -f $outnamewebp ]; then
magick "$filename" -quiet -interlace Plane -define partitions=3 -adaptive-resize $out "$outnamewebp"
elif [ $overwrite ]; then
magick "$filename" -quiet -interlace Plane -define partitions=3 -adaptive-resize $out "$outnamewebp"
fi
if [ "$out" -ne 1920 ]; then
T="resized/$outfile-$outw.$type"
J="$J$T $outw, $N"
T="resized/$outfile-$outw.webp"
W="$W$T $outw, $N"
T="resized/$outfile-$outw.avif"
A="$A$T $outw, $N"
else
T="resized/$outfile-$outw.$type"
J="$J$T $outw $N"
T="resized/$outfile-$outw.webp"
W="$W$T $outw $N"
T="resized/$outfile-$outw.avif"
A="$A$T $outw $N"
fi
done
else
for out in 480 640 768 960 1024 1366 1600 1920; do
outw=$out"w"
outname="$outfolder$outfile-$outw.$type"
outnameavif="$outfolder$outfile-$outw.avif"
outnamewebp="$outfolder$outfile-$outw.webp"
if [ ! -f $outname ]; then
magick "$filename" -interlace Plane -quality 100 -adaptive-resize $out "$outname"
elif [ $overwrite ]; then
magick "$filename" -interlace Plane -quality 100 -adaptive-resize $out "$outname"
fi
if [ ! -f $outnameavif ]; then
magick "$filename" -define heic:speed=9 -adaptive-resize $out "$outnameavif"
elif [ $overwrite ]; then
magick "$filename" -verbose -define heic:speed=9 -adaptive-resize $out "$outnameavif"
fi
if [ ! -f $outnamewebp ]; then
magick "$filename" -interlace Plane -define partitions=3 -adaptive-resize $out "$outnamewebp"
elif [ $overwrite ]; then
magick "$filename" -interlace Plane -define partitions=3 -adaptive-resize $out "$outnamewebp"
fi
if [ ! $quiet ]; then
echo "generating $outname"
fi
if [ "$out" -ne 1920 ]; then
T="resized/$outfile-$outw.$type"
J="$J$T $outw, $N"
T="resized/$outfile-$outw.webp"
W="$W$T $outw, $N"
T="resized/$outfile-$outw.avif"
A="$A$T $outw, $N"
else
T="resized/$outfile-$outw.$type"
J="$J$T $outw $N"
T="resized/$outfile-$outw.webp"
W="$W$T $outw $N"
T="resized/$outfile-$outw.avif"
A="$A$T $outw $N"
fi
done
fi
Default="resized/$outfile-768.jpg"
srcset="$A \">$W \">$J \">$N <img src =\"$Default\""
if [ ! $quiet ]; then
echo "$srcset"
echo "$srcset" >"$outfolder$outfile.srcset"
else
echo "$srcset" >"$outfolder$outfile.srcset"
fi
}
gpsclear=false
jpeg=false
while getopts 'cojq --overwrite --clear --jpeg --quiet' option; do
case $option in
j | --jpeg ) jpeg=true ;;
c | --clear ) gpsclear=true ;;
o | --overwrite ) overwrite=true ;;
q | --quiet ) quiet=true ;;
\?)
echo "usage `basename $(0)` OPTION path/to/file(s) or path/to/folder"
echo "available options:"
echo "`basename $(0) [--overwrite] -o overwrites existing files."
echo "`basename $(0) -c clears location data."
echo "`basename $(0)` -j jpeg converts to jpeg."
echo "`basename $(0)` -q quiet quiets the output"
exit 1
;; #Invalid argument
esac
done
for f in "$@"; do
if [ -d "$f" ]; then
files=$(find $f -type f -name "*.jpg" -o -name "*.jpeg" -o -name "*.heic"-maxdepth 1)
for filename in $files; do
resize_file
done
elif [ -f "$f" ]; then
filename="$f"
type=$(file -b --mime-type $filename)
if [ $jpeg == true ] && [ $type == "image/heic" ];
then
#echo $jpeg
convert
else
if [ ! $quiet ]; then
echo $type
fi
resize_file
fi
else
if [ ! "-" == $(echo "$f" | cut -c -1) ]; then
echo "$f is neither a file or directory"
fi
fi
done