Skip to content

Instantly share code, notes, and snippets.

@prurigro
Last active August 29, 2015 14:13
Show Gist options
  • Save prurigro/ee68ecdb6e34aa295bc7 to your computer and use it in GitHub Desktop.
Save prurigro/ee68ecdb6e34aa295bc7 to your computer and use it in GitHub Desktop.
A zbar wrapper utility to read barcodes from various sources
#!/usr/bin/env bash
#
# CodeGet: A zbar wrapper utility to read barcodes from various sources
#
# Version: 1.4.8
#
# Written by Kevin MacMartin and released under the MIT license
#
# Requirements:
# base64 | converts to and from base64 encoding
# file | detect information about files
# fswebcam | grabs images from the webcam
# scrot | grabs screenshots from the desktop
# xclip | saves decoded text to the clipboard
# zbar (zbarimg) | decodes text from barcodes
#
# Store /dev/stdin in $stdin if any input is given
[[ $(file /dev/fd/0) =~ pipe:\[[0-9]*\]$ ]] \
&& stdin=$(base64 /dev/stdin)
# Variables
script_name="${0//*\/}"
temp_file="/tmp/${script_name}.tmp.jpeg"
zbar_args='--raw'
dependencies=('base64' 'file' 'fswebcam' 'scrot' 'xclip' 'zbarimg')
# Colours
[[ -t 1 ]] && {
c_d=$'\e[1;30m' # GREY
c_r=$'\e[1;31m' # RED
c_g=$'\e[1;32m' # GREEN
c_y=$'\e[1;33m' # YELLOW
c_b=$'\e[1;34m' # BLUE
c_m=$'\e[1;35m' # VIOLET
c_t=$'\e[1;36m' # TEAL
c_w=$'\e[1;37m' # WHITE
c_c=$'\e[0m' # DISABLES COLOUR
}
# Function: display help and exit with a status of $1
function help() {
printf '\n%s\n\n' "${c_m}CodeGet$c_c: Scan visible zbar-compatible barcodes from the screen"
printf '%s\n' "${c_b}USAGE$c_c"
printf ' %s %s %s\n\n' "$c_y$script_name" "$c_d[${c_b}OPTION$c_d]" "$c_d[${c_r}FILE$c_d]$c_c"
printf '%s\n' "${c_b}OPTIONS$c_c"
printf ' %-20s %s\n' "$c_w-c → $c_c" 'output to the clipboard instead of stdout'
printf ' %-20s %s\n' "$c_w-v → $c_c" 'include barcode metadata in the output'
printf ' %-20s %s\n' "$c_w-w → $c_c" 'use the webcam as an input source'
printf ' %-20s %s\n\n' "$c_w-h → $c_c" 'display this help and exit'
printf '%s\n' "${c_b}SOURCES$c_c"
printf ' %-18s %s\n' "${c_m}display$c_c" "the current ${c_m}display$c_c is scanned by default"
printf ' %-18s %s\n' "${c_m}file$c_c" "a ${c_m}file$c_c is scanned when provided as an argument"
printf ' %-18s %s\n' "${c_m}stdin$c_c" "an image file sent to ${c_m}stdin$c_c is used when provided"
printf ' %-18s %s\n\n' "${c_m}webcam$c_c" "the webcam is scanned when the $c_w-w$c_c flag is set"
exit "$1"
}
# Function: display $1 (and help if set by $2), then exit with an failed status
function error_exit() {
printf '\n%s %s\n' "${c_r}ERROR:$c_c" "$1" >&2
if [[ "$2" = 'help' ]]; then
help 1
else
printf '\n'
fi
exit 1
}
# Test for programs required by this script before running
declare -a missing_dependencies=()
for dep in "${dependencies[@]}"; do
type -P "$dep" >/dev/null \
|| missing_dependencies=( ${missing_dependencies[@]} "$dep" )
done
[[ -n "${missing_dependencies[*]}" ]] && {
error_exit "${c_w}missing dependencies ($(
for (( x=0; x < ${#missing_dependencies[@]}; x++ )); do
printf '%s' "$c_m${missing_dependencies[$x]}$c_c"
(( (( x + 1 )) < ${#missing_dependencies[@]} )) && printf '%s' ', '
done
)$c_w)$c_c"
}
# Unset variables that should be set by parsed arguments
unset clipboard input_source input_file zbar_verbose
# Read stdin into $stdin and set as the input source if it's an image
[[ -n "$stdin" && $(file - < <(base64 -d <<< "$stdin")) =~ image\ data ]] \
&& input_source=stdin
# Parse command-line arguments to set config variables to the values selected by the user
while (( "$#" )); do
case "$1" in
-c)
clipboard=1
;;
-w)
input_source=webcam
;;
-v)
zbar_verbose=1
;;
-h|--help)
help 0
;;
*)
[[ -f "$1" ]] \
|| error_exit "$1 is not a file or valid argument" 'help'
[[ -z "$input_source" ]] && {
input_source=file
input_file="$1"
}
;;
esac
shift
done
# Add the quiet flag if verbose hasn't been set
(( "$zbar_verbose" )) \
|| zbar_args+=' -q'
# Set the input source to display if one hasn't already been set
[[ -z "$input_source" ]] \
&& input_source=display
# Remove the old temporary image file if one exists
[[ -f "$temp_file" ]] \
&& rm "$temp_file"
# Set the number of tries attempts to make based on input type
if [[ "$input_source" = 'webcam' ]]; then
maxtries=8
else
maxtries=1
fi
# Attempt to decode input source barcodes until successful or reaching $maxtries
tries=0; while [[ -z "$code_text" ]]; do
# Exit the loop if $tries >= $maxtries, otherwise add one to $tries
(( tries >= maxtries )) && break
(( tries++ ))
# Create the temporary image file using the selected input source
case "$input_source" in
display)
# input_source: display
scrot "$temp_file"
;;
file)
# input_source: file
cp "$input_file" "$temp_file"
;;
stdin)
# input_source: stdin
base64 -d <<< "$stdin" > "$temp_file"
;;
webcam)
# input_source: webcam
fswebcam -q -r 1280x720 "$temp_file"
;;
esac
# Exit with an error if $temp_file doesn't exist
[[ -f "$temp_file" ]] \
|| error_exit "Failed to save $temp_file"
# Decode barcodes contained in the temporary image file
code_text="$(zbarimg $zbar_args "$temp_file")"
done
# Clean up the temporary image file
[[ -f "$temp_file" ]] \
&& rm "$temp_file"
# Send the decoded text to the clipboard or stdout
[[ -n "$code_text" ]] && {
if (( "$clipboard" )); then
printf '%s' "$code_text" | xclip -in -selection clipboard
else
printf '%s\n' "$code_text"
fi
}
# Exit successfully
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment