Create An Optimized PDF of CBR/CBZ Files

For some strange reason, in the land of the internet when people create books with flowable text (i.e. novels), they use the PDF format, which is simply awful for the medium. Yet when they have a content that lends itself perfectly to the PDF format, like comics, they instead use an unnecessary made-up format that is just a renamed ZIP or RAR file.

Also, for some reason, JPEG-2000 as a format seems to have never gained much traction. I do not understand why. It is so much better than classic JPEG. And because PDF readers do support the JPEG-2000 format, it seems even more ideal as a format for comics to make the file more portable, and smaller with no perceptual loss of quality.

I have a Remarkable 2, and it’s a perfect reader for manga and comics (at least black and white ones), and it handles PDFs better, so I wrote this script to convert a CBZ to a PDF using JPEG-2000 for compression.

This script requires the imagemagick and img2pdf packages.

Note: This does not work in Ubuntu linux, as they inexplicably removed all support for JPEG-2000. It does, however work perfectly on a Raspberry Pi (and probably Debian).

#!/bin/bash

CURDIR=$( pwd )

trap 'rm -rf "${CURDIR}"/*.$$ ; exit 0' 0 1 2 3 13 15

# This is the JPEG2000 compress rate.  In my own testing, 24 provides nearly no
# perceptual loss with a dramatic file size reduction.
#
# 0 is lossless, and will give a larger file, but will incur perfect reproduction.
# > 0 increases compression with progressivly more loss.

COMPRESS_RATE=24

COMICFILE=$1

mkdir -p comicpdf.$$

unzip -j -d "comicpdf.$$" "${COMICFILE}"


cd comicpdf.$$

if [ "$( ls -1 *.[Jj][Pp][Gg] 2> /dev/null )" ]
then
	for file in *.[Jj][Pp][Gg]
	{
		# Because of the Microsoft world not handling file name case, make
		# sure that the extension is lower case so basename works correctly.

		mv -n "$file" "$( echo "$file" | sed -e "s/[Jj][Pp][Gg]$/jpg/" )"
		echo -ne "Converting ${file}..."
		convert "$file" -define jp2:rate=${COMPRESS_RATE} "$( basename "$file" .jpg ).jp2"
		echo "Done."
	}
fi

if [ "$( ls -1 *.[Pp][Nn][Gg] 2> /dev/null )" ]
then
	for file in *.png
	{
		# Because of the Microsoft world not handling file name case, make
		# sure that the extension is lower case so basename works correctly.

		mv -n "$file" "$( echo "$file" | sed -e "s/[Pp][Nn][Gg]$/png/" )"
		echo -ne "Converting ${file}..."
		convert "$file" -define jp2:rate=${COMPRESS_RATE} "$( basename "$file" .png ).jp2"
		echo "Done."
	}
fi

if [ "$( ls -1 *.[Jj][Pp]2 2> /dev/null )" ]
then
	echo -ne "Creating PDF..."
	img2pdf --output "${CURDIR}/$( basename -s .cbz "${COMICFILE}" ).pdf" *.jp2
	echo "Done."
fi

cd "${CURDIR}"

Leave a Comment