Skip to content

Instantly share code, notes, and snippets.

@gwpl
Last active July 28, 2020 20:23
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save gwpl/6d6c1457b4d1f6b778917a2f7c3c57fd to your computer and use it in GitHub Desktop.
Save gwpl/6d6c1457b4d1f6b778917a2f7c3c57fd to your computer and use it in GitHub Desktop.
Bash script that generates tex with barcode containing data from commandline. gen_barcode.sh - has "preview|save|print" options and is tailored to be used with Dymo 450 LaberWriter printers. Self-link: https://goo.gl/QCqrOj

This gist consist of tex templates for making barcodes using \psbarcode command using pst-barcode package: https://www.ctan.org/pkg/pst-barcode?lang=en .

Scripts and templates are tailored for use with label printer. I use Dymo 450 LabelWriter under Linux systems (Arch, Ubuntu, Raspibian) without hassle.

However it's easy to modify templates below to work with A4 sheets of label stickers for oridinary ink printers using labels - here is example: http://tex.stackexchange.com/a/289151/7128 .

  • standalone_code128_special_chars.tex - base template
  • standalone_code128_special_chars.sh - base for crafting bash script. It outputs same tex as standalone_code128_special_chars.tex
  • standalone_code128_gen_latex.sh - more generic generator. You can modify output by providing between 0 and 4 optional parameters.
  • gen_barcode.sh - most comprehensive script. It's standalone_code128_gen_latex.sh extended by options : preview, save, print, with ability to output both pdf and png files.

Requirements:

  • program pdflatex and appropriate packages. You may consider installing tex-live to have complete versatile environment and freedom of choosing packages if own modifications would happen.
  • for gen_barcode.sh:
    • program convert from imagemagick
    • some pdf viewer (like xpdf, mupdf,fbpdf)
    • for printing, lpr and probably cups

TODOs:

  • add GNU Barcode as alternative to pdflatex generator for simple barcodes. (pdflatex is mostly useful if you customized based on those templates to make custom layouts).
    • eventually consiser generation with GNU Barcode and inclusion into templates (ala includepdf or sth)
  • for pdflatex try to avoid -shell-escape:
#!/bin/bash
cmd="$1"
shift
case "$cmd" in
preview)
pdfviewer="$1"
shift
;;
save)
if [ -z "$1" ]; then
echo 'Error: please specify output directory or file';
exit 1;
fi
output="$1"
shift
;;
print|printpdf|printpng)
if [ -z "$1" ]; then
echo 'Error: please specify printer (check lpstat -v) or use "+" as printername to select one.';
exit 1;
fi
printer="$1"
if [ "$printer" == '+' ]; then
select printer in $(lpstat -a | cut -f 1 -d ' '); do break; done
fi
shift
;;
cattex)
;;
*)
cat<<ENDHELP
Usage:
$0 preview pdfviewer barcode_options...
$0 save outputdirectory|outputfile barcode_options... # detects extension
$0 print printername barcode_options...
$0 print + barcode_options... # use + instad of printername to select printer from menu
$0 cattex barcode_options... #this one outputs generated tex
barcode_options: 'Barcode Data' [psbarcode_options [barcodetype [document_options]]]
* "Barcode Data" - string with data to encode
* "psbarcode_options" - for defaults can be empty string '', for none space ' '. Look for custom options at http://www.ctan.org/pkg/pst-barcode depending on barcode. For example for code128 'includecheck includetext' are typical, for 'qrcode' can be for example 'eclevel=L width=1.15 height=1.15'
* "barcodetype" - few examples: code128, ean13, datamatrix, qrcode, interleaved2of5,... more in http://www.ctan.org/pkg/pst-barcode
* "document_options" - of documentclass
* http://ctan.org/pkg/standalone . Example usefull 'border={left bottom right top}' or sometimes 'preview' helps.
Example using all barcode_options:
$0 save . 'https://goo.gl/QCqrOj' 'includetext' qrcode 'border={10 20 30 40}'
Example omiting "psbarcode_options" by supplying them sapce, but
specifying barcodetype:
$0 save . 'DataMatrixExample' '' 'datamatrix'
ENDHELP
exit 0
;;
esac
data="${1:-Example}"
params="${2:-includecheck includetext}"
barcodetype="${3:-code128}"
standalone_opts="${4:-border={4pt 0pt 4pt 0pt\} %}" # % border={ left bottom right top }
tmpdir="$(mktemp -d --suffix=gen_barcode)"
function clean_up {
# Perform program exit housekeeping
rm "$tmpdir"/*
rmdir "$tmpdir"
exit
}
trap clean_up SIGHUP SIGINT SIGQUIT SIGTERM SIGKILL
data="$( echo "${data}" | sed 's:\\:\\\\:g;s:#:\\#:g;s:\$:\\$:g;s:%:\\%:g;s:{:\\{:g;s:}:\\}:g' )"
bname=barcode_"$(echo "${data}" | tr -c -d '[:alnum:]' )"_"$(echo "$barcodetype" | tr -c -d '[:alnum:]' )"_"$(date --iso-8601=seconds)"
cat >"$tmpdir"/"$bname".tex <<ENDTEX
\documentclass[%
${standalone_opts}
]{standalone} % http://ctan.org/pkg/standalone
\usepackage{pst-barcode} % http://www.ctan.org/pkg/pst-barcode
\usepackage{auto-pst-pdf} % pdflatex require -shell-escape option!!!
% Usage: pdflatex -shell-escape standalone_code128_special_chars.tex
\begin{document}
\begin{pspicture}%{44.5mm,17.5mm}
\psbarcode{\detokenize{${data}}}{${params}}{${barcodetype}}
\end{pspicture}
\end{document}
ENDTEX
if [ "$cmd" == "cattex" ]; then
cat "$tmpdir"/"$bname".tex
else
# pushd+popd because `-output-directory` did not play well
# with /psbarcode function.
pushd .
cd "$tmpdir"
pdflatex -shell-escape "$bname".tex
popd
fi
# When being pedantic and running on strong computer you might
# consider 600x600 resolution. As pdf->png convertion is it's 4 timers
# faster with 300x300 resolution (what matters in case I run this
# script on ARM devices) it's absolutetly enought from my practice.
# However if you are pedantic and have time/memory resources, go ahead
# and increase :).
function pdf2png(){
#/usr/bin/time convert -density 300x300 -background white -alpha remove -flatten -alpha off "$@"
density=300
convert -density "$density"x"$density" -background white -alpha remove -flatten -alpha off "$1" "$2"
# try to determine if accidentally it is not too small.
# It sometimes happens when used play with options and for example
# specify type `datamatrix` with small amount of data and does not
# specify dimensions.
# If it's too small, let's try to increase resolution.
imgwidth="$(identify "$2" | sed 's:.*PNG \([0-9]*\)x.*:\1:g')"
imgheight="$(identify "$2" | sed 's:.*PNG [0-9]*x\([0-9]*\).*:\1:g')"
while [ "$imgwidth" -lt 800 -a "$imgheight" -lt 800 ]; do
(( density *= 2 )) # double resolution until dimensions are below 800px
convert -density "$density"x"$density" -background white -alpha remove -flatten -alpha off "$1" "$2"
imgwidth="$(identify "$2" | sed 's:.*PNG \([0-9]*\)x.*:\1:g')"
imgheight="$(identify "$2" | sed 's:.*PNG [0-9]*x\([0-9]*\).*:\1:g')"
done
}
case "$cmd" in
preview)
$pdfviewer "$tmpdir"/"$bname".pdf
;;
save)
if [ -d "$output" ]; then
pdf2png "$tmpdir"/"$bname".{pdf,png}
cp -v "$tmpdir"/"$bname".{pdf,png,tex} "$output"
elif [[ $output =~ \.pdf ]]; then
cp -v "$tmpdir"/"$bname".pdf "$output"
elif [[ $output =~ \.png ]]; then
pdf2png "$tmpdir"/"$bname".{pdf,png}
cp -v "$tmpdir"/"$bname".png "$output"
else
echo 'Error: output was not directory, not filename with pdf or png extension'
exit 1
fi
;;
print|printpdf|printpng)
# Printing of this type of labels *usually* works better with .png on Dymo 450 LabelWriter to me
if [ "$cmd" != "printpdf" ]; then
pdf2png "$tmpdir"/"$bname".{pdf,png}
printfile="$tmpdir"/"$bname".png
else
printfile="$tmpdir"/"$bname".pdf
fi
#display "$tmpdir"/"$bname".png
# When Dymo 450 LabelWriter is shared via network (ipp/ipps) then
# printing only works with `-o raw` option.
# Let's determine if we deal with locally connected dymo via
# USB - by checking if lpstat -v $printer contains
# "usb://DYMO/" substring. In case of match let's assume that
# it's locally connected printer and omit `-o raw` parameter,
# otherwise use it by default.
printer_dev_spec="$(lpstat -v "$printer")"
if [[ "$printer_dev_spec" =~ 'usb://DYMO/' ]]; then
set -x
lpr -P "$printer" -o scaling=100 "$printfile"
set +x
else
set -x
lpr -P "$printer" -o raw -o scaling=100 "$printfile"
set +x
fi
;;
esac
clean_up
#!/bin/bash
#usage: bash ./standalone_code128_gen_latex.sh [Data [params [barcodetype [standalone_opts]]]]
# All params example: ./standalone_code128_gen_latex.sh 'https://goo.gl/QCqrOj' 'includetext' qrcode 'border={10 20 30 40}'> t.tex && pdflatex -shell-escape t.tex
# Special characters example: ./standalone_code128_gen_latex.sh 'Special chars: _x^2=+!@#$%^&*()-_\|'"'"'";:/?<>[]{}`~'
data="${1:-Example}"
params="${2:-includecheck includetext}"
barcodetype="${3:-code128}"
standalone_opts="${4:-border={2pt 0pt 2pt 0pt\} %}" # % border={ left bottom right top }
data="$( echo "${data}" | sed 's:\\:\\\\:g;s:#:\\#:g;s:\$:\\$:g;s:%:\\%:g;s:{:\\{:g;s:}:\\}:g')"
cat <<ENDTEX
\documentclass[%
${standalone_opts}
]{standalone} % http://ctan.org/pkg/standalone
\usepackage{pst-barcode} % http://www.ctan.org/pkg/pst-barcode
\usepackage{auto-pst-pdf} % pdflatex require -shell-escape option!!!
% Usage: pdflatex -shell-escape standalone_code128_special_chars.tex
\begin{document}
\begin{pspicture}%{44.5mm,17.5mm}
\psbarcode{\detokenize{${data}}}{${params}}{${barcodetype}}
\end{pspicture}
\end{document}
ENDTEX
#!/bin/bash
cat <<ENDTEX
\documentclass[% indead of "border=4" :
border={2pt 0pt 2pt 0pt} % left bottom right top
]{standalone} % http://ctan.org/pkg/standalone
\usepackage{pst-barcode} % http://www.ctan.org/pkg/pst-barcode
\usepackage{auto-pst-pdf} % pdflatex require -shell-escape option!!!
% Usage: pdflatex -shell-escape standalone_code128_special_chars.tex
\begin{document}
\begin{pspicture}%{44.5mm,17.5mm}
\psbarcode{\detokenize{Special_x^2=+!@\#\$\%^&*()-_\\|'";:/?,.<>[]\\{\\}\`~}}{includecheck includetext}{code128}
\end{pspicture}
\end{document}
ENDTEX
\documentclass[% indead of "border=4" :
border={2pt 0pt 2pt 0pt} % left bottom right top
]{standalone} % http://ctan.org/pkg/standalone
\usepackage{pst-barcode}
\usepackage{auto-pst-pdf} % pdflatex require -shell-escape option!!!
% Usage: pdflatex -shell-escape standalone_code128_special_chars.tex
\begin{document}
\begin{pspicture}%{44.5mm,17.5mm}
\psbarcode{\detokenize{Special_x^2=+!@\#\$\%^&*()-_\\|'";:/?,.<>[]\{\}`~}}{includecheck includetext}{code128}
\end{pspicture}
\end{document}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment