#!/usr/bin/perl use strict; use warnings; use GD; use Getopt::Long qw/:config auto_help gnu_getopt bundling/; use Data::Dumper; use PTouch qw/pixels/; use GdUtil qw/new_image/; my ($out,$tapewidth); my $cut = 0; my $count = 1; my $mirror = 0; my $printername = "ptouch"; my $center = 64; GetOptions( "P=s" => \$printername, "w=f" => \$tapewidth, c => \$cut, "n=n" => \$count, "o=s" => \$out, m => \$mirror, "c=n" => \$center ) or die "invalid options"; defined $tapewidth or die "You must specify a width with -w"; # returns true if pixel is black, zero if it is white or undef if out of bounds. sub checkPixel { my ($img,$x,$y) = @_; my ($w,$h) = $img->getBounds(); return undef if $x < 0 || $x >= $w || $y < 0 || $y >= $h; my ($r,$g,$b) = $img->rgb($img->getPixel($x,$y)); return $r + $g + $b > 127*3 ? 0 : 1; } sub pprint { my $out = ''; while (@_) { my $img = shift @_; my ($w,$h) = $img->getBounds(); my $y0 = $center - $h/2; $out .= 'ZZZZ'; for my $x (0..$w-1) { my @bytes; for my $x (0..15) { push @bytes, 0; } for my $y (0..127) { #my $set = $y >= $center-pixels($tapewidth)/2 && $y < $center+pixels($tapewidth)/2; my $set = $y >= $center-$h/2 && $y < $center+$h/2; $set = 0 unless checkPixel($img, $x, $y - $y0); if ($set) { my $bit = 2** (7-($y % 8)); $bytes[int($y / 8)] |= $bit; } } # Chop off the bytes that are zero. pop @bytes while @bytes and !$bytes[@bytes-1]; if (!@bytes) { $out .= 'Z'; } else { my $data = join '', map {chr} @bytes; $out .= 'G'.chr(@bytes).chr(0).$data; } } if (@_) { $out .= chr(0x0C); # There are more pages to print, don't discharge. } else { $out .= chr(0x1A); # This is the last page, discharge. } } return $out; } sub initialize { my $output=chr(0x1B).'@'; $output .= chr(0x1B).'iS'; $output .= chr(0x1B).'iR'.chr(0x01); my $mode = $cut ? 64 : 0 | $mirror ? 128 : 0; $output .= chr(0x1B).'iM'.chr($mode); # Set mode return $output; } # create calibration image my ($cgd,$fg) = new_image(8*3,pixels($tapewidth)); for my $y ( 0 .. pixels($tapewidth) -1 ) { for my $x ( 0 .. 7) { $cgd->setPixel(3*$x,$y,$fg) if $y & (1 << $x); $cgd->setPixel(3*$x+1,$y,$fg) if $y & (1 << $x); $cgd->setPixel(3*$x+2,$y,$fg) if $y & (1 << $x); } } my @gds = map { GD::Image->newFromPng($_) } @ARGV; my $rawdata=pprint($cgd, (@gds) x $count); if (defined $out) { open PRINT, ">", $out or die "$!: $out"; } else { open PRINT, "| lpr -l -P$printername" or die "$!: | lpr -P$printername"; } binmode PRINT; print PRINT initialize(); print PRINT $rawdata; close PRINT; __END__ =head1 SYNOPSIS Options: --help brief help message -P printer select printer -w n specify tape width in mm -c cut tape between items printed -n count print count copies of -o outfile output to file instead of printer -m mirror the output