cdscript/cdscript.sh

242 lines
5.8 KiB
Bash
Raw Normal View History

2025-08-28 12:31:50 +02:00
#!/usr/bin/env bash
# __ __ __
# .----.--| | .-----.----.----.|__|.-----.| |_
# | __| _ | |__ --| __| _|| || _ || _|
# |____|_____| |_____|____|__| |__|| __||____|
# |__|
#
# script to make cd jewel case inserts easily
# by sun https://sx7n8.tech/
#
# dependencies are: imagemagick, bash, awk
# TODO:
2025-08-29 18:31:22 +00:00
# - !!! Add support for back insert !!!
# - Remove bugs
# - Add more paper types DONE
# - Make DPI a command line option DONE
# - Add different folding points for inserts
# - Clean up code and add more comments
# - Improve input and output further DONE
# usage message
USAGE="Usage: $0 -p <paper> -c <cover> -b <back> [-i <back_image>] [-m <border>] -o <output>"
# help message
HELP="Script to create printable CD jewel case inserts
Usage:
2025-08-29 18:31:22 +00:00
$0 -p <paper> -c <cover> -b <back> [-i <back_image>] [-m <border>] [-d DPI] -o <output>
Required options:
2025-08-29 18:31:22 +00:00
-p Paper format a4 | letter | legal
-c Album cover path Path to cover image
-b Back type no | image
-o Output file Path to save the resulting insert (NO PNG)
2025-08-29 18:31:22 +00:00
Optional options:
-i Back image path Required if back type is 'image'
-m Border width (px) Adds a border around the cover/back
2025-08-29 18:31:22 +00:00
-d DPI Desired DPI of the output
DO NOT USE PNG FOR OUTPUT
"
2025-08-29 18:31:22 +00:00
# default DPI
DPI="300"
# error function
error() {
echo -e "Error: $1" >&2
echo -e "$USAGE" >&2
exit 1
}
# file existance check
check_file_exists() {
if [ ! -f "$1" ]; then
error "File '$1' does not exist."
fi
}
# file existance check but opposite
check_output_file() {
if [ -f "$1" ]; then
error "Output file '$1' already exists."
fi
}
2025-08-29 18:31:22 +00:00
# number check
check_dpi() {
if ! [[ "$var" =~ ^[1-9][0-9]*$ ]]; then
error "DPI is not a valid number"
fi
}
# getops argument handling
2025-08-29 18:31:22 +00:00
while getopts "hp:c:b:i:m:o:d:" o; do
case "${o}" in
h)
echo -e "$HELP"
exit
;;
p)
if [[ "$OPTARG" != "a4" && "$OPTARG" != "letter" ]]; then
error "Invalid paper type '$OPTARG'. Must be 'a4' or 'letter'."
fi
PAPER="$OPTARG"
;;
c)
check_file_exists "$OPTARG"
COVER="$OPTARG"
COVERSIZE="$(identify -format "%w" "$COVER")"
;;
b)
if [[ "$OPTARG" != "no" && "$OPTARG" != "image" ]]; then
error "Invalid back type '$OPTARG'. Must be 'no' or 'image'."
fi
BACKTYPE="$OPTARG"
;;
i)
if [[ "$BACKTYPE" != "image" ]]; then
error "-i option requires back type to be 'image'."
fi
check_file_exists "$OPTARG"
BACKIMG="$OPTARG"
;;
m)
BORDER="TRUE"
BORDER_WIDTH="$OPTARG"
;;
o)
check_output_file "$OPTARG"
OUTPUT="$OPTARG"
;;
2025-08-29 18:31:22 +00:00
d)
check_dpi "$OPTARG"
DPI="$OPTARG"
;;
*)
echo -e "$USAGE"
exit 1
;;
esac
done
# check if something is missing
[[ -z "$PAPER" ]] && error "Missing paper format (-p)."
[[ -z "$COVER" ]] && error "Missing cover image (-c)."
[[ -z "$BACKTYPE" ]] && error "Missing back type (-b)."
[[ -z "$OUTPUT" ]] && error "Missing output file (-o)."
[[ "$BACKTYPE" == "image" && -z "$BACKIMG" ]] && error "Missing back image (-i) for back type 'image'."
2025-08-28 16:15:16 +00:00
# function to convert mm to px with dpi
CONVERT() { awk -v mm="$1" -v dpi="$2" 'BEGIN{printf("%d", mm/25.4*dpi + 0.5)}'; }
# cover art size (mm)
CO_MM="120"
CO_PX="$(CONVERT "$CO_MM" "$DPI")"
# Width and Height of paper in mm
2025-08-28 12:31:50 +02:00
A4MM_W="210"
A4MM_H="297"
2025-08-28 12:31:50 +02:00
LTMM_W="216"
LTMM_H="279"
2025-08-29 18:31:22 +00:00
LGMM_W="216"
LGMM_H="279"
2025-08-28 12:31:50 +02:00
2025-08-28 16:15:16 +00:00
# same values in pixels
2025-08-28 12:31:50 +02:00
A4PX="$(CONVERT "$A4MM_W" "$DPI")x$(CONVERT "$A4MM_H" "$DPI")"
LTPX="$(CONVERT "$LTMM_W" "$DPI")x$(CONVERT "$LTMM_H" "$DPI")"
2025-08-29 18:31:22 +00:00
LGPX="$(CONVERT "$LGMM_W" "$DPI")x$(CONVERT "$LGMM_H" "$DPI")"
2025-08-28 12:31:50 +02:00
# assign to the 'size' variable the right value
if [ "$PAPER" = "a4" ]; then
SIZE=$A4PX
2025-08-28 16:15:16 +00:00
elif [ "$PAPER" = "letter" ]; then
2025-08-28 12:31:50 +02:00
SIZE=$LTPX
2025-08-29 18:31:22 +00:00
elif [ "$PAPER" = "legal" ]; then
SIZE=$LGPX
2025-08-28 12:31:50 +02:00
fi
# create a blank file with the specified paper type
2025-08-29 11:36:49 +00:00
magick -colorspace sRGB -type TrueColor -depth 8 -size $SIZE canvas:white "$OUTPUT" > /dev/null
2025-08-28 16:15:16 +00:00
# draws border (rectangle)
if [ "$BORDER" = "TRUE" ]; then
INSET=$((BORDER_WIDTH / 2))
2025-08-29 11:36:49 +00:00
magick ""$OUTPUT"" \( -size $((CO_PX + 2 * BORDER_WIDTH))x$((CO_PX * 2 + 2 * BORDER_WIDTH)) xc:none -colorspace sRGB -type TrueColor -depth 8 -fill none -stroke black -strokewidth $BORDER_WIDTH -draw "rectangle $INSET,$INSET $((CO_PX + BORDER_WIDTH - 1)),$((CO_PX * 2 + BORDER_WIDTH - 1))" \) -gravity center -composite ""$OUTPUT""
2025-08-28 16:15:16 +00:00
2025-08-29 18:31:22 +00:00
fi
2025-08-28 16:15:16 +00:00
2025-08-29 18:31:22 +00:00
# adds the cover
magick \
-colorspace sRGB\
-type TrueColor \
-depth 8 \
"$OUTPUT" \
\( "$COVER" \
-resize ${CO_PX}x${CO_PX} \
-rotate 270 \) \
-gravity center \
-geometry +0-$((CO_PX/2)) \
-composite \
"$OUTPUT" \
> /dev/null
# adds back
if [ "$BACKTYPE" = "image" ]; then # if the back is an image
# adds image
magick \
-colorspace sRGB \
-type TrueColor \
-depth 8 \
"$OUTPUT" \
\( "$BACKIMG" \
-resize ${CO_PX}x${CO_PX} \
-rotate 270 \) \
-gravity center \
-geometry +0+$((CO_PX/2)) \
-composite \
"$OUTPUT" \
> /dev/null
else # if the back is not an image
# adds white square
magick \
-colorspace sRGB \
-type TrueColor \
-depth 8 \
"$OUTPUT" \
\( -size ${CO_PX}x${CO_PX} \
xc:'#FFFFFF' \) \
-gravity center \
-geometry +0+$((CO_PX/2)) \
-composite "$OUTPUT"\
> /dev/null
2025-08-28 16:15:16 +00:00
fi