Archive-name: pdfqruuid-is
Submitted-by:
onei...@gmail.com
Last-modified: 2013-03-29 14:30:23.437032191+00:00
Copyright-Notice: Both the README and the code are under the
CC0 Public Domain Dedication.
README.pdfqruuid -*- Text -*-
Synopsis
$ pdfqruuid [--verbose] \
[--start-page=START | -j START] \
[--generate=GENERATE | -g GENERATE] \
[--in=PDF-INPUT | -i PDF-INPUT] \
[--out=PDF-OUTPUT | -o PDF-INPUT] \
[--] [UUID-INPUT...]
Description
This Perl script either creates a PDF file having an arbitrary
number of QR-encoded UUID labels (along with their respective
leading 50-bit groups encoded in zBase32), one per resulting
page, suitable for later $ pdftk ... multistamp (or
$ pdftk ... multibackground), or adds these labels to the
PDF-INPUT file specified by itself.
The resulting PDF is written to the file specified, or standard
output ("-") if none given.
The GENERATE first UUIDs are randomly-generated (if specified);
an arbitrary number of UUIDs is then read from the UUID-INPUT
files given, or (if neither those nor GENERATE are given) read
from standard input.
The input UUIDs may be encoded as either hexadecimal or zBase32
sequences, allowing for optional dashes ("-".) Thus, all the
following forms are equivalent:
3a6799aa-73c6-41b4-9273-fb242a76d6d5
3a6799aa73c641b49273fb242a76d6d5
4331jiqqgqoemjqq58jwn534ig
Optionally, START, if specified, designates the first input page
to add a UUID label to. The behavior of the --start=, -j
options is unspecified if neither --input= nor -i is given.
(Currently, they're simply ignored.)
Bugs
The code assumes ISO A4 page size.
It should be possible to specify the position, size, and the
colors of the labels generated, and to alter their layout (the
QR-coding parameters, the use of the zBase32 encoding, the
number of bits to encode in the text part of the label, etc.)
GNU standard --help and --version options should be implemented.
There should be an option to generate both an arbitrary number
of UUID labels per single page, /and/ to generate a single label
per arbitrary number of input pages. (To facilitate two-side
and n-up printing.)
Somehow, ZBar appears to assume ISO-8859-1 if the QR code being
read contains a non-UTF-8 octet sequence, and merrily transcodes
it into UTF-8. (And then, its Barcode::ZBar Perl interface
fails to convey that the resulting octet sequence is in UTF-8.)
Possible workarounds for Shell and Perl may be as follows:
$ zbarimg ... | iconv -f UTF-8 -t ISO-8859-1 > uuid.bin
my $reader
= Barcode::ZBar::Processor->new ();
my $image
= Barcode::ZBar::Image->new ();
## ... read image data...
$reader->process_image ($image);
## assuming a single symbol
my ($sym)
= $image->get_symbols ();
my $uuid
= Encode::decode_utf8 ($sym->get_data (), Encode::FB_CROAK ());
(It was discussed in a news:alt.barcodes thread, starting with
news:87ehfjm...@violet.siamics.net, posted 13 March 2013.
See also Debian Bug#703234.)
Check also the FIXME marks within the code.
README.pdfqruuid ends here
#!/usr/bin/perl
### w5m66bor6iuqnqg4qxchg7cehf.perl -*- Perl -*-
### Ivan Shmakov, 2013
## To the extent possible under law, the author(s) have dedicated all
## copyright and related and neighboring rights to this software to the
## public domain worldwide. This software is distributed without any
## warranty.
## You should have received a copy of the CC0 Public Domain Dedication
## along with this software. If not, see
## <
http://creativecommons.org/publicdomain/zero/1.0/>.
### Code:
use common::sense;
use English qw (-no_match_vars);
require Carp;
require Convert::zBase32;
require Data::Dump;
require GD;
require Getopt::Long;
require Imager::QRCode;
require PDF::API2;
require UUID;
sub uuid_string {
my ($uuid) = @_;
my $s;
UUID::unparse ($uuid, $s);
my $z
= Convert::zBase32::encode_zbase32 ($uuid);
return ("urn:uuid:" . $s . " [" . $z . "]");
}
my $qr_coder
= Imager::QRCode->new (qw (version 1 level L),
qw (mode 8-bit casesensitive 1));
sub add_page_uuid {
my ($pdf, $data, $font, $may_be_page) = @_;
my $page
= ($may_be_page // $pdf->page ());
$page->mediabox ("A4")
unless (defined ($may_be_page));
my $g
= $page->gfx ();
my $image
= $qr_coder->plot ($data);
## FIXME: or use "raw" file format?
my $im_data;
$image->write ("data" => \$im_data, qw (type png))
or die ();
my $gd
= GD::Image->new ($im_data)
or die ();
my $img
= $pdf->image_gd ($gd, qw (-lossless 1))
or die ();
## FIXME: too much data hardcoded (assumes A4)
my $mmul
= (72 / 25.4);
$g->scale (($mmul) x 2);
# $g->translate (105, -10 - 12.5 + 297);
$g->translate (105, +10);
$g->linewidth (.175);
# $g->translate (200, 500);
$g->move (0, 15);
$g->poly (-12.5, 0, +12.5, 0, +12.5, 12.5, -12.5, 12.5);
$g->close ();
$g->stroke ();
$g->image ($img, (-12.5 + .25), .25, (12) x 2);
# $t->font ($pdf->corefont (qw (Helvetica-Bold -encode latin1)), 33);
{
my $z
= Convert::zBase32::encode_zbase32 ($data)
or die ();
# my $wxx
# = $t->text (("XXX: " . $z));
my $x_a
= $g->textlabel (0, 8, $font, 10 / $mmul,
substr ($z, 0, 5),
qw (-color #000));
my $x_b
= $g->textlabel (0, 3, $font, 10 / $mmul,
substr ($z, 5, 5),
qw (-color #000));
# print STDERR (Data::Dump::dump ([ $x_a, $x_b ]), "\n");
}
## .
return (wantarray ()
? ($page, "gfx" => $g)
: $page);
}
Getopt::Long::Configure (qw (gnu_compat));
my ($in, $out)
= (undef, "-");
my ($gen, $start, $verbose_p)
= (undef, 1, 0);
my $parsable_p
= Getopt::Long::GetOptions ("g|generate=i" => \$gen,
"i|input=s" => \$in,
"j|start-page=i" => \$start,
"o|output=s" => \$out,
"v|verbose!" => \$verbose_p)
or die ("Cannot parse command line arguments");
die ("--generate= (-g) cannot be negative")
unless ($gen >= 0);
die ("--start-page= (-j) cannot be non-positive")
unless ($start > 0);
my $pdf
= (defined ($in)
? PDF::API2->open ($in)
: PDF::API2->new ());
print STDERR ($in, ": PDF file opened\n")
if ($verbose_p && defined ($in));
$pdf->mediabox ("A4");
my $font
= $pdf->corefont ("Courier");
my $page_no
= (defined ($in) ? $start : undef);
for (my $i = 0; $i < $gen; $i++) {
my $uuid;
UUID::generate ($uuid);
print STDERR ("Generated: ", uuid_string ($uuid), "\n")
if ($verbose_p);
add_page_uuid ($pdf, $uuid, $font,
(defined ($page_no)
? $pdf->openpage ($page_no++)
: undef));
}
# unless ($gen > 0 || 1 + $#ARGV > 0) {
# push (@ARGV, "-");
# }
# foreach my $f (@ARGV) {
# }
if (1 + $#ARGV > 0 || $gen < 1) {
while (<>) {
# print STDERR ("Read: ", Data::Dump::dump ($_), "\n");
chomp ();
tr/-//d;
my $uuid
= (/^[[:xdigit:]]{32}$/
? pack ("H*", $_)
: Convert::zBase32::decode_zbase32 ($_))
or die ("Cannot parse UUID: ",
Data::Dump::dump ($_));
print STDERR ("UUID: ", uuid_string ($uuid),
" (", Data::Dump::dump ($_), ")\n")
if ($verbose_p);
add_page_uuid ($pdf, $uuid, $font,
(defined ($page_no)
? $pdf->openpage ($page_no++)
: undef));
}
}
## FIXME: ->saveas () should allow for a filehandle argument
if ($out eq "-") {
my $o
= \*STDOUT;
binmode ($o);
print $o ($pdf->stringify ());
} else {
$pdf->saveas ($out);
}
print STDERR ($out eq "-"
? ("PDF file written to stdout\n")
: ($out, ": PDF file written\n"))
if ($verbose_p);
### Emacs trailer
## Local variables:
## coding: us-ascii
## fill-column: 72
## indent-tabs-mode: nil
## ispell-local-dictionary: "american"
## End:
### w5m66bor6iuqnqg4qxchg7cehf.perl ends here
--
FSF associate member #7257
http://hfday.org/