EOS
my $root = $canvas->get_root_item;
for my $i ( 0 .. $root->get_n_children - 1 ) {
my $group = $root->get_child($i);
my $bounds = $group->get_bounds;
my ( $x1, $y1, $x2, $y2 ) =
( $bounds->x1 + 1, $bounds->y1 + 1, $bounds->x2 - 1, $bounds->y2 - 1 );
# my $matrix = $group->get_transform; FIXME: use this as soon as Goo::Canvas 0.07 is in generally available
# my ( $x1, $y1 ) = ( $matrix->x0, $matrix->y0 );
# my ( $x2, $y2, $text );
my ($text);
for my $i ( 0 .. $group->get_n_children - 1 ) {
my $item = $group->get_child($i);
if ( $item->isa('Goo::Canvas::Rect') ) {
# ( $x2, $y2 ) = ( $x1 + $item->get('width'), $y1 + $item->get('height') );
}
elsif ( $item->isa('Goo::Canvas::Text') ) {
$text = $item->get('text');
}
$current_page->{hocr} .=
" $text\n"
if ( defined($x2) and defined($text) );
}
}
$current_page->{hocr} .= "
";
return;
}
# Save selected pages as PDF under given name.
sub save_PDF {
my ($filename) = @_;
# Compile list of pages
my @list_of_pages;
my @pagelist =
$slist->get_page_index( $SETTING{'Page range'}, \&error_callback );
if ( not @pagelist ) { return }
for (@pagelist) {
push @list_of_pages, $slist->{data}[$_][2];
}
# Compile options
my %options = (
compression => $SETTING{'pdf compression'},
downsample => $SETTING{downsample},
'downsample dpi' => $SETTING{'downsample dpi'},
quality => $SETTING{quality},
font => $SETTING{'pdf font'},
);
# Create the PDF
$logger->debug("Started saving $filename");
my ( $signal, $pid );
$pid = $slist->save_pdf(
path => $filename,
list_of_pages => \@list_of_pages,
metadata => get_pdf_metadata(),
options => \%options,
queued_callback => sub {
return update_tpbar(@_);
},
started_callback => sub {
my ( $thread, $process, $completed, $total ) = @_;
$signal = setup_tpbar( $thread, $process, $completed, $total, $pid );
return TRUE if ( defined $signal );
},
running_callback => sub {
return update_tpbar(@_);
},
finished_callback => sub {
my ( $new_page, $pending ) = @_;
$thbox->hide_all unless $pending;
$tcbutton->signal_handler_disconnect($signal) if ( defined $signal );
mark_pages(@pagelist);
system("xdg-open \"$filename\" &")
if ( defined( $SETTING{'view files toggle'} )
and $SETTING{'view files toggle'} );
$logger->debug("Finished saving $filename");
},
error_callback => \&error_callback
);
return;
}
# Set up quality spinbutton here so that it can be shown or hidden by callback
sub add_quality_spinbutton {
my ($vbox) = @_;
my $hbox = Gtk2::HBox->new;
$vbox->pack_start( $hbox, TRUE, TRUE, 0 );
my $label = Gtk2::Label->new( $d->get('JPEG Quality') );
$hbox->pack_start( $label, FALSE, FALSE, 0 );
my $spinbutton = Gtk2::SpinButton->new_with_range( 1, 100, 1 );
$spinbutton->set_value( $SETTING{'quality'} );
$hbox->pack_end( $spinbutton, FALSE, FALSE, 0 );
return ( $hbox, $spinbutton );
}
sub add_pdf_compression {
my ($vbox) = @_;
# Downsample options
my $hboxd = Gtk2::HBox->new;
$vbox->pack_start( $hboxd, FALSE, FALSE, 0 );
my $button = Gtk2::CheckButton->new( $d->get('Downsample to') );
$button->set_active(TRUE);
$hboxd->pack_start( $button, FALSE, FALSE, 0 );
my $spinbutton = Gtk2::SpinButton->new_with_range( 9, 2400, 1 );
$spinbutton->set_value( $SETTING{'downsample dpi'} );
my $label = Gtk2::Label->new( $d->get('PPI') );
$hboxd->pack_end( $label, FALSE, FALSE, 0 );
$hboxd->pack_end( $spinbutton, FALSE, FALSE, 0 );
$button->signal_connect(
toggled => sub {
if ( $button->get_active ) {
$spinbutton->set_sensitive(TRUE);
}
else {
$spinbutton->set_sensitive(FALSE);
}
}
);
$button->set_active( $SETTING{'downsample'} );
# Compression options
my @compression = (
[
'auto',
$d->get('Automatic'),
$d->get('Let gscan2pdf which type of compression to use.')
],
[
'lzw', $d->get('LZW'),
$d->get('Compress output with Lempel-Ziv & Welch encoding.')
],
[ 'zip', $d->get('Zip'), $d->get('Compress output with deflate encoding.') ],
[
'packbits', $d->get('Packbits'),
$d->get('Compress output with Packbits encoding.')
],
# g3 and 4 give an error message
# [ 'g3', $d->get('G3'), $d->get('Compress output with CCITT Group 3 encoding.') ],
# [ 'g4', $d->get('G4'), $d->get('Compress output with CCITT Group 4 encoding.') ],
[ 'png', $d->get('PNG'), $d->get('Compress output with PNG encoding.') ],
[ 'jpg', $d->get('JPEG'), $d->get('Compress output with JPEG encoding.') ],
[
'none', $d->get('None'),
$d->get('Use no compression algorithm on output.')
],
);
# Compression ComboBox
my $hbox = Gtk2::HBox->new;
$vbox->pack_start( $hbox, TRUE, TRUE, 0 );
$label = Gtk2::Label->new( $d->get('Compression') );
$hbox->pack_start( $label, FALSE, FALSE, 0 );
# Set up quality spinbutton here so that it can be shown or hidden by callback
my ( $hboxq, $spinbuttonq ) = add_quality_spinbutton($vbox);
my $combob = combobox_from_array(@compression);
$combob->signal_connect(
changed => sub {
if ( $compression[ $combob->get_active ][0] eq 'jpg' ) {
$hboxq->show_all;
}
else {
$hboxq->hide_all;
}
}
);
combobox_set_active( $combob, $SETTING{'pdf compression'}, @compression );
$hbox->pack_end( $combob, FALSE, FALSE, 0 );
return ( $button, $spinbutton, $combob, $hboxq, $spinbuttonq, @compression );
}
# Display page selector and on save a fileselector.
sub save_dialog {
# $SETTING{'Page range'} = 'selected' if $SETTING{'RMB'};
if ( defined $windowi ) {
$windowi->present;
return;
}
$windowi = Gscan2pdf::Dialog->new(
'transient-for' => $window,
title => $d->get('Save'),
'hide-on-delete' => TRUE,
border_width => $border_width
);
my $vbox = $windowi->get('vbox');
# Frame for page range
add_page_range($vbox);
# Image type ComboBox
my $hboxi = Gtk2::HBox->new;
$vbox->pack_start( $hboxi, TRUE, TRUE, 0 );
my $label = Gtk2::Label->new( $d->get('Image type') );
$hboxi->pack_start( $label, FALSE, FALSE, 0 );
my @type = (
[ 'pdf', $d->get('PDF'), $d->get('Portable Document Format') ],
[ 'gif', $d->get('GIF'), $d->get('CompuServe graphics interchange format') ],
[
'jpg', $d->get('JPEG'),
$d->get('Joint Photographic Experts Group JFIF format')
],
[ 'png', $d->get('PNG'), $d->get('Portable Network Graphics') ],
[ 'pnm', $d->get('PNM'), $d->get('Portable anymap') ],
[ 'ps', $d->get('PS'), $d->get('Postscript') ],
[ 'tif', $d->get('TIFF'), $d->get('Tagged Image File Format') ],
[ 'txt', $d->get('Text'), $d->get('Plain text') ],
[ 'session', $d->get('Session'), $d->get('gscan2pdf session file') ],
);
push @type, [ 'djvu', $d->get('DjVu'), $d->get('Deja Vu') ]
if $dependencies{djvu};
my @tiff_compression = (
[
'lzw', $d->get('LZW'),
$d->get('Compress output with Lempel-Ziv & Welch encoding.')
],
[ 'zip', $d->get('Zip'), $d->get('Compress output with deflate encoding.') ],
# jpeg rather than jpg needed here because tiffcp uses -c jpeg
[ 'jpeg', $d->get('JPEG'), $d->get('Compress output with JPEG encoding.') ],
[
'packbits', $d->get('Packbits'),
$d->get('Compress output with Packbits encoding.')
],
[
'g3', $d->get('G3'),
$d->get('Compress output with CCITT Group 3 encoding.')
],
[
'g4', $d->get('G4'),
$d->get('Compress output with CCITT Group 4 encoding.')
],
[
'none', $d->get('None'),
$d->get('Use no compression algorithm on output.')
],
);
# Compression ComboBox
my $hboxc = Gtk2::HBox->new;
$vbox->pack_start( $hboxc, FALSE, FALSE, 0 );
$label = Gtk2::Label->new( $d->get('Compression') );
$hboxc->pack_start( $label, FALSE, FALSE, 0 );
# Set up quality spinbutton here so that it can be shown or hidden by callback
my ( $hboxtq, $spinbuttontq ) = add_quality_spinbutton($vbox);
$label = Gtk2::Label->new( $d->get('tiff') );
$hboxtq->pack_start( $label, FALSE, FALSE, 0 );
# Fill compression ComboBox
my $combobtc = combobox_from_array(@tiff_compression);
$combobtc->signal_connect(
changed => sub {
if ( $tiff_compression[ $combobtc->get_active ][0] eq 'jpeg' ) {
$hboxtq->show_all;
}
else {
$hboxtq->hide_all;
$windowi->resize( 100, 100 ); # Doesn't matter that 200x200 is too small
}
}
);
combobox_set_active( $combobtc, $SETTING{'tiff compression'},
@tiff_compression );
$hboxc->pack_end( $combobtc, FALSE, FALSE, 0 );
# PDF options
my $vboxp = Gtk2::VBox->new;
$vbox->pack_start( $vboxp, FALSE, FALSE, 0 );
my ( $entrya, $entryt, $entrys, $entryk ) = add_pdf_metadata($vboxp);
# Compression options
my ( $buttond, $spinbuttond, $combob, $hboxpq, $spinbuttonpq,
@pdf_compression ) = add_pdf_compression($vboxp);
# Font for non-ASCII text
my $scwinf = Gtk2::ScrolledWindow->new;
$scwinf->set_policy( 'automatic', 'automatic' );
$vbox->pack_start( $scwinf, TRUE, TRUE, 0 );
my $hboxf = Gtk2::HBox->new;
$scwinf->add_with_viewport($hboxf);
$scwinf->get_child->set_shadow_type('none');
$label = Gtk2::Label->new( $d->get('Font for non-ASCII text') );
$hboxf->pack_start( $label, FALSE, FALSE, 0 );
my @fonts;
my ($stdout) = Gscan2pdf::Document::open_three('fc-list : family style file');
for ( split /\n/, $stdout ) {
if (/ttf:\ /x) {
my ( $file, $family, $style ) = split ':';
chomp $style;
$family =~ s/^\ //x;
$style =~ s/^style=//x;
$style =~ s/,.*$//x;
my $font = "$family $style";
push @fonts, [ $file, $font, $font ];
$SETTING{'pdf font'} = $file
if ( not defined( $SETTING{'pdf font'} )
and $font eq 'Times New Roman Regular' );
}
}
@fonts = sort { $a->[1] cmp $b->[1] } @fonts;
my $combof = combobox_from_array(@fonts);
combobox_set_active( $combof, $SETTING{'pdf font'}, @fonts );
$hboxf->pack_start( $combof, FALSE, FALSE, 0 );
# Fill image type ComboBox
my $combobi = combobox_from_array(@type);
$combobi->signal_connect(
changed => \&image_type_changed_callback,
[
\@type, $vboxp, $hboxf, \@pdf_compression,
$combob, $hboxpq, $hboxc, \@tiff_compression,
$combobtc, $hboxtq
]
);
combobox_set_active( $combobi, $SETTING{'image type'}, @type );
$hboxi->pack_end( $combobi, FALSE, FALSE, 0 );
# HBox for buttons
my $hboxb = Gtk2::HBox->new;
$vbox->pack_start( $hboxb, FALSE, TRUE, 0 );
# Save button
my $sbutton = Gtk2::Button->new_from_stock('gtk-save');
$hboxb->pack_start( $sbutton, TRUE, TRUE, 0 );
$sbutton->signal_connect(
clicked => \&save_button_clicked_callback,
[
\@type, $combobi, $buttond,
$spinbuttond, \@pdf_compression, $combob,
$spinbuttonpq, \@fonts, $combof,
$entrya, $entryt, $entrys,
$entryk, \@tiff_compression, $combobtc,
$spinbuttontq
]
);
# Cancel button
my $cbutton = Gtk2::Button->new_from_stock('gtk-cancel');
$hboxb->pack_end( $cbutton, FALSE, FALSE, 0 );
$cbutton->signal_connect( clicked => sub { $windowi->hide; } );
$windowi->show_all;
$hboxpq->hide_all if ( $pdf_compression[ $combob->get_active ][0] ne 'jpg' );
$hboxtq->hide_all
if (
$type[ $combobi->get_active ][0] ne 'jpg'
or ( $type[ $combobi->get_active ][0] eq 'tif'
and $tiff_compression[ $combobtc->get_active ][0] ne 'jpg' )
);
$hboxc->hide_all
if ( $type[ $combobi->get_active ][0] ne 'tif'
and $type[ $combobi->get_active ][0] ne 'ps' );
if ( $type[ $combobi->get_active ][0] ne 'pdf' ) {
$vboxp->hide_all;
$hboxf->hide_all;
}
$windowi->resize( 100, 100 ); # Doesn't matter that 200x200 is too small
return;
}
sub image_type_changed_callback {
my ( $widget, $data ) = @_;
my (
$type, $vboxp, $hboxf, $pdf_compression,
$combob, $hboxpq, $hboxc, $tiff_compression,
$combobtc, $hboxtq
) = @$data;
if ( $type->[ $widget->get_active ][0] eq 'pdf' ) {
$vboxp->show_all;
$hboxf->show_all;
if ( $pdf_compression->[ $combob->get_active ][0] eq 'jpg' ) {
$hboxpq->show_all;
}
else {
$hboxpq->hide_all;
$windowi->resize( 100, 100 ); # Doesn't matter that 200x200 is too small
}
}
else {
$vboxp->hide_all;
$hboxf->hide_all;
$windowi->resize( 100, 100 ); # Doesn't matter that 200x200 is too small
}
if ($type->[ $widget->get_active ][0] eq 'tif'
or $type->[ $widget->get_active ][0] eq 'ps' )
{
$hboxc->show_all;
}
else {
$hboxc->hide_all;
$windowi->resize( 100, 100 ); # Doesn't matter that 200x200 is too small
}
if (
$type->[ $widget->get_active ][0] eq 'jpg'
or ( $type->[ $widget->get_active ][0] eq 'tif'
and $tiff_compression->[ $combobtc->get_active ][0] eq 'jpeg' )
)
{
$hboxtq->show_all;
}
else {
$hboxtq->hide_all;
$windowi->resize( 100, 100 ); # Doesn't matter that 200x200 is too small
}
return;
}
sub save_button_clicked_callback {
my ( $widget, $data ) = @_;
my (
$type, $combobi, $buttond, $spinbuttond,
$pdf_compression, $combob, $spinbuttonpq, $fonts,
$combof, $entrya, $entryt, $entrys,
$entryk, $tiff_compression, $combobtc, $spinbuttontq
) = @$data;
# dig out the image type, compression and quality
$SETTING{'image type'} = $type->[ $combobi->get_active ][0];
given ( $SETTING{'image type'} ) {
when ('pdf') {
# dig out the compression
$SETTING{'downsample'} = $buttond->get_active;
$SETTING{'downsample dpi'} = $spinbuttond->get_value;
$SETTING{'pdf compression'} = $pdf_compression->[ $combob->get_active ][0];
$SETTING{'quality'} = $spinbuttonpq->get_value;
$SETTING{'pdf font'} = $fonts->[ $combof->get_active ][0];
update_PDF_settings( $entrya, $entryt, $entrys, $entryk );
# cd back to cwd to save
chdir $SETTING{'cwd'};
# Set up file selector
my $file_chooser = Gtk2::FileChooserDialog->new(
$d->get('PDF filename'),
$windowi, 'save',
'gtk-cancel' => 'cancel',
'gtk-save' => 'ok'
);
my ( $dday, $dmonth, $dyear ) =
( localtime( time + $SETTING{'date offset'} * 24 * 60 * 60 ) )[ 3, 4, 5 ];
$dyear += 1900;
$dmonth = sprintf( "%02d", $dmonth + 1 );
$dday = sprintf( "%02d", $dday );
my ( $tday, $tmonth, $tyear ) = ( localtime(time) )[ 3, 4, 5 ];
$tyear += 1900;
$tmonth = sprintf( "%02d", $tmonth + 1 );
$tday = sprintf( "%02d", $tday );
my $filename = $SETTING{'default filename'};
$filename =~ s/%a/$SETTING{author}/g;
$filename =~ s/%t/$SETTING{title}/g;
$filename =~ s/%y/$dyear/g;
$filename =~ s/%Y/$tyear/g;
$filename =~ s/%m/$dmonth/g;
$filename =~ s/%M/$tmonth/g;
$filename =~ s/%d/$dday/g;
$filename =~ s/%D/$tday/g;
$file_chooser->set_current_name($filename);
$file_chooser->set_default_response('ok');
$file_chooser->set_current_folder( $SETTING{'cwd'} );
add_filter( $file_chooser, $d->get('PDF files'), 'pdf' );
$file_chooser->set_do_overwrite_confirmation(TRUE);
$file_chooser->signal_connect(
response => \&file_chooser_response_callback,
'pdf'
);
$file_chooser->show;
# cd back to tempdir
chdir $session;
}
when ('djvu') {
# cd back to cwd to save
chdir $SETTING{'cwd'};
# Set up file selector
my $file_chooser = Gtk2::FileChooserDialog->new(
$d->get('DjVu filename'),
$windowi, 'save',
'gtk-cancel' => 'cancel',
'gtk-save' => 'ok'
);
$file_chooser->set_default_response('ok');
$file_chooser->set_current_folder( $SETTING{'cwd'} );
add_filter( $file_chooser, $d->get('DjVu files'), 'djvu' );
$file_chooser->set_do_overwrite_confirmation(TRUE);
$file_chooser->signal_connect(
response => \&file_chooser_response_callback,
'djvu'
);
$file_chooser->show;
# cd back to tempdir
chdir $session;
}
when ('tif') {
$SETTING{'tiff compression'} =
$tiff_compression->[ $combobtc->get_active ][0];
$SETTING{'quality'} = $spinbuttontq->get_value;
# cd back to cwd to save
chdir $SETTING{'cwd'};
# Set up file selector
my $file_chooser = Gtk2::FileChooserDialog->new(
$d->get('TIFF filename'),
$windowi, 'save',
'gtk-cancel' => 'cancel',
'gtk-save' => 'ok'
);
$file_chooser->set_default_response('ok');
$file_chooser->set_current_folder( $SETTING{'cwd'} );
add_filter( $file_chooser, $d->get('Image files'), $SETTING{'image type'} );
$file_chooser->set_do_overwrite_confirmation(TRUE);
$file_chooser->signal_connect(
response => \&file_chooser_response_callback,
'tif'
);
$file_chooser->show;
# cd back to tempdir
chdir $session;
}
when ('txt') {
# cd back to cwd to save
chdir $SETTING{'cwd'};
# Set up file selector
my $file_chooser = Gtk2::FileChooserDialog->new(
$d->get('Text filename'),
$windowi, 'save',
'gtk-cancel' => 'cancel',
'gtk-save' => 'ok'
);
$file_chooser->set_default_response('ok');
$file_chooser->set_current_folder( $SETTING{'cwd'} );
$file_chooser->set_do_overwrite_confirmation(TRUE);
add_filter( $file_chooser, $d->get('Text files'), 'txt' );
$file_chooser->signal_connect(
response => \&file_chooser_response_callback,
'txt'
);
$file_chooser->show;
# cd back to tempdir
chdir $session;
}
when ('ps') {
$SETTING{'tiff compression'} =
$tiff_compression->[ $combobtc->get_active ][0];
$SETTING{'quality'} = $spinbuttontq->get_value;
# cd back to cwd to save
chdir $SETTING{'cwd'};
# Set up file selector
my $file_chooser = Gtk2::FileChooserDialog->new(
$d->get('PS filename'),
$windowi, 'save',
'gtk-cancel' => 'cancel',
'gtk-save' => 'ok'
);
$file_chooser->set_default_response('ok');
$file_chooser->set_current_folder( $SETTING{'cwd'} );
add_filter( $file_chooser, $d->get('Postscript files'), 'ps' );
$file_chooser->set_do_overwrite_confirmation(TRUE);
$file_chooser->signal_connect(
response => \&file_chooser_response_callback,
'ps'
);
$file_chooser->show;
# cd back to tempdir
chdir $session;
}
when ('session') {
# cd back to cwd to save
chdir $SETTING{'cwd'};
# Set up file selector
my $file_chooser = Gtk2::FileChooserDialog->new(
$d->get('gscan2pdf session filename'),
$windowi, 'save',
'gtk-cancel' => 'cancel',
'gtk-save' => 'ok'
);
$file_chooser->set_default_response('ok');
$file_chooser->set_current_folder( $SETTING{'cwd'} );
add_filter( $file_chooser, $d->get('gscan2pdf session files'), 'gs2p' );
$file_chooser->set_do_overwrite_confirmation(TRUE);
$file_chooser->signal_connect(
response => \&file_chooser_response_callback,
'gs2p'
);
$file_chooser->show;
# cd back to tempdir
chdir $session;
}
default {
save_image();
}
}
return;
}
sub file_chooser_response_callback {
my ( $dialog, $response, $type ) = @_;
$logger->debug("PDF save filename dialog returned $response");
if ( $response eq 'ok' ) {
my $filename = $dialog->get_filename;
if ( $filename !~ /\.$type$/ix ) {
$filename = "$filename.$type";
if ( -f $filename ) {
# File exists; get the file chooser to ask the user to confirm.
$dialog->set_filename($filename);
# Give the name change time to take effect.
Glib::Idle->add( sub { $dialog->response('ok'); } );
return;
}
}
# Check that the file can be written
if ( not -w dirname($filename)
or ( -f $filename and not -w $filename ) )
{
show_message_dialog( $dialog, 'error', 'close',
sprintf( $d->get("File %s is read-only"), $filename ) );
return;
}
# Update cwd
$SETTING{'cwd'} = dirname($filename);
given ($type) {
when ('pdf') {
save_PDF($filename);
}
when ('djvu') {
save_djvu($filename);
}
when ('tif') {
save_TIFF($filename);
}
when ('txt') {
save_txt($filename);
}
when ('ps') {
my $tif = File::Temp->new( DIR => $session, SUFFIX => '.tif' );
save_TIFF( $tif->filename, $filename );
}
when ('gs2p') {
$slist->save_session($filename);
}
}
$windowi->hide if defined $windowi;
}
$dialog->destroy;
return;
}
sub file_exists {
my ( $file_chooser, $filename ) = @_;
if ( not -w dirname($filename) or ( -f $filename and not -w $filename ) ) {
show_message_dialog( $file_chooser, 'error', 'close',
sprintf( $d->get("File %s is read-only"), $filename ) );
return TRUE;
}
elsif ( -e $filename ) {
my $response =
show_message_dialog( $file_chooser, 'question', 'ok-cancel',
sprintf( $d->get("File %s exists.\nReally overwrite?"), $filename ) );
return TRUE if ( $response ne 'ok' );
}
return FALSE;
}
sub save_image {
# cd back to cwd to save
chdir $SETTING{'cwd'};
# Set up file selector
my $file_chooser = Gtk2::FileChooserDialog->new(
$d->get('Image filename'),
$windowi, 'save',
'gtk-cancel' => 'cancel',
'gtk-save' => 'ok'
);
$file_chooser->set_default_response('ok');
$file_chooser->set_current_folder( $SETTING{'cwd'} );
add_filter( $file_chooser, $d->get('Image files'),
'jpg', 'png', 'pnm', 'gif', 'tif', 'tiff', 'pdf', 'djvu', 'ps' );
if ( 'ok' eq $file_chooser->run ) {
my $filename = $file_chooser->get_filename;
# Update cwd
$SETTING{'cwd'} = dirname($filename);
# cd back to tempdir
chdir $session;
# Compile list of pages
my @list_of_pages;
my @pagelist =
$slist->get_page_index( $SETTING{'Page range'}, \&error_callback );
if ( not @pagelist ) { return }
for (@pagelist) {
push @list_of_pages, $slist->{data}[$_][2];
}
if ( @list_of_pages > 1 ) {
my $w = length( scalar @list_of_pages );
for ( my $i = 1 ; $i <= @list_of_pages ; $i++ ) {
my $current_filename = sprintf "${filename}_%0${w}d.$SETTING{'image type'}",
$i;
return if ( file_exists( $file_chooser, $current_filename ) );
}
$filename = "${filename}_%0${w}d.$SETTING{'image type'}";
}
else {
$filename = $filename . ".$SETTING{'image type'}"
if ( $filename !~ /\.$SETTING{'image type'}$/ix );
return if ( file_exists( $file_chooser, $filename ) );
}
# Create the image
$logger->debug("Started saving $filename");
my ( $signal, $pid );
$pid = $slist->save_image(
path => $filename,
list_of_pages => \@list_of_pages,
queued_callback => sub {
return update_tpbar(@_);
},
started_callback => sub {
my ( $thread, $process, $completed, $total ) = @_;
$signal = setup_tpbar( $thread, $process, $completed, $total, $pid );
return TRUE if ( defined $signal );
},
running_callback => sub {
return update_tpbar(@_);
},
finished_callback => sub {
my ( $new_page, $pending ) = @_;
$thbox->hide_all unless $pending;
$tcbutton->signal_handler_disconnect($signal) if ( defined $signal );
mark_pages(@pagelist);
system("xdg-open \"$filename\" &")
if ( defined( $SETTING{'view files toggle'} )
and $SETTING{'view files toggle'} );
$logger->debug("Finished saving $filename");
},
error_callback => \&error_callback
);
$windowi->hide if defined $windowi;
}
$file_chooser->destroy;
return;
}
sub save_TIFF {
my ( $filename, $ps ) = @_;
# Compile list of pages
my @list_of_pages;
my @pagelist =
$slist->get_page_index( $SETTING{'Page range'}, \&error_callback );
if ( not @pagelist ) { return }
for (@pagelist) {
push @list_of_pages, $slist->{data}[$_][2];
}
# Compile options
my %options = (
compression => $SETTING{'tiff compression'},
quality => $SETTING{quality},
);
my ( $signal, $pid );
$pid = $slist->save_tiff(
path => $filename,
list_of_pages => \@list_of_pages,
options => \%options,
ps => $ps,
queued_callback => sub {
return update_tpbar(@_);
},
started_callback => sub {
my ( $thread, $process, $completed, $total ) = @_;
$signal = setup_tpbar( $thread, $process, $completed, $total, $pid );
return TRUE if ( defined $signal );
},
running_callback => sub {
return update_tpbar(@_);
},
finished_callback => sub {
my ( $new_page, $pending ) = @_;
$thbox->hide_all unless $pending;
$tcbutton->signal_handler_disconnect($signal) if ( defined $signal );
mark_pages(@pagelist);
my $file = defined($ps) ? $ps : $filename;
system("xdg-open \"$filename\" &")
if ( defined( $SETTING{'view files toggle'} )
and $SETTING{'view files toggle'} );
$logger->debug("Finished saving $filename");
},
error_callback => \&error_callback
);
return;
}
sub save_djvu {
my ($filename) = @_;
# Compile list of pages
my @list_of_pages;
my @pagelist =
$slist->get_page_index( $SETTING{'Page range'}, \&error_callback );
if ( not @pagelist ) { return }
for (@pagelist) {
push @list_of_pages, $slist->{data}[$_][2];
}
# cd back to tempdir
chdir $session;
# Create the DjVu
$logger->debug("Started saving $filename");
my ( $signal, $pid );
$pid = $slist->save_djvu(
path => $filename,
list_of_pages => \@list_of_pages,
queued_callback => sub {
return update_tpbar(@_);
},
started_callback => sub {
my ( $thread, $process, $completed, $total ) = @_;
$signal = setup_tpbar( $thread, $process, $completed, $total, $pid );
return TRUE if ( defined $signal );
},
running_callback => sub {
return update_tpbar(@_);
},
finished_callback => sub {
my ( $new_page, $pending ) = @_;
$thbox->hide_all unless $pending;
$tcbutton->signal_handler_disconnect($signal) if ( defined $signal );
mark_pages(@pagelist);
system("xdg-open \"$filename\" &")
if ( defined( $SETTING{'view files toggle'} )
and $SETTING{'view files toggle'} );
$logger->debug("Finished saving $filename");
},
error_callback => \&error_callback
);
return;
}
sub save_txt {
my ($filename) = @_;
# Compile list of pages
my @list_of_pages;
my @pagelist =
$slist->get_page_index( $SETTING{'Page range'}, \&error_callback );
if ( not @pagelist ) { return }
for (@pagelist) {
push @list_of_pages, $slist->{data}[$_][2];
}
my ( $signal, $pid );
$pid = $slist->save_text(
path => $filename,
list_of_pages => \@list_of_pages,
queued_callback => sub {
return update_tpbar(@_);
},
started_callback => sub {
my ( $thread, $process, $completed, $total ) = @_;
$signal = setup_tpbar( $thread, $process, $completed, $total, $pid );
return TRUE if ( defined $signal );
},
running_callback => sub {
return update_tpbar(@_);
},
finished_callback => sub {
my ( $new_page, $pending ) = @_;
$thbox->hide_all unless $pending;
$tcbutton->signal_handler_disconnect($signal) if ( defined $signal );
mark_pages(@pagelist);
system("xdg-open \"$filename\" &")
if ( defined( $SETTING{'view files toggle'} )
and $SETTING{'view files toggle'} );
$logger->debug("Finished saving $filename");
},
error_callback => \&error_callback
);
return;
}
# Display page selector and email.
sub email {
if ( defined $windowe ) {
$windowe->present;
return;
}
# $SETTING{'Page range'} = 'selected' if $SETTING{'RMB'};
$windowe = Gscan2pdf::Dialog->new(
'transient-for' => $window,
title => $d->get('Email as PDF'),
'hide-on-delete' => TRUE,
border_width => $border_width
);
my $vbox = $windowe->get('vbox');
# PDF options
my ( $entrya, $entryt, $entrys, $entryk ) = add_pdf_metadata($vbox);
# Frame for page range
add_page_range($vbox);
# Compression options
my ( $buttond, $spinbuttond, $combob, $hboxq, $spinbuttonq, @compression ) =
add_pdf_compression($vbox);
# HBox for buttons
my $hboxb = Gtk2::HBox->new;
$vbox->pack_start( $hboxb, FALSE, TRUE, 0 );
# OK button
my $sbutton = Gtk2::Button->new_from_stock('gtk-ok');
$hboxb->pack_start( $sbutton, TRUE, TRUE, 0 );
$sbutton->signal_connect(
clicked => sub {
# Set options
update_PDF_settings( $entrya, $entryt, $entrys, $entryk );
# Compile list of pages
my @list_of_pages;
my @pagelist =
$slist->get_page_index( $SETTING{'Page range'}, \&error_callback );
if ( not @pagelist ) { return }
for (@pagelist) {
push @list_of_pages, $slist->{data}[$_][2];
}
# dig out the compression
$SETTING{'downsample'} = $buttond->get_active;
$SETTING{'downsample dpi'} = $spinbuttond->get_value;
$SETTING{'pdf compression'} = $compression[ $combob->get_active ][0];
$SETTING{'quality'} = $spinbuttonq->get_value;
# Compile options
my %options = (
compression => $SETTING{'pdf compression'},
downsample => $SETTING{downsample},
'downsample dpi' => $SETTING{'downsample dpi'},
quality => $SETTING{quality},
font => $SETTING{'pdf font'},
);
$pdf = File::Temp->new( DIR => $session, SUFFIX => '.pdf' );
# Check for thunderbird
my ($client);
if ( defined( $ENV{KDE_FULL_SESSION} ) and $ENV{KDE_FULL_SESSION} eq 'true' )
{
($client) = Gscan2pdf::Document::open_three(
"kreadconfig --file emaildefaults --group PROFILE_Default --key EmailClient| cut -d ' ' -f 1"
);
}
elsif (
(
defined( $ENV{GNOME_DESKTOP_SESSION_ID} )
and $ENV{GNOME_DESKTOP_SESSION_ID} ne ''
)
or ( defined( $ENV{XDG_CURRENT_DESKTOP} )
and $ENV{XDG_CURRENT_DESKTOP} eq 'XFCE' )
)
{
($client) = Gscan2pdf::Document::open_three(
"gconftool --get /desktop/gnome/url-handlers/mailto/command | cut -d ' ' -f 1"
);
}
my $mua_string;
if ( $client =~ /thunderbird/ ) {
$mua_string = "thunderbird -compose attachment=file://$pdf";
}
else {
$mua_string = "xdg-email --attach $pdf 'x\@y'";
}
# Create the PDF
my ( $signal, $pid );
$pid = $slist->save_pdf(
path => $pdf->filename,
list_of_pages => \@list_of_pages,
metadata => get_pdf_metadata(),
options => \%options,
queued_callback => sub {
return update_tpbar(@_);
},
started_callback => sub {
my ( $thread, $process, $completed, $total ) = @_;
$signal = setup_tpbar( $thread, $process, $completed, $total, $pid );
return TRUE if ( defined $signal );
},
running_callback => sub {
return update_tpbar(@_);
},
finished_callback => sub {
my ( $new_page, $pending ) = @_;
$thbox->hide_all unless $pending;
$tcbutton->signal_handler_disconnect($signal) if ( defined $signal );
mark_pages(@pagelist);
system("xdg-open \"$pdf\" &")
if ( defined( $SETTING{'view files toggle'} )
and $SETTING{'view files toggle'} );
$logger->info($mua_string);
show_message_dialog( $window, 'error', 'close',
$d->get('Error creating email') )
if ( system($mua_string) );
},
error_callback => \&error_callback
);
$windowe->hide;
}
);
# Cancel button
my $cbutton = Gtk2::Button->new_from_stock('gtk-cancel');
$hboxb->pack_end( $cbutton, FALSE, FALSE, 0 );
$cbutton->signal_connect( clicked => sub { $windowe->hide; } );
$windowe->show_all;
$hboxq->hide_all if ( $compression[ $combob->get_active ][0] ne 'jpg' );
return;
}
# Scan
sub scan_dialog {
my ($hidden) = @_;
if ( defined $windows ) {
$windows->show_all;
return;
}
# If device not set by config and there is a default device, then set it
$SETTING{device} = $ENV{'SANE_DEFAULT_DEVICE'}
if ( not defined( $SETTING{device} )
and defined( $ENV{'SANE_DEFAULT_DEVICE'} ) );
$SETTING{'pages to scan'} = 0 if ( $SETTING{'pages to scan'} eq 'all' );
# scan pop-up window
my %options = (
'transient-for' => $window,
title => $d->get('Scan Document'),
border_width => $border_width,
logger => $logger,
dir => $session,
'hide-on-delete' => TRUE,
'num-pages' => $SETTING{'pages to scan'},
'page-number-start' => $#{ $slist->{data} } > -1
? $slist->{data}[ $#{ $slist->{data} } ][0] + 1
: 1,
);
if ( $SETTING{frontend} eq 'libsane-perl' ) {
$windows = Gscan2pdf::Dialog::Scan::Sane->new(%options);
}
else {
$windows = Gscan2pdf::Dialog::Scan::CLI->new(
%options,
prefix => $SETTING{'scan prefix'},
frontend => $SETTING{'frontend'},
'visible-scan-options' => $SETTING{'visible-scan-options'},
'reload-triggers' => $SETTING{'scan-reload-triggers'},
'cache-options' => $SETTING{'cache options'},
'options-cache' => $SETTING{cache},
);
$windows->signal_connect(
'changed-options-cache' => sub {
my ( $widget, $cache ) = @_;
$SETTING{cache} = $cache;
}
);
}
# Can't set the device when creating the window,
# as the list does not exist then
$windows->signal_connect(
'changed-device-list' => \&changed_device_list_callback );
# Update default device
$windows->signal_connect( 'changed-device' => \&changed_device_callback );
# Set default
$windows->signal_connect(
'changed-num-pages' => sub {
( my $widget, $SETTING{'pages to scan'} ) = @_;
# Check that there is room in the list for the number of pages
update_number();
}
);
$windows->signal_connect(
'changed-page-number-start' => sub {
my ( $widget, $value ) = @_;
$windows->set( 'max-pages',
$slist->pages_possible( $value, $windows->get('page-number-increment') ) );
}
);
$windows->signal_connect(
'changed-page-number-increment' => sub {
my ( $widget, $step ) = @_;
$windows->set( 'max-pages',
$slist->pages_possible( $windows->get('page-number-start'), $step ) );
}
);
$windows->signal_connect(
'changed-side-to-scan' => \&changed_side_to_scan_callback );
my $signal;
$windows->signal_connect(
'started-process' => sub {
my ( $widget, $message ) = @_;
$spbar->set_fraction(0);
$spbar->set_text($message);
$shbox->show_all;
$signal = $scbutton->signal_connect(
clicked => sub {
$windows->cancel_scan;
}
);
}
);
$windows->signal_connect( 'changed-progress' => \&changed_progress_callback );
$windows->signal_connect(
'finished-process' => sub {
my ( $widget, $process, $button_signal ) = @_;
$logger->info("signal 'finished-process' emitted with data: $process");
$scbutton->signal_handler_disconnect($button_signal)
if ( defined $button_signal );
$shbox->hide;
$widget->scan_options( $SETTING{device} )
if ( $SETTING{'cycle sane handle'} and $process eq 'scan_pages' );
}
);
$windows->signal_connect(
'process-error' => sub {
my ( $widget, $process, $msg ) = @_;
$logger->info("signal 'process-error' emitted with data: $process $msg");
$scbutton->signal_handler_disconnect($signal) if ( defined $signal );
$shbox->hide;
if ( $process =~ /^(?:get_devices|find_scan_options)$/x ) {
$widget->hide;
undef $widget;
show_message_dialog( $window, 'error', 'close', $msg );
}
else {
show_message_dialog( $widget, 'error', 'close', $d_sane->get($msg) );
}
}
);
$windows->signal_connect(
'changed-scan-option' => \&changed_scan_option_callback );
# Profiles
for my $profile ( keys %{ $SETTING{profile} } ) {
$windows->add_profile( $profile, $SETTING{profile}{$profile} );
}
$windows->signal_connect(
'changed-profile' => sub {
my ( $widget, $profile ) = @_;
$SETTING{'default profile'} = $profile;
}
);
$windows->signal_connect(
'added-profile' => sub {
my ( $widget, $name, $profile ) = @_;
$SETTING{profile}{$name} = $profile;
}
);
$windows->signal_connect(
'removed-profile' => sub {
my ( $widget, $profile ) = @_;
delete $SETTING{profile}{$profile};
}
);
# Update the default profile when the scan options change
$windows->signal_connect(
'changed-current-scan-options' => sub {
my ( $widget, $option_array ) = @_;
$SETTING{'default-scan-options'} = $option_array;
}
);
# Can't set the paper or profile until the options have been loaded
$windows->signal_connect(
'reloaded-scan-options' => \&reloaded_scan_options_callback );
$windows->signal_connect(
'changed-paper-formats' => sub {
my ( $widget, $formats ) = @_;
$SETTING{Paper} = $formats;
}
);
$windows->signal_connect(
'changed-paper' => sub {
my ( $widget, $paper ) = @_;
$SETTING{'Paper size'} = $paper;
}
);
$windows->signal_connect( 'new-scan' => \&new_scan_callback );
add_postprocessing_options($windows);
$windows->show_all unless $hidden;
if (@device_list) {
$windows->set( 'device-list', \@device_list );
}
else {
$windows->get_devices;
}
return;
}
sub changed_device_callback {
my ( $widget, $device ) = @_;
$logger->info("signal 'changed-device' emitted with data: '$device'");
$SETTING{device} = $device
if ( defined($device) and $device ne '' );
return;
}
sub changed_device_list_callback {
my ( $widget, $device_list ) = @_;
$logger->info(
"signal 'changed-device-list' emitted with data: " . Dumper($device_list) );
if ( defined $device_list ) {
# Only set default device if it hasn't been specified on the command line
# and it is in the the device list
if ( defined( $SETTING{device} ) and not @device_list ) {
for (@$device_list) {
if ( $SETTING{device} eq $_->{name} ) {
$windows->set( 'device', $SETTING{device} );
return;
}
}
}
$windows->set( 'device', $device_list->[0]{name} );
}
return;
}
sub changed_side_to_scan_callback {
my ( $widget, $side ) = @_;
if ( $#{ $slist->{data} } > -1 ) {
$windows->set( 'page-number-start',
$slist->{data}[ $#{ $slist->{data} } ][0] + 1 );
}
else {
$windows->set( 'page-number-start', 1 );
}
return;
}
sub reloaded_scan_options_callback {
$windows->set( 'paper-formats', $SETTING{Paper} );
$windows->set( 'paper', $SETTING{'Paper size'} )
if ( defined $SETTING{'Paper size'} );
my @profiles = keys %{ $SETTING{profile} };
if ( defined $SETTING{'default profile'} ) {
$windows->set( 'profile', $SETTING{'default profile'} );
}
elsif ( defined $SETTING{'default-scan-options'} ) {
$windows->set( 'current-scan-options', $SETTING{'default-scan-options'} );
}
elsif (@profiles) {
$windows->set( 'profile', $profiles[0] );
}
return;
}
sub changed_scan_option_callback {
my ( $widget, $option, $value ) = @_;
# Note resolution
$SETTING{resolution} = $value
if ( $option eq SANE_NAME_SCAN_RESOLUTION );
return;
}
sub changed_progress_callback {
my ( $widget, $progress, $message ) = @_;
if ( defined $progress ) {
$spbar->set_fraction($progress);
}
else {
$spbar->pulse;
}
$spbar->set_text($message) if ( defined $message );
return;
}
sub new_scan_callback {
my ( $widget, $n ) = @_;
# Update undo/redo buffers
take_snapshot();
# If the scan can't be loaded then blow the scanning dialog away and
# show an error
my $rotate = $n % 2 ? $SETTING{'rotate facing'} : $SETTING{'rotate reverse'};
if ( defined $test_image ) {
import_scan(
filename => $test_image,
page => $n,
delete => FALSE,
rotate => $rotate,
unpaper => $SETTING{'unpaper on scan'},
ocr => $SETTING{'OCR on scan'}
);
}
else {
my $options = $windows->get('available-scan-options');
my $opt = $options->by_name(SANE_NAME_SCAN_RESOLUTION);
$SETTING{resolution} =
( defined($opt) and defined( $opt->{val} ) )
? $opt->{val}
: $Gscan2pdf::Document::POINTS_PER_INCH;
$logger->info("Importing scan with resolution=$SETTING{resolution}");
import_scan(
filename => File::Spec->catdir( $session, "out$n.pnm" ),
page => $n,
resolution => $SETTING{resolution},
delete => TRUE,
rotate => $rotate,
unpaper => $SETTING{'unpaper on scan'},
ocr => $SETTING{'OCR on scan'}
);
}
return;
}
sub add_postprocessing_rotate {
my ($vbox) = @_;
my $hboxr = Gtk2::HBox->new;
$vbox->pack_start( $hboxr, FALSE, FALSE, 0 );
my $rbutton = Gtk2::CheckButton->new( $d->get('Rotate') );
$tooltips->set_tip( $rbutton, $d->get('Rotate image after scanning') );
$hboxr->pack_start( $rbutton, TRUE, TRUE, 0 );
my @side = (
[ 'both', $d->get('Both sides'), $d->get('Both sides.') ],
[ 'facing', $d->get('Facing side'), $d->get('Facing side.') ],
[ 'reverse', $d->get('Reverse side'), $d->get('Reverse side.') ],
);
my $comboboxs = combobox_from_array(@side);
$tooltips->set_tip( $comboboxs, $d->get('Select side to rotate') );
$hboxr->pack_start( $comboboxs, TRUE, TRUE, 0 );
my @rotate = (
[ 90, $d->get('90'), $d->get('Rotate image 90 degrees clockwise.') ],
[ 180, $d->get('180'), $d->get('Rotate image 180 degrees clockwise.') ],
[ 270, $d->get('270'), $d->get('Rotate image 90 degrees anticlockwise.') ],
);
my $comboboxr = combobox_from_array(@rotate);
$tooltips->set_tip( $comboboxr, $d->get('Select direction of rotation') );
$hboxr->pack_end( $comboboxr, TRUE, TRUE, 0 );
$hboxr = Gtk2::HBox->new;
$vbox->pack_start( $hboxr, FALSE, FALSE, 0 );
my $r2button = Gtk2::CheckButton->new( $d->get('Rotate') );
$tooltips->set_tip( $r2button, $d->get('Rotate image after scanning') );
$hboxr->pack_start( $r2button, TRUE, TRUE, 0 );
my @side2;
my $comboboxs2 = Gtk2::ComboBox->new_text;
$tooltips->set_tip( $comboboxs2, $d->get('Select side to rotate') );
$hboxr->pack_start( $comboboxs2, TRUE, TRUE, 0 );
my $comboboxr2 = combobox_from_array(@rotate);
$tooltips->set_tip( $comboboxr2, $d->get('Select direction of rotation') );
$hboxr->pack_end( $comboboxr2, TRUE, TRUE, 0 );
$rbutton->signal_connect(
toggled => sub {
if ( $rbutton->get_active ) {
$hboxr->set_sensitive(TRUE)
if ( $side[ $comboboxs->get_active ]->[0] ne 'both' );
}
else {
$hboxr->set_sensitive(FALSE);
}
}
);
$comboboxs->signal_connect(
changed => sub {
if ( $side[ $comboboxs->get_active ]->[0] eq 'both' ) {
$hboxr->set_sensitive(FALSE);
$r2button->set_active(FALSE);
}
else {
$hboxr->set_sensitive(TRUE) if ( $rbutton->get_active );
# Empty combobox
while ( $comboboxs2->get_active > -1 ) {
$comboboxs2->remove_text(0);
$comboboxs2->set_active(0);
}
@side2 = ();
foreach (@side) {
push @side2, $_
unless ( $_->[0] eq 'both'
or $_->[0] eq $side[ $comboboxs->get_active ]->[0] );
}
$comboboxs2->append_text( $side2[0]->[1] );
$comboboxs2->set_active(0);
}
}
);
# In case it isn't set elsewhere
combobox_set_active( $comboboxr2, 90, @rotate );
if ( $SETTING{'rotate facing'} or $SETTING{'rotate reverse'} ) {
$rbutton->set_active(TRUE);
}
if ( $SETTING{'rotate facing'} == $SETTING{'rotate reverse'} ) {
combobox_set_active( $comboboxs, 'both', @side );
combobox_set_active( $comboboxr, $SETTING{'rotate facing'}, @rotate );
}
elsif ( $SETTING{'rotate facing'} ) {
combobox_set_active( $comboboxs, 'facing', @side );
combobox_set_active( $comboboxr, $SETTING{'rotate facing'}, @rotate );
if ( $SETTING{'rotate reverse'} ) {
$r2button->set_active(TRUE);
combobox_set_active( $comboboxs2, 'reverse', @side2 );
combobox_set_active( $comboboxr2, $SETTING{'rotate reverse'}, @rotate );
}
}
else {
combobox_set_active( $comboboxs, 'reverse', @side );
combobox_set_active( $comboboxr, $SETTING{'rotate reverse'}, @rotate );
}
return (
\@rotate, \@side, \@side2, $rbutton, $r2button,
$comboboxs, $comboboxs2, $comboboxr, $comboboxr2
);
}
sub add_postprocessing_ocr {
my ($vbox) = @_;
my $hboxo = Gtk2::HBox->new;
$vbox->pack_start( $hboxo, FALSE, FALSE, 0 );
my $obutton = Gtk2::CheckButton->new( $d->get('OCR scanned pages') );
$tooltips->set_tip( $obutton, $d->get('OCR scanned pages') );
if ( not $dependencies{gocr}
and not $dependencies{tesseract}
and not $dependencies{ocropus}
and not $dependencies{cuneiform} )
{
$hboxo->set_sensitive(FALSE);
$obutton->set_active(FALSE);
}
elsif ( $SETTING{'OCR on scan'} ) {
$obutton->set_active(TRUE);
}
$hboxo->pack_start( $obutton, TRUE, TRUE, 0 );
my $comboboxe = combobox_from_array(@ocr_engine);
$tooltips->set_tip( $comboboxe, $d->get('Select OCR engine') );
$hboxo->pack_end( $comboboxe, TRUE, TRUE, 0 );
my ( $comboboxtl, $hboxtl, @tesslang, $comboboxcl, $hboxcl, @cflang );
if ( $dependencies{tesseract} ) {
( $hboxtl, $comboboxtl, @tesslang ) = add_tess_languages($vbox);
$comboboxe->signal_connect(
changed => sub {
if ($ocr_engine[ $comboboxe->get_active ]->[0] eq 'tesseract'
or $ocr_engine[ $comboboxe->get_active ]->[0] eq 'ocropus' )
{
$hboxtl->show_all;
}
else {
$hboxtl->hide_all;
}
}
);
if ( $dependencies{cuneiform} ) {
( $hboxcl, $comboboxcl, @cflang ) = add_cf_languages($vbox);
$comboboxe->signal_connect(
changed => sub {
if ( $ocr_engine[ $comboboxe->get_active ]->[0] eq 'cuneiform' ) {
$hboxcl->show_all;
}
else {
$hboxcl->hide_all;
}
}
);
}
$hboxtl->set_sensitive(FALSE) unless ( $obutton->get_active );
$obutton->signal_connect(
toggled => sub {
if ( $obutton->get_active ) {
$hboxtl->set_sensitive(TRUE);
}
else {
$hboxtl->set_sensitive(FALSE);
}
}
);
}
combobox_set_active( $comboboxe, $SETTING{'ocr engine'}, @ocr_engine );
return (
$obutton, $comboboxe, $hboxtl, $comboboxtl,
$hboxcl, $comboboxcl, \@tesslang, \@cflang
);
}
sub add_postprocessing_options {
my ($self) = @_;
my $vbox = $self->get('vbox');
# Frame for post-processing
my $framep = Gtk2::Frame->new( $d->get('Post-processing') );
$vbox->pack_start( $framep, FALSE, FALSE, 0 );
my $vboxp = Gtk2::VBox->new;
$vboxp->set_border_width($border_width);
$framep->add($vboxp);
# Rotate
my (
$rotate, $side, $side2, $rbutton, $r2button,
$comboboxs, $comboboxs2, $comboboxr, $comboboxr2
) = add_postprocessing_rotate($vboxp);
# CheckButton for unpaper
my $hboxu = Gtk2::HBox->new;
$vboxp->pack_start( $hboxu, FALSE, FALSE, 0 );
my $ubutton = Gtk2::CheckButton->new( $d->get('Clean up images') );
$tooltips->set_tip( $ubutton,
$d->get('Clean up scanned images with unpaper') );
$hboxu->pack_start( $ubutton, TRUE, TRUE, 0 );
if ( not $dependencies{unpaper} ) {
$ubutton->set_sensitive(FALSE);
$ubutton->set_active(FALSE);
}
elsif ( $SETTING{'unpaper on scan'} ) {
$ubutton->set_active(TRUE);
}
my $button = Gtk2::Button->new( $d->get('Options') );
$tooltips->set_tip( $button, $d->get('Set unpaper options') );
$hboxu->pack_end( $button, TRUE, TRUE, 0 );
$button->signal_connect(
clicked => sub {
my $windowuo = Gscan2pdf::Dialog->new(
'transient-for' => $window,
title => $d->get('unpaper options'),
border_width => $border_width
);
my $vbox1 = $windowuo->get('vbox');
$unpaper->add_options($vbox1);
# HBox for buttons
my $hboxb = Gtk2::HBox->new;
$vbox1->pack_start( $hboxb, FALSE, TRUE, 0 );
# OK button
my $sbutton = Gtk2::Button->new_from_stock('gtk-ok');
$hboxb->pack_start( $sbutton, TRUE, TRUE, 0 );
$sbutton->signal_connect(
clicked => sub {
# Update $SETTING
$SETTING{'unpaper options'} = $unpaper->get_options;
$windowuo->destroy;
}
);
# Cancel button
my $cbutton = Gtk2::Button->new_from_stock('gtk-cancel');
$hboxb->pack_end( $cbutton, FALSE, FALSE, 0 );
$cbutton->signal_connect( clicked => sub { $windowuo->destroy; } );
$windowuo->show_all;
}
);
my (
$obutton, $comboboxe, $hboxtl, $comboboxtl,
$hboxcl, $comboboxcl, $tesslang, $cflang
) = add_postprocessing_ocr($vboxp);
$self->signal_connect(
'clicked-scan-button' => sub {
$SETTING{'rotate facing'} = 0;
$SETTING{'rotate reverse'} = 0;
if ( $rbutton->get_active ) {
if ( $side->[ $comboboxs->get_active ][0] eq 'both' ) {
$SETTING{'rotate facing'} = $rotate->[ $comboboxr->get_active ][0];
$SETTING{'rotate reverse'} = $SETTING{'rotate facing'};
}
elsif ( $side->[ $comboboxs->get_active ][0] eq 'facing' ) {
$SETTING{'rotate facing'} = $rotate->[ $comboboxr->get_active ][0];
}
else {
$SETTING{'rotate reverse'} = $rotate->[ $comboboxr->get_active ][0];
}
if ( $r2button->get_active ) {
if ( $side2->[ $comboboxs2->get_active ][0] eq 'facing' ) {
$SETTING{'rotate facing'} = $rotate->[ $comboboxr2->get_active ][0];
}
else {
$SETTING{'rotate reverse'} = $rotate->[ $comboboxr2->get_active ][0];
}
}
}
$logger->info("rotate facing $SETTING{'rotate facing'}");
$logger->info("rotate reverse $SETTING{'rotate reverse'}");
$SETTING{'unpaper on scan'} = $ubutton->get_active;
$logger->info("unpaper $SETTING{'unpaper on scan'}");
$SETTING{'OCR on scan'} = $obutton->get_active;
$logger->info("OCR $SETTING{'OCR on scan'}");
if ( $SETTING{'OCR on scan'} ) {
$SETTING{'ocr engine'} = $ocr_engine[ $comboboxe->get_active ]->[0];
$SETTING{'ocr language'} = $tesslang->[ $comboboxtl->get_active ][0]
if ( $SETTING{'ocr engine'} eq 'tesseract'
or $SETTING{'ocr engine'} eq 'ocropus' );
$SETTING{'ocr language'} = $cflang->[ $comboboxcl->get_active ][0]
if ( $SETTING{'ocr engine'} eq 'cuneiform' );
}
}
);
$self->signal_connect(
show => sub {
$hboxtl->hide_all
if (
defined($hboxtl)
and not( $ocr_engine[ $comboboxe->get_active ]->[0] eq 'tesseract'
or $ocr_engine[ $comboboxe->get_active ]->[0] eq 'ocropus' )
);
$hboxcl->hide_all
if ( defined($hboxcl)
and not( $ocr_engine[ $comboboxe->get_active ]->[0] eq 'cuneiform' ) );
}
);
return;
}
# Called either from changed-value signal of spinbutton,
# or row-changed signal of simplelist
sub update_start {
return unless ( defined $windows );
my $value = $windows->get('page-number-start');
$start = $windows->get('page-number-start') unless ( defined $start );
my $step = $value - $start;
$step = $windows->get('page-number-increment') if ( $step == 0 );
my $exists = TRUE;
my $i = $step > 0 ? 0 : $#{ $slist->{data} };
$start = $value;
while ($exists) {
if ($i < 0
or $i > $#{ $slist->{data} }
or ( $slist->{data}[$i][0] > $value and $step > 0 )
or ( $slist->{data}[$i][0] < $value and $step < 0 ) )
{
$exists = FALSE;
}
elsif ( $slist->{data}[$i][0] == $value ) {
$value += $step;
if ( $value < 1 ) {
$value = 1;
$step = 1;
}
}
else {
$i += $step > 0 ? 1 : -1;
}
}
$windows->set( 'page-number-start', $value );
$start = $value;
update_number();
return;
}
# Update the number of pages to scan spinbutton if necessary
sub update_number {
return unless ( defined $windows );
my $n = $slist->pages_possible( $windows->get('page-number-start'),
$windows->get('page-number-increment') );
$windows->set( 'num-pages', $n )
if ( $n > 0 and $n < $windows->get('num-pages') );
return;
}
sub post_process_scan {
my ( $pages, $rotate, $unpaper_flag, $ocr ) = @_;
if ($rotate) {
rotate(
$rotate, $pages,
sub { # finished callback
my ($page) = @_;
post_process_scan( $page, undef, $unpaper_flag, $ocr );
}
);
}
elsif ($unpaper_flag) {
unpaper_page(
$pages,
$unpaper->get_cmdline,
sub { # finished callback
my ($page) = @_;
post_process_scan( $page, undef, undef, $ocr );
}
);
}
elsif ($ocr) {
ocr_page($pages);
}
return;
}
# Take new scan and display it
sub import_scan {
my %options = @_;
# Interface to frontend
open my $fh, '<', $options{filename} ## no critic (RequireBriefOpen)
or die "can't open $options{filename}: $!\n";
# Read without blocking
my $size = 0;
Glib::IO->add_watch(
fileno($fh),
[ 'in', 'hup' ],
sub {
my ( $fileno, $condition ) = @_;
if ( $condition & 'in' ) { # bit field operation. >= would also work
if ( $size == 0 ) {
$size = Gscan2pdf::NetPBM::file_size_from_header( $options{filename} );
$logger->info("Header suggests $size");
return Glib::SOURCE_CONTINUE if ( $size == 0 );
close($fh);
}
my $filesize = -s $options{filename};
$logger->info("Expecting $size, found $filesize");
if ( $size > $filesize ) {
my $pad = $size - $filesize;
open( my $fh, ">>", $options{filename} )
or die "cannot open >> $options{filename}: $!\n";
my $data = '';
for ( 1 .. $pad * 8 ) {
$data .= '1';
}
printf $fh pack( sprintf( "b%d", length $data ), $data );
close $fh;
$logger->info("Padded $pad bytes");
}
my $gpage = Gscan2pdf::Page->new(
filename => $options{filename},
resolution => $options{resolution},
format => 'Portable anymap',
delete => $options{delete},
dir => $session,
window => $window,
);
my $index = $slist->add_page( $gpage, $options{page}, &update_uimanager );
if ( $index == -1 ) {
show_message_dialog( $windows, 'error', 'close',
$d->get('Unable to load image') );
}
else {
update_uimanager();
post_process_scan( [$gpage], $options{rotate}, $options{unpaper},
$options{ocr} );
}
return Glib::SOURCE_REMOVE;
}
return Glib::SOURCE_CONTINUE;
}
);
return;
}
# print
sub print_dialog {
chdir $SETTING{'cwd'};
my $print_op = Gtk2::PrintOperation->new;
$print_op->set_print_settings($print_settings)
if ( defined $print_settings );
$print_op->signal_connect(
begin_print => sub {
my ( $op, $context ) = @_;
my $settings = $op->get_print_settings;
my $pages = $settings->get('print-pages');
my @page_list;
if ( $pages eq 'ranges' ) {
my $page_set = Set::IntSpan->new;
my $ranges = $settings->get('page-ranges');
for ( split ',', $ranges ) {
$page_set->I($_);
}
for ( 0 .. $#{ $slist->{data} } ) {
push @page_list, $_ if ( $page_set->member( $slist->{data}[$_][0] ) );
}
}
else {
@page_list = ( 0 .. $#{ $slist->{data} } );
}
$op->set_n_pages( scalar(@page_list) );
}
);
$print_op->signal_connect(
draw_page => sub {
my ( $op, $context, $page_number ) = @_;
my $cr = $context->get_cairo_context;
# Context dimensions
my $pwidth = $context->get_width;
my $pheight = $context->get_height;
# Image dimensions
my $pixbuf = Gtk2::Gdk::Pixbuf->new_from_file(
"$slist->{data}[$page_number][2]{filename}")
; # quotes required to prevent File::Temp object being clobbered
my $iwidth = $pixbuf->get_width;
my $iheight = $pixbuf->get_height;
# Scale context to fit image
my $scale = $pwidth / $iwidth;
$scale = $pheight / $iheight if ( $pheight / $iheight < $scale );
$cr->scale( $scale, $scale );
# Set source pixbuf
Gtk2::Gdk::Cairo::Context::set_source_pixbuf( $cr, $pixbuf, 0, 0 );
# Paint
$cr->paint;
return;
}
);
my $res = $print_op->run( 'print-dialog', $window );
$print_settings = $print_op->get_print_settings if ( $res eq 'apply' );
chdir $session;
return;
}
# Cut the selection
sub cut_selection {
if ( $slist->has_focus ) {
copy_selection();
delete_pages();
}
# elsif ($textview -> has_focus) {
# my $clipboard = Gtk2::Clipboard->get(Gtk2::Gdk->SELECTION_CLIPBOARD);
# $textbuffer->cut_clipboard ($clipboard, TRUE)
# }
return;
}
# Copy the selection
sub copy_selection {
if ( $slist->has_focus ) {
undef @clipboard;
my @pages = $slist->get_selected_indices;
for my $page (@pages) {
my @copy = map { [@$_] } $slist->{data}[$page];
push @clipboard, @copy;
}
}
# elsif ($textview -> has_focus) {
# my $clipboard = Gtk2::Clipboard->get(Gtk2::Gdk->SELECTION_CLIPBOARD);
# $textbuffer->copy_clipboard ($clipboard)
# }
return;
}
# Paste the selection
sub paste_selection {
# We only add pages if the list of thumbnails has the focus
if ( $window->get_focus eq $slist ) {
my @page = $slist->get_selected_indices;
# Create a new image file for each page in the clipboard
for (@clipboard) {
my $suffix;
$suffix = $1 if ( $_->[2]{filename} =~ /(\.\w*)$/x );
my $new = File::Temp->new( DIR => $session, SUFFIX => $suffix );
# stringify filename to prevent copy from mangling it
unless ( copy( "$_->[2]{filename}", $new ) ) {
show_message_dialog( $window, 'error', 'close',
$d->get( sprintf("Error pasting image - %s"), $! ) );
return;
}
$_->[2]{filename} = $new;
}
# Block the row-changed signal whilst adding the scan (row) and sorting it.
$slist->get_model->signal_handler_block( $slist->{row_changed_signal} );
# If a page is selected, then insert the pasted page immediately afterwards
if (@page) {
splice @{ $slist->{data} }, $page[0] + 1, 0, @clipboard;
@page = ( $page[0] + 1 );
}
# Otherwise append the page to the end
else {
push @{ $slist->{data} }, @clipboard;
@page = ( $#{ $slist->{data} } - $#clipboard );
}
$slist->renumber;
$slist->get_model->signal_handler_unblock( $slist->{row_changed_signal} );
# Select new page, deselecting others. This fires the select callback,
# displaying the page
$slist->get_selection->unselect_all;
$slist->select(@page);
update_uimanager();
}
# elsif ($textview -> has_focus) {
# my $clipboard = Gtk2::Clipboard->get(Gtk2::Gdk->SELECTION_CLIPBOARD);
# $textbuffer->paste_clipboard ($clipboard, undef, TRUE)
# }
return;
}
# Delete the selected scans
sub delete_pages {
# Update undo/redo buffers
take_snapshot();
my @pages = $slist->get_selected_indices;
my @page = @pages;
$slist->get_selection->signal_handler_block(
$slist->{selection_changed_signal} );
while (@pages) {
splice @{ $slist->{data} }, $pages[0], 1;
@pages = $slist->get_selected_indices;
}
$slist->get_selection->signal_handler_unblock(
$slist->{selection_changed_signal} );
# Select nearest page to last current page
if ( @{ $slist->{data} } and @page ) {
# Select just the first one
@page = ( $page[0] );
$page[0] = $#{ $slist->{data} } if ( $page[0] > $#{ $slist->{data} } );
$slist->select(@page);
}
# Select nothing
elsif ( @{ $slist->{data} } ) {
$slist->select;
}
# No pages left, and having blocked the selection_changed_signal, we've got to clear the image
else {
$view->set_pixbuf(undef);
$scwin_buffer->remove($_) for ( $scwin_buffer->get_children );
}
# Reset start page in scan dialog
reset_start();
update_uimanager();
return;
}
# Reset start page number after delete or new
sub reset_start {
if ( $#{ $slist->{data} } > -1 ) {
my $start_page = $windows->get('page-number-start');
my $step = $windows->get('page-number-increment');
$windows->set( 'page-number-start',
$slist->{data}[ $#{ $slist->{data} } ][0] + $step )
if ( $start_page > $slist->{data}[ $#{ $slist->{data} } ][0] + $step );
}
else {
$windows->set( 'page-number-start', 1 );
}
return;
}
# Select all scans
sub select_all {
# if ($textview -> has_focus) {
# my ($start, $end) = $textbuffer->get_bounds;
# $textbuffer->select_range ($start, $end);
# }
# else {
$slist->get_selection->select_all;
# }
return;
}
# Select all odd(0) or even(1) scans
sub select_odd_even {
my $odd = shift;
my @selection;
for ( 0 .. $#{ $slist->{data} } ) {
push @selection, $_ if ( $slist->{data}[$_][0] % 2 xor $odd );
}
$slist->get_selection->unselect_all;
$slist->select(@selection);
return;
}
sub select_modified_since_ocr {
my @selection;
foreach my $page ( 0 .. $#{ $slist->{data} } ) {
my $dirty_time = $slist->{data}[$page][2]{dirty_time};
my $ocr_flag = $slist->{data}[$page][2]{ocr_flag};
my $ocr_time = $slist->{data}[$page][2]{ocr_time};
$dirty_time = defined($dirty_time) ? $dirty_time : 0;
$ocr_time = defined($ocr_time) ? $ocr_time : 0;
push @selection, $_ if ( $ocr_flag and ( $ocr_time le $dirty_time ) );
}
$slist->get_selection->unselect_all;
$slist->select(@selection);
return;
}
# Select pages with no ocr output
sub select_no_ocr {
my @selection;
for ( 0 .. $#{ $slist->{data} } ) {
push @selection, $_ unless ( defined $slist->{data}[$_][2]{hocr} );
}
$slist->get_selection->unselect_all;
$slist->select(@selection);
return;
}
# Clear the OCR output from selected pages
sub clear_ocr {
# Update undo/redo buffers
take_snapshot();
# Remove the existing canvas
$scwin_buffer->remove($_) for ( $scwin_buffer->get_children );
my @selection = $slist->get_selected_indices;
for (@selection) {
delete $slist->{data}[$_][2]{hocr};
}
return;
}
# Analyse and select blank pages
sub analyse_select_blank {
analyse( 1, 0 );
return;
}
# Select blank pages
sub select_blank_pages {
$slist->get_selection->unselect_all;
foreach my $page ( 0 .. $#{ $slist->{data} } ) {
$logger->info("smp page: $page");
my $dirty_time = $slist->{data}[$page][2]{dirty_time};
my $analyse_time = $slist->{data}[$page][2]{analyse_time};
$dirty_time = defined($dirty_time) ? $dirty_time : 0;
$analyse_time = defined($analyse_time) ? $analyse_time : 0;
if ( $analyse_time le $dirty_time ) {
$logger->warn(
$d->get(
sprintf(
"Page %d probably needs to be re-Analysed. Try Update or Analyse.",
$page + 1 )
)
);
next;
}
#compare Std Dev to threshold
if ( $slist->{data}[$page][2]{std_dev} <= $SETTING{'Blank threshold'} ) {
$slist->select($page);
$logger->info("Selecting blank page");
}
$logger->info( "StdDev: "
. $slist->{data}[$page][2]{std_dev}
. " threshold: "
. $SETTING{'Blank threshold'} );
}
return;
}
# Analyse and select dark pages
sub analyse_select_dark {
analyse( 0, 1 );
return;
}
# Select dark pages
sub select_dark_pages {
$slist->get_selection->unselect_all;
$logger->info("Checking for dark pages now, is analysis done?");
foreach my $page ( 0 .. $#{ $slist->{data} } ) {
$logger->info("smp page: $page");
my $dirty_time = $slist->{data}[$page][2]{dirty_time};
my $analyse_time = $slist->{data}[$page][2]{analyse_time};
$dirty_time = defined($dirty_time) ? $dirty_time : 0;
$analyse_time = defined($analyse_time) ? $analyse_time : 0;
if ( $analyse_time le $dirty_time ) {
$logger->warn(
$d->get(
sprintf(
"Page %d probably needs to be re-Analysed. Try Update or Analyse.",
$page + 1 )
)
);
next;
}
#compare Mean to threshold
if ( $slist->{data}[$page][2]{mean} <= $SETTING{'Dark threshold'} ) {
$slist->select($page);
$logger->info("Selecting dark page");
}
}
return;
}
# Display about dialog
sub about {
use utf8;
my $about = Gtk2::AboutDialog->new;
# Gtk2::AboutDialog->set_url_hook ($func, $data=undef);
# Gtk2::AboutDialog->set_email_hook ($func, $data=undef);
$about->set_program_name($prog_name);
$about->set_version($VERSION);
my $authors = <<'EOS';
Frederik Elwert
Klaus Ethgen
Andy Fingerhut
Leon Fisk
John Goerzen
David Hampton
Sascha Hunold
Matthijs Kooijman
Chris Mayo
Pablo Saratxaga
Torsten Schönfeld
Roy Shahbazian
Jarl Stefansson
Jakub Wilk
Hiroshi Miura
EOS
$about->set_authors( "Jeff Ratcliffe\n\n"
. $d->get('Patches gratefully received from:')
. "\n$authors" );
$about->set_comments( $d->get('To aid the scan-to-PDF process') );
$about->set_copyright( $d->get('Copyright 2006--2013 Jeffrey Ratcliffe') );
my $licence = <<'EOS';
gscan2pdf --- to aid the scan to PDF or DjVu process
Copyright 2006 -- 2013 Jeffrey Ratcliffe
This program is free software: you can redistribute it and/or modify
it under the terms of the version 3 GNU General Public License as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
EOS
$about->set_license($licence);
$about->set_website('http://gscan2pdf.sf.net');
my $translators =
<<'EOS'; # inverted commas required around EOS because of UTF-8 in $translators
Prescott_SK
Rodrigo Zimmermann
peteradleralberti
mavosaure
Arthur Rodrigues
Utku BERBEROĞLU
Piotr Strębski
Aleksey Kabanov
Сергій Дубик
zdpo
Eric Spierings
Milo Casagrande
Raúl González Duque
R120X
NSV
Alexandre Prokoudine
Paul Wohlhart
Pierre Slamich
Tiago Silva
Igor Zubarev
EOS
$about->set_translator_credits($translators);
$about->set_artists('lodp');
$about->run;
$about->destroy;
return;
}
# Check that a command exists
sub check_command {
return system("which $_[0] >/dev/null 2>/dev/null") == 0 ? TRUE : FALSE;
}
# Dialog for renumber
sub renumber_dialog {
if ( defined $windowrn ) {
$windowrn->present;
return;
}
$windowrn = Gscan2pdf::Dialog::Renumber->new(
'transient-for' => $window,
document => $slist,
'hide-on-delete' => FALSE,
border_width => $border_width
);
# Update undo/redo buffers
$windowrn->signal_connect(
'before-renumber' => sub {
take_snapshot();
}
);
$windowrn->show_all;
return;
}
# Helper function to convert an array of indices into an array of Gscan2pdf::Page objects
sub indices2pages {
my @indices = @_;
my @pages;
for (@indices) {
push @pages, $slist->{data}[$_][2];
}
return @pages;
}
# Rotate selected images
sub rotate {
my ( $angle, $pagelist, $callback ) = @_;
# Update undo/redo buffers
take_snapshot();
for my $page ( @{$pagelist} ) {
my ( $signal, $pid );
$pid = $slist->rotate(
angle => $angle,
page => $page,
queued_callback => sub {
return update_tpbar(@_);
},
started_callback => sub {
my ( $thread, $process, $completed, $total ) = @_;
$signal = setup_tpbar( $thread, $process, $completed, $total, $pid );
return TRUE if ( defined $signal );
},
finished_callback => sub {
my ( $new_page, $pending ) = @_;
$callback->($new_page) if $callback;
$thbox->hide_all unless $pending;
$tcbutton->signal_handler_disconnect($signal) if ( defined $signal );
},
error_callback => \&error_callback,
display_callback => sub {
my ($new_page) = @_;
display_image($new_page);
},
);
}
return;
}
# Analyse selected images
sub analyse {
my ( $select_blank, $select_dark ) = @_;
# Update undo/redo buffers
take_snapshot();
foreach my $i ( 0 .. $#{ $slist->{data} } ) {
my $dirty_time = $slist->{data}[$i][2]{dirty_time};
my $analyse_time = $slist->{data}[$i][2]{analyse_time};
$dirty_time = defined($dirty_time) ? $dirty_time : 0;
$analyse_time = defined($analyse_time) ? $analyse_time : 0;
if ( $analyse_time le $dirty_time ) {
$logger->info(
"Updating: $slist->{data}[$i][0] analyse_time: $analyse_time dirty_time: $dirty_time"
);
my ( $signal, $pid );
$pid = $slist->analyse(
page => $slist->{data}[$i][2],
queued_callback => sub {
return update_tpbar(@_);
},
started_callback => sub {
my ( $thread, $process, $completed, $total ) = @_;
$signal = setup_tpbar( $thread, $process, $completed, $total, $pid );
return TRUE if ( defined $signal );
},
finished_callback => sub {
my ( $new_page, $pending ) = @_;
$thbox->hide_all unless $pending;
$tcbutton->signal_handler_disconnect($signal) if ( defined $signal );
select_blank_pages() if $select_blank;
select_dark_pages() if $select_dark;
},
error_callback => \&error_callback,
);
}
}
return;
}
# Handle right-clicks
sub handle_clicks {
my ( $widget, $event ) = @_;
# $SETTING{'RMB'} = ($event->button == 3);
#warn "rmb $SETTING{'RMB'}\n";
if ( $event->button == 3 ) {
if ( $widget->isa('Gtk2::ImageView') ) { # main image
$uimanager->get_widget('/Detail_Popup')
->popup( undef, undef, undef, undef, $event->button, $event->time );
}
else { # Thumbnail simplelist
$uimanager->get_widget('/Thumb_Popup')
->popup( undef, undef, undef, undef, $event->button, $event->time );
}
# block event propagation
return TRUE;
}
# allow event propagation
return FALSE;
}
# Display page selector and on apply threshold accordingly
sub threshold {
# $SETTING{'Page range'} = 'selected' if $SETTING{'RMB'};
my $windowt = Gscan2pdf::Dialog->new(
'transient-for' => $window,
title => $d->get('Threshold'),
border_width => $border_width
);
my $vbox = $windowt->get('vbox');
# Frame for page range
add_page_range($vbox);
# SpinButton for threshold
my $hboxt = Gtk2::HBox->new;
$vbox->pack_start( $hboxt, FALSE, TRUE, 0 );
my $label = Gtk2::Label->new( $d->get('Threshold') );
$hboxt->pack_start( $label, FALSE, TRUE, 0 );
my $labelp = Gtk2::Label->new( $d->get('%') );
$hboxt->pack_end( $labelp, FALSE, TRUE, 0 );
my $spinbutton = Gtk2::SpinButton->new_with_range( 0, 100, 1 );
$spinbutton->set_value( $SETTING{'threshold tool'} );
$hboxt->pack_end( $spinbutton, FALSE, TRUE, 0 );
# HBox for buttons
my $hboxb = _hbox_with_apply_cancel_buttons(
sub {
# Update undo/redo buffers
take_snapshot();
$SETTING{'threshold tool'} = $spinbutton->get_value;
my @pagelist =
$slist->get_page_index( $SETTING{'Page range'}, \&error_callback );
if ( not @pagelist ) { return }
my $page = 0;
for my $i (@pagelist) {
$page++;
my ( $signal, $pid );
$pid = $slist->threshold(
threshold => $SETTING{'threshold tool'},
page => $slist->{data}[$i][2],
queued_callback => sub {
return update_tpbar(@_);
},
started_callback => sub {
my ( $thread, $process, $completed, $total ) = @_;
$signal = setup_tpbar( $thread, $process, $completed, $total, $pid );
return TRUE if ( defined $signal );
},
finished_callback => sub {
my ( $new_page, $pending ) = @_;
$thbox->hide_all unless $pending;
$tcbutton->signal_handler_disconnect($signal) if ( defined $signal );
},
error_callback => \&error_callback,
display_callback => sub {
my ($new_page) = @_;
display_image($new_page);
},
);
}
},
sub { $windowt->destroy }
);
$vbox->pack_start( $hboxb, FALSE, TRUE, 0 );
$windowt->show_all;
return;
}
# Display page selector and on apply negate accordingly
sub negate {
# $SETTING{'Page range'} = 'selected' if $SETTING{'RMB'};
my $windowt = Gscan2pdf::Dialog->new(
'transient-for' => $window,
title => $d->get('Negate'),
border_width => $border_width
);
my $vbox = $windowt->get('vbox');
# Frame for page range
add_page_range($vbox);
# HBox for buttons
my $hboxb = _hbox_with_apply_cancel_buttons(
sub {
# Update undo/redo buffers
take_snapshot();
my @pagelist =
$slist->get_page_index( $SETTING{'Page range'}, \&error_callback );
if ( not @pagelist ) { return }
for my $i (@pagelist) {
my ( $signal, $pid );
$pid = $slist->negate(
page => $slist->{data}[$i][2],
queued_callback => sub {
return update_tpbar(@_);
},
started_callback => sub {
my ( $thread, $process, $completed, $total ) = @_;
$signal = setup_tpbar( $thread, $process, $completed, $total, $pid );
return TRUE if ( defined $signal );
},
finished_callback => sub {
my ( $new_page, $pending ) = @_;
$thbox->hide_all unless $pending;
$tcbutton->signal_handler_disconnect($signal) if ( defined $signal );
},
error_callback => \&error_callback,
display_callback => sub {
my ($new_page) = @_;
display_image($new_page);
},
);
}
},
sub { $windowt->destroy }
);
$vbox->pack_start( $hboxb, FALSE, TRUE, 0 );
$windowt->show_all;
return;
}
# Display page selector and on apply unsharp accordingly
sub unsharp {
# $SETTING{'Page range'} = 'selected' if $SETTING{'RMB'};
my $windowum = Gscan2pdf::Dialog->new(
'transient-for' => $window,
title => $d->get('Unsharp mask'),
border_width => $border_width
);
my $vbox = $windowum->get('vbox');
# Frame for page range
add_page_range($vbox);
# SpinButton for radius
my $hbox = Gtk2::HBox->new;
$vbox->pack_start( $hbox, FALSE, TRUE, 0 );
my $label = Gtk2::Label->new( $d->get('Radius') );
$hbox->pack_start( $label, FALSE, TRUE, 0 );
$label = Gtk2::Label->new( $d->get('pixels') );
$hbox->pack_end( $label, FALSE, TRUE, 0 );
my $spinbuttonr = Gtk2::SpinButton->new_with_range( 0, 100, 1 );
$spinbuttonr->set_value( $SETTING{'unsharp radius'} );
$tooltips->set_tip(
$spinbuttonr,
$d->get(
'The radius of the Gaussian, in pixels, not counting the center pixel (0 = automatic).'
)
);
$hbox->pack_end( $spinbuttonr, FALSE, TRUE, 0 );
# SpinButton for sigma
$hbox = Gtk2::HBox->new;
$vbox->pack_start( $hbox, FALSE, TRUE, 0 );
$label = Gtk2::Label->new( $d->get('Sigma') );
$hbox->pack_start( $label, FALSE, TRUE, 0 );
$label = Gtk2::Label->new( $d->get('pixels') );
$hbox->pack_end( $label, FALSE, TRUE, 0 );
my $spinbuttons = Gtk2::SpinButton->new_with_range( 0, 5, .1 );
$spinbuttons->set_value( $SETTING{'unsharp sigma'} );
$tooltips->set_tip( $spinbuttons,
$d->get('The standard deviation of the Gaussian.') );
$hbox->pack_end( $spinbuttons, FALSE, TRUE, 0 );
# SpinButton for amount
$hbox = Gtk2::HBox->new;
$vbox->pack_start( $hbox, FALSE, TRUE, 0 );
$label = Gtk2::Label->new( $d->get('Amount') );
$hbox->pack_start( $label, FALSE, TRUE, 0 );
$label = Gtk2::Label->new( $d->get('%') );
$hbox->pack_end( $label, FALSE, TRUE, 0 );
my $spinbuttona = Gtk2::SpinButton->new_with_range( 0, 100, 1 );
$spinbuttona->set_value( $SETTING{'unsharp amount'} );
$tooltips->set_tip(
$spinbuttona,
$d->get(
'The percentage of the difference between the original and the blur image that is added back into the original.'
)
);
$hbox->pack_end( $spinbuttona, FALSE, TRUE, 0 );
# SpinButton for threshold
$hbox = Gtk2::HBox->new;
$vbox->pack_start( $hbox, FALSE, TRUE, 0 );
$label = Gtk2::Label->new( $d->get('Threshold') );
$hbox->pack_start( $label, FALSE, TRUE, 0 );
my $spinbuttont = Gtk2::SpinButton->new_with_range( 0, 1, 0.01 );
$spinbuttont->set_value( $SETTING{'unsharp threshold'} );
$tooltips->set_tip(
$spinbuttont,
$d->get(
'The threshold, as a fraction of QuantumRange, needed to apply the difference amount.'
)
);
$hbox->pack_end( $spinbuttont, FALSE, TRUE, 0 );
# HBox for buttons
my $hboxb = _hbox_with_apply_cancel_buttons(
sub {
# Update undo/redo buffers
take_snapshot();
$SETTING{'unsharp radius'} = $spinbuttonr->get_value;
$SETTING{'unsharp sigma'} = $spinbuttons->get_value;
$SETTING{'unsharp amount'} = $spinbuttona->get_value;
$SETTING{'unsharp threshold'} = $spinbuttont->get_value;
my @pagelist =
$slist->get_page_index( $SETTING{'Page range'}, \&error_callback );
if ( not @pagelist ) { return }
for my $i (@pagelist) {
my ( $signal, $pid );
$pid = $slist->unsharp(
page => $slist->{data}[$i][2],
radius => $SETTING{'unsharp radius'},
sigma => $SETTING{'unsharp sigma'},
amount => $SETTING{'unsharp amount'},
threshold => $SETTING{'unsharp threshold'},
queued_callback => sub {
return update_tpbar(@_);
},
started_callback => sub {
my ( $thread, $process, $completed, $total ) = @_;
$signal = setup_tpbar( $thread, $process, $completed, $total, $pid );
return TRUE if ( defined $signal );
},
finished_callback => sub {
my ( $new_page, $pending ) = @_;
$thbox->hide_all unless $pending;
$tcbutton->signal_handler_disconnect($signal) if ( defined $signal );
},
error_callback => \&error_callback,
display_callback => sub {
my ($new_page) = @_;
display_image($new_page);
},
);
}
},
sub { $windowum->destroy }
);
$windowum->show_all;
return;
}
# Callback for change Gtk2::ImageView::Tool
sub change_image_tool_cb {
my ( $action, $current ) = @_;
my $value = $current->get_current_value();
my $tool = $selector;
if ( $value == 10 ) {
$tool = $dragger;
}
elsif ( $value == 30 ) {
$tool = $painter;
}
$view->set_tool($tool);
if ( $value == 20
and defined( $SETTING{selection} )
and @{ $SETTING{selection} } == 4 )
{
$selector->signal_handler_block( $selector->{selection_changed_signal} );
$selector->set_selection(
Gtk2::Gdk::Rectangle->new( @{ $SETTING{selection} } ) );
$selector->signal_handler_unblock( $selector->{selection_changed_signal} );
}
return;
}
# Display page selector and on apply crop accordingly
sub crop {
if ( defined $windowc ) {
$windowc->present;
return;
}
# $SETTING{'Page range'} = 'selected' if $SETTING{'RMB'};
$windowc = Gscan2pdf::Dialog->new(
'transient-for' => $window,
title => $d->get('Crop'),
'hide-on-delete' => TRUE,
border_width => $border_width
);
my $vbox = $windowc->get('vbox');
# Frame for page range
add_page_range($vbox);
# SpinButton for x
my $hbox = Gtk2::HBox->new;
$vbox->pack_start( $hbox, FALSE, TRUE, 0 );
my $label = Gtk2::Label->new( $d->get('x') );
$hbox->pack_start( $label, FALSE, TRUE, 0 );
$label = Gtk2::Label->new( $d->get('pixels') );
$hbox->pack_end( $label, FALSE, TRUE, 0 );
$sb_selector_x = Gtk2::SpinButton->new_with_range( 0, $current_page->{w}, 1 );
$tooltips->set_tip( $sb_selector_x,
$d->get('The x-position of the left hand edge of the crop.') );
$hbox->pack_end( $sb_selector_x, FALSE, TRUE, 0 );
# SpinButton for y
$hbox = Gtk2::HBox->new;
$vbox->pack_start( $hbox, FALSE, TRUE, 0 );
$label = Gtk2::Label->new( $d->get('y') );
$hbox->pack_start( $label, FALSE, TRUE, 0 );
$label = Gtk2::Label->new( $d->get('pixels') );
$hbox->pack_end( $label, FALSE, TRUE, 0 );
$sb_selector_y = Gtk2::SpinButton->new_with_range( 0, $current_page->{h}, 1 );
$tooltips->set_tip( $sb_selector_y,
$d->get('The y-position of the top edge of the crop.') );
$hbox->pack_end( $sb_selector_y, FALSE, TRUE, 0 );
# SpinButton for w
$hbox = Gtk2::HBox->new;
$vbox->pack_start( $hbox, FALSE, TRUE, 0 );
$label = Gtk2::Label->new( $d->get('Width') );
$hbox->pack_start( $label, FALSE, TRUE, 0 );
$label = Gtk2::Label->new( $d->get('pixels') );
$hbox->pack_end( $label, FALSE, TRUE, 0 );
$sb_selector_w = Gtk2::SpinButton->new_with_range( 0, $current_page->{w}, 1 );
$tooltips->set_tip( $sb_selector_w, $d->get('The width of the crop.') );
$hbox->pack_end( $sb_selector_w, FALSE, TRUE, 0 );
# SpinButton for h
$hbox = Gtk2::HBox->new;
$vbox->pack_start( $hbox, FALSE, TRUE, 0 );
$label = Gtk2::Label->new( $d->get('Height') );
$hbox->pack_start( $label, FALSE, TRUE, 0 );
$label = Gtk2::Label->new( $d->get('pixels') );
$hbox->pack_end( $label, FALSE, TRUE, 0 );
$sb_selector_h = Gtk2::SpinButton->new_with_range( 0, $current_page->{h}, 1 );
$tooltips->set_tip( $sb_selector_h, $d->get('The height of the crop.') );
$hbox->pack_end( $sb_selector_h, FALSE, TRUE, 0 );
# Callbacks if the spinbuttons change
$sb_selector_x->signal_connect(
'value-changed' => sub {
$SETTING{selection}[0] = $sb_selector_x->get_value;
$sb_selector_w->set_range( 0, $current_page->{w} - $SETTING{selection}[0] );
update_selector();
}
);
$sb_selector_y->signal_connect(
'value-changed' => sub {
$SETTING{selection}[1] = $sb_selector_y->get_value;
$sb_selector_h->set_range( 0, $current_page->{h} - $SETTING{selection}[1] );
update_selector();
}
);
$sb_selector_w->signal_connect(
'value-changed' => sub {
$SETTING{selection}[2] = $sb_selector_w->get_value;
$sb_selector_x->set_range( 0, $current_page->{w} - $SETTING{selection}[2] );
update_selector();
}
);
$sb_selector_h->signal_connect(
'value-changed' => sub {
$SETTING{selection}[3] = $sb_selector_h->get_value;
$sb_selector_y->set_range( 0, $current_page->{h} - $SETTING{selection}[3] );
update_selector();
}
);
$sb_selector_x->set_value( $SETTING{selection}[0] )
if ( defined $SETTING{selection}[0] );
$sb_selector_y->set_value( $SETTING{selection}[1] )
if ( defined $SETTING{selection}[1] );
$sb_selector_w->set_value( $SETTING{selection}[2] )
if ( defined $SETTING{selection}[2] );
$sb_selector_h->set_value( $SETTING{selection}[3] )
if ( defined $SETTING{selection}[3] );
# HBox for buttons
my $hboxb = _hbox_with_apply_cancel_buttons(
sub {
return unless ( @{ $SETTING{selection} } );
# Update undo/redo buffers
take_snapshot();
my @pagelist =
$slist->get_page_index( $SETTING{'Page range'}, \&error_callback );
if ( not @pagelist ) { return }
for my $i (@pagelist) {
my ( $signal, $pid );
$pid = $slist->crop(
page => $slist->{data}[$i][2],
x => $SETTING{selection}[0],
y => $SETTING{selection}[1],
w => $SETTING{selection}[2],
h => $SETTING{selection}[3],
queued_callback => sub {
return update_tpbar(@_);
},
started_callback => sub {
my ( $thread, $process, $completed, $total ) = @_;
$signal = setup_tpbar( $thread, $process, $completed, $total, $pid );
return TRUE if ( defined $signal );
},
finished_callback => sub {
my ( $new_page, $pending ) = @_;
$thbox->hide_all unless $pending;
$tcbutton->signal_handler_disconnect($signal) if ( defined $signal );
},
error_callback => \&error_callback,
display_callback => sub {
my ($new_page) = @_;
display_image($new_page);
},
);
}
},
sub { $windowc->hide }
);
$vbox->pack_start( $hboxb, FALSE, TRUE, 0 );
$windowc->show_all;
return;
}
sub update_selector {
my $sel = $selector->get_selection;
$selector->signal_handler_block( $selector->{selection_changed_signal} );
$selector->set_selection(
Gtk2::Gdk::Rectangle->new( @{ $SETTING{selection} } ) )
if ( defined $sel );
$selector->signal_handler_unblock( $selector->{selection_changed_signal} );
return;
}
# Run a user-defined tool on the selected images
sub user_defined_tool {
my ($action) = @_;
my @pages = $slist->get_selected_indices;
# Update undo/redo buffers
take_snapshot();
my $cmd = $action->get('label');
for my $i (@pages) {
my ( $signal, $pid );
$pid = $slist->user_defined(
page => $slist->{data}[$i][2],
command => $cmd,
queued_callback => sub {
return update_tpbar(@_);
},
started_callback => sub {
my ( $thread, $process, $completed, $total ) = @_;
$signal = setup_tpbar( $thread, $process, $completed, $total, $pid );
return TRUE if ( defined $signal );
},
finished_callback => sub {
my ( $new_page, $pending ) = @_;
$thbox->hide_all unless $pending;
$tcbutton->signal_handler_disconnect($signal) if ( defined $signal );
},
error_callback => \&error_callback,
display_callback => sub {
my ($new_page) = @_;
display_image($new_page);
},
);
}
return;
}
# queue $page to be processed by unpaper
sub unpaper_page {
my ( $pages, $options, $callback ) = @_;
$options = '' unless ( defined $options );
# Update undo/redo buffers
take_snapshot();
for my $pageobject ( @{$pages} ) {
my ( $signal, $pid );
$pid = $slist->unpaper(
page => $pageobject,
options => $options,
queued_callback => sub {
return update_tpbar(@_);
},
started_callback => sub {
my ( $thread, $process, $completed, $total ) = @_;
$signal = setup_tpbar( $thread, $process, $completed, $total, $pid );
return TRUE if ( defined $signal );
},
finished_callback => sub {
my ( $new_page, $pending ) = @_;
$callback->($new_page) if $callback;
$thbox->hide_all unless $pending;
$tcbutton->signal_handler_disconnect($signal) if ( defined $signal );
},
error_callback => \&error_callback,
display_callback => sub {
my ($new_page) = @_;
display_image($new_page);
},
);
}
return;
}
# Run unpaper to clean up scan.
sub unpaper {
if ( defined $windowu ) {
$windowu->present;
return;
}
$windowu = Gscan2pdf::Dialog->new(
'transient-for' => $window,
title => $d->get('unpaper'),
'hide-on-delete' => TRUE,
border_width => $border_width
);
my $vbox = $windowu->get('vbox');
$unpaper->add_options($vbox);
# Frame for page range
add_page_range($vbox);
# HBox for buttons
my $hboxb = Gtk2::HBox->new;
$vbox->pack_start( $hboxb, FALSE, TRUE, 0 );
# OK button
my $sbutton = Gtk2::Button->new_from_stock('gtk-ok');
$hboxb->pack_start( $sbutton, TRUE, TRUE, 0 );
$sbutton->signal_connect(
clicked => sub {
# Update undo/redo buffers
take_snapshot();
# Update $SETTING
$SETTING{'unpaper options'} = $unpaper->get_options;
# run unpaper
my @pagelist = indices2pages(
$slist->get_page_index( $SETTING{'Page range'}, \&error_callback ) );
if ( not @pagelist ) { return }
unpaper_page( \@pagelist, $unpaper->get_cmdline );
$windowu->hide;
}
);
# Cancel button
my $cbutton = Gtk2::Button->new_from_stock('gtk-cancel');
$hboxb->pack_end( $cbutton, FALSE, FALSE, 0 );
$cbutton->signal_connect( clicked => sub { $windowu->hide; } );
$windowu->show_all;
return;
}
# Add $page to the OCR stack, setting it off if not running.
sub ocr_page {
my ($pages) = @_;
my ( $signal, $pid );
my %options = (
queued_callback => sub {
return update_tpbar(@_);
},
started_callback => sub {
my ( $thread, $process, $completed, $total ) = @_;
$signal = setup_tpbar( $thread, $process, $completed, $total, $pid );
return TRUE if ( defined $signal );
},
finished_callback => sub {
my ( $new_page, $pending ) = @_;
$thbox->hide_all unless $pending;
$tcbutton->signal_handler_disconnect($signal) if ( defined $signal );
},
error_callback => \&error_callback,
display_callback => sub {
my ($new_page) = @_;
my @page = $slist->get_selected_indices;
create_canvas($new_page)
if ( @page and $new_page == $slist->{data}[ $page[0] ][2] );
}
);
$options{language} = $SETTING{'ocr language'}
unless ( $SETTING{'ocr engine'} eq 'gocr' );
for my $page ( @{$pages} ) {
$options{page} = $page;
if ( $SETTING{'ocr engine'} eq 'gocr' ) {
$pid = $slist->gocr(%options);
}
elsif ( $SETTING{'ocr engine'} eq 'tesseract' ) {
$pid = $slist->tesseract(%options);
}
elsif ( $SETTING{'ocr engine'} eq 'ocropus' ) {
$pid = $slist->ocropus(%options);
}
else { # cuneiform
$pid = $slist->cuneiform(%options);
}
}
return;
}
# Create a combobox from an array and set the default
sub combobox_from_array {
my (@array) = @_;
# Fill ComboBox
my $combobox = Gtk2::ComboBox->new_text;
foreach (@array) {
$combobox->append_text( $_->[1] );
}
return $combobox;
}
# Create a combobox from an array and set the default
sub combobox_set_active {
my ( $combobox, $default, @array ) = @_;
# Fill ComboBox
my $i = 0;
my $o;
if ( defined($default) ) {
foreach (@array) {
$o = $i if ( defined( $_->[0] ) and $_->[0] eq $default );
++$i;
}
}
$o = 0 unless ( defined $o );
$combobox->set_active($o);
return;
}
# Add hbox for tesseract languages
sub add_tess_languages {
my ($vbox) = @_;
my $hbox = Gtk2::HBox->new;
$vbox->pack_start( $hbox, FALSE, FALSE, 0 );
my $label = Gtk2::Label->new( $d->get('Language to recognise') );
$hbox->pack_start( $label, TRUE, TRUE, 0 );
# Tesseract language files
my @tesslang;
for ( sort { $a cmp $b } keys %{ Gscan2pdf::Tesseract->languages } ) {
push @tesslang, [ $_, $d->get( ${ Gscan2pdf::Tesseract->languages }{$_} ) ];
}
# If there are no language files, then we have tesseract-1.0, i.e. English
unless (@tesslang) {
push @tesslang, [ undef, $d->get('English') ];
$logger->info("No tesseract languages found");
}
my $combobox = combobox_from_array(@tesslang);
combobox_set_active( $combobox, $SETTING{'ocr language'}, @tesslang );
$hbox->pack_end( $combobox, TRUE, TRUE, 0 );
return $hbox, $combobox, @tesslang;
}
# Add hbox for cuneiform languages
sub add_cf_languages {
my ($vbox) = @_;
my $hbox = Gtk2::HBox->new;
$vbox->pack_start( $hbox, FALSE, FALSE, 0 );
my $label = Gtk2::Label->new( $d->get('Language to recognise') );
$hbox->pack_start( $label, TRUE, TRUE, 0 );
# Tesseract language files
my @lang;
for ( sort { $a cmp $b } keys %{ Gscan2pdf::Cuneiform->languages } ) {
push @lang, [ $_, $d->get( ${ Gscan2pdf::Cuneiform->languages }{$_} ) ];
}
my $combobox = combobox_from_array(@lang);
combobox_set_active( $combobox, $SETTING{'ocr language'}, @lang );
$hbox->pack_end( $combobox, TRUE, TRUE, 0 );
return $hbox, $combobox, @lang;
}
# Run OCR on current page and display result
sub OCR {
if ( defined $windowo ) {
$windowo->present;
return;
}
$windowo = Gscan2pdf::Dialog->new(
'transient-for' => $window,
title => $d->get('OCR'),
'hide-on-delete' => TRUE,
border_width => $border_width
);
my $vbox = $windowo->get('vbox');
# OCR engine selection
my $hboxe = Gtk2::HBox->new;
$vbox->pack_start( $hboxe, TRUE, TRUE, 0 );
my $label = Gtk2::Label->new( $d->get('OCR Engine') );
$hboxe->pack_start( $label, FALSE, FALSE, 0 );
my $combobe = combobox_from_array(@ocr_engine);
combobox_set_active( $combobe, $SETTING{'ocr engine'}, @ocr_engine );
$hboxe->pack_end( $combobe, FALSE, FALSE, 0 );
my ( $comboboxtl, $hboxtl, @tesslang, $comboboxcl, $hboxcl, @cflang );
if ( $dependencies{tesseract} ) {
( $hboxtl, $comboboxtl, @tesslang ) = add_tess_languages($vbox);
$combobe->signal_connect(
changed => sub {
if ($ocr_engine[ $combobe->get_active ]->[0] eq 'tesseract'
or $ocr_engine[ $combobe->get_active ]->[0] eq 'ocropus' )
{
$hboxtl->show_all;
}
else {
$hboxtl->hide_all;
}
}
);
}
if ( $dependencies{cuneiform} ) {
( $hboxcl, $comboboxcl, @cflang ) = add_cf_languages($vbox);
$combobe->signal_connect(
changed => sub {
if ( $ocr_engine[ $combobe->get_active ]->[0] eq 'cuneiform' ) {
$hboxcl->show_all;
}
else {
$hboxcl->hide_all;
}
}
);
}
# Frame for page range
add_page_range($vbox);
# HBox for buttons
my $hbox = Gtk2::HBox->new;
$vbox->pack_start( $hbox, FALSE, TRUE, 0 );
# Start button
my $obutton = Gtk2::Button->new( $d->get('Start OCR') );
$hbox->pack_start( $obutton, TRUE, TRUE, 0 );
$obutton->signal_connect(
clicked => sub {
$SETTING{'ocr engine'} = $ocr_engine[ $combobe->get_active ]->[0];
$SETTING{'ocr language'} = $tesslang[ $comboboxtl->get_active ]->[0]
if ( $SETTING{'ocr engine'} eq 'tesseract'
or $SETTING{'ocr engine'} eq 'ocropus' );
$SETTING{'ocr language'} = $cflang[ $comboboxcl->get_active ]->[0]
if ( $SETTING{'ocr engine'} eq 'cuneiform' );
# fill $pagelist with filenames depending on which radiobutton is active
my @pagelist = indices2pages(
$slist->get_page_index( $SETTING{'Page range'}, \&error_callback ) );
if ( not @pagelist ) { return }
ocr_page( \@pagelist );
$windowo->hide;
}
);
# Close button
my $cbutton = Gtk2::Button->new_from_stock('gtk-close');
$hbox->pack_end( $cbutton, FALSE, FALSE, 0 );
$cbutton->signal_connect( clicked => sub { $windowo->hide; } );
$windowo->show_all;
$hboxtl->hide_all
if (
defined($hboxtl)
and not( $ocr_engine[ $combobe->get_active ]->[0] eq 'tesseract'
or $ocr_engine[ $combobe->get_active ]->[0] eq 'ocropus' )
);
$hboxcl->hide_all
if ( defined($hboxcl)
and not( $ocr_engine[ $combobe->get_active ]->[0] eq 'cuneiform' ) );
return;
}
# Remove temporary files, note window state, save settings and quit.
sub quit {
# Check that all pages have been saved
for ( my $i = 0 ; $i < @{ $slist->{data} } ; $i++ ) {
if ( not $slist->{data}[$i][2]{saved} ) {
my $response =
show_message_dialog( $window, 'question', 'ok-cancel',
$d->get("Some pages have not been saved.\nDo you really want to quit?") );
if ( $response ne 'ok' ) {
return FALSE;
}
else {
last;
}
}
}
# Make sure that we are back in the start directory, otherwise we can't delete
# the temp dir.
chdir $SETTING{'cwd'};
# Remove temporary files (for some reason File::Temp wasn't doing its job here)
unlink <$session/*>;
rmdir $session;
# Write window state to settings
( $SETTING{'window_width'}, $SETTING{'window_height'} ) = $window->get_size;
( $SETTING{'window_x'}, $SETTING{'window_y'} ) = $window->get_position;
$SETTING{'thumb panel'} = $hpaned->get_position;
# delete $SETTING{'RMB'};
# Write config file
$conf->save_file( $rc, \%SETTING );
$logger->info("Wrote config to $ENV{'HOME'}/.$prog_name");
kill_threads();
kill_subs();
$logger->debug("Quitting");
return TRUE;
}
# kill all threads
sub kill_threads {
$logger->info("Killing Sane thread(s)");
Gscan2pdf::Frontend::Sane->quit();
$logger->info("Killing document thread(s)");
Gscan2pdf::Document->quit();
return;
}
# View POD
sub view_pod {
if ( defined $windowh ) {
$windowh->present;
return;
}
try { require Gtk2::Ex::PodViewer }
catch {
show_message_dialog(
$window, 'error', 'close',
sprintf(
$d->get(
"The help viewer requires module Gtk2::Ex::PodViewer\n"
. "Alternatively, try: %s %s\n\n"
),
$prog_name,
"--help"
)
);
return;
};
# Window
$windowh = Gtk2::Window->new;
$windowh->set_transient_for($window); # Assigns parent
$windowh->signal_connect(
delete_event => sub {
$windowh->hide;
return TRUE; # ensures that the window is not destroyed
}
);
$windowh->set_default_size( 800, 600 );
# Vertical divider between index and viewer
my $pane = Gtk2::HPaned->new;
$pane->set_position(200);
$windowh->add($pane);
# Index list
my $index = Gtk2::Ex::Simple::List->new(
'icon' => 'pixbuf',
'title' => 'text',
'link' => 'hstring'
);
$index->set_headers_visible(FALSE);
$index->get_column(1)->set_sizing('autosize');
# Index
my $index_scrwin = Gtk2::ScrolledWindow->new;
$index_scrwin->set_shadow_type('in');
$index_scrwin->set_policy( 'automatic', 'automatic' );
$index_scrwin->add_with_viewport($index);
$index_scrwin->get_child->set_shadow_type('none');
# Viewer
my $viewer = Gtk2::Ex::PodViewer->new;
$viewer->set_border_width($border_width);
$viewer->set_cursor_visible(FALSE);
$index->get_selection->signal_connect(
'changed',
sub {
my $idx = ( $index->get_selected_indices )[0];
my $mark = $index->{data}[$idx][2];
$viewer->jump_to($mark);
return TRUE;
}
);
my $viewer_scrwin = Gtk2::ScrolledWindow->new;
$viewer_scrwin->set_shadow_type('in');
$viewer_scrwin->set_policy( 'automatic', 'automatic' );
$viewer_scrwin->add($viewer);
$pane->add1($index_scrwin);
$pane->add2($viewer_scrwin);
$viewer->load($0);
# Index contents
my $idx_pbf = Gtk2::Image->new->render_icon( 'gtk-jump-to', 'menu' );
map { push( @{ $index->{data} }, [ $idx_pbf, strippod($_), $_ ] ) }
$viewer->get_marks;
$windowh->show_all;
return;
}
# Remove formatting characters
sub strippod {
my $text = shift;
$text =~ s/B<([^<]*)>/$1/gx;
$text =~ s/E/>/gx;
return $text;
}
# Update undo/redo buffers before doing something
sub take_snapshot {
# Deep copy the tied data. Otherwise, very bad things happen.
@undo_buffer = map { [@$_] } @{ $slist->{data} };
@undo_selection = $slist->get_selected_indices;
$logger->debug( Dumper( \@undo_buffer ) );
# Unghost Undo/redo
$uimanager->get_widget('/MenuBar/Edit/Undo')->set_sensitive(TRUE);
$uimanager->get_widget('/ToolBar/Undo')->set_sensitive(TRUE);
# Save session
$slist->save_session;
return;
}
# Put things back to last snapshot after updating redo buffer
sub undo {
$logger->info("Undoing");
# Deep copy the tied data. Otherwise, very bad things happen.
@redo_buffer = map { [@$_] } @{ $slist->{data} };
@redo_selection = $slist->get_selected_indices;
$logger->debug("redo_selection, undo_selection:");
$logger->debug( Dumper( \@redo_selection, \@undo_selection ) );
$logger->debug("redo_buffer, undo_buffer:");
$logger->debug( Dumper( \@redo_buffer, \@undo_buffer ) );
# Block slist signals whilst updating
$slist->get_model->signal_handler_block( $slist->{row_changed_signal} );
@{ $slist->{data} } = @undo_buffer;
# Unblock slist signals now finished
$slist->get_model->signal_handler_unblock( $slist->{row_changed_signal} );
# Reselect the pages to display the detail view
$slist->select(@undo_selection);
# Update menus/buttons
update_uimanager();
$uimanager->get_widget('/MenuBar/Edit/Undo')->set_sensitive(FALSE);
$uimanager->get_widget('/MenuBar/Edit/Redo')->set_sensitive(TRUE);
$uimanager->get_widget('/ToolBar/Undo')->set_sensitive(FALSE);
$uimanager->get_widget('/ToolBar/Redo')->set_sensitive(TRUE);
return;
}
# Put things back to last snapshot after updating redo buffer
sub unundo {
$logger->info("Redoing");
# Deep copy the tied data. Otherwise, very bad things happen.
@undo_buffer = map { [@$_] } @{ $slist->{data} };
@undo_selection = $slist->get_selected_indices;
$logger->debug("redo_selection, undo_selection:");
$logger->debug( Dumper( \@redo_selection, \@undo_selection ) );
$logger->debug("redo_buffer, undo_buffer:");
$logger->debug( Dumper( \@redo_buffer, \@undo_buffer ) );
# Block slist signals whilst updating
$slist->get_model->signal_handler_block( $slist->{row_changed_signal} );
@{ $slist->{data} } = @redo_buffer;
# Unblock slist signals now finished
$slist->get_model->signal_handler_unblock( $slist->{row_changed_signal} );
# Reselect the pages to display the detail view
$slist->select(@redo_selection);
# Update menus/buttons
update_uimanager();
$uimanager->get_widget('/MenuBar/Edit/Undo')->set_sensitive(TRUE);
$uimanager->get_widget('/MenuBar/Edit/Redo')->set_sensitive(FALSE);
$uimanager->get_widget('/ToolBar/Undo')->set_sensitive(TRUE);
$uimanager->get_widget('/ToolBar/Redo')->set_sensitive(FALSE);
return;
}
# Initialise IconFactory
sub init_icons {
my @icons = @_;
return if defined $IconFactory;
$IconFactory = Gtk2::IconFactory->new();
$IconFactory->add_default();
foreach (@icons) {
register_icon( $_->[0], $_->[1] );
}
return;
}
# Add icons
sub register_icon {
my ( $stock_id, $path ) = @_;
return unless defined $IconFactory;
my $icon;
try { $icon = Gtk2::Gdk::Pixbuf->new_from_file($path); }
catch {
$logger->warn("Unable to load icon `$path': $_");
return;
};
$IconFactory->add( $stock_id, Gtk2::IconSet->new_from_pixbuf($icon) );
return;
}
# We should clean up after ourselves so that we don't
# leave dead processes flying around.
sub kill_subs {
foreach ( keys %helperTag ) {
$logger->info("Sending TERM signal to PID $_ and its children");
killfam 'TERM', ($_);
}
return;
}
# marked page list as saved
sub mark_pages {
my @pages = @_;
$slist->get_model->signal_handler_block( $slist->{row_changed_signal} );
foreach (@pages) {
$slist->{data}[$_][2]{saved} = TRUE;
}
$slist->get_model->signal_handler_unblock( $slist->{row_changed_signal} );
return;
}
# Convert all files in temp that are not jpg, png, or tiff to png,
sub compress_temp {
return
if (
show_message_dialog(
$window, 'question',
'ok-cancel', $d->get('This operation cannot be undone. Are you sure?')
) ne 'ok'
);
@undo_buffer = ();
@undo_selection = ();
$uimanager->get_widget('/MenuBar/Edit/Undo')->set_sensitive(FALSE);
$uimanager->get_widget('/ToolBar/Undo')->set_sensitive(FALSE);
for ( @{ $slist->{data} } ) {
my ( $signal, $pid );
$pid = $slist->to_png(
page => $_->[2],
queued_callback => sub {
return update_tpbar(@_);
},
started_callback => sub {
my ( $thread, $process, $completed, $total ) = @_;
$signal = setup_tpbar( $thread, $process, $completed, $total, $pid );
return TRUE if ( defined $signal );
},
finished_callback => sub {
my ( $new_page, $pending ) = @_;
$thbox->hide_all unless $pending;
$tcbutton->signal_handler_disconnect($signal) if ( defined $signal );
},
error_callback => \&error_callback,
);
}
return;
}
# Expand tildes in the filename
sub expand_tildes {
my ($filename) = @_;
$filename =~ s{ ^ ~ ( [^/]* ) } {
$1 ? (getpwnam($1))[7] : ( $ENV{HOME} || $ENV{LOGDIR} || (getpwuid($>))[7] )
}ex;
return $filename;
}
# Preferences dialog
sub preferences { ## no critic (ProhibitExcessComplexity)
if ( defined $windowr ) {
$windowr->present;
return;
}
$windowr = Gscan2pdf::Dialog->new(
'transient-for' => $window,
title => $d->get('Preferences'),
'hide-on-delete' => TRUE,
border_width => $border_width
);
my $vbox = $windowr->get('vbox');
# Notebook for scan and general options
my $notebook = Gtk2::Notebook->new;
$vbox->pack_start( $notebook, TRUE, TRUE, 0 );
my $vbox1 = Gtk2::VBox->new;
$notebook->append_page( $vbox1, $d->get('Scan options') );
$vbox1->set_border_width($border_width);
my $cbo =
Gtk2::CheckButton->new_with_label(
$d->get('Open scan dialog at program start') );
$tooltips->set_tip(
$cbo,
$d->get(
"Automatically open the scan dialog in the background at program start. "
. "This saves time clicking the scan button and waiting for the program to find the list of scanners"
)
);
$cbo->set_active( $SETTING{'auto-open-scan-dialog'} )
if ( defined $SETTING{'auto-open-scan-dialog'} );
$vbox1->pack_start( $cbo, TRUE, TRUE, 0 );
# Frontends
my $hbox = Gtk2::HBox->new;
$vbox1->pack_start( $hbox, FALSE, FALSE, 0 );
my $label = Gtk2::Label->new( $d->get('Frontend') );
$hbox->pack_start( $label, FALSE, FALSE, 0 );
my @frontends = (
[
'libsane-perl', $d->get('libsane-perl'),
$d->get('Scan using the perl bindings for SANE.')
],
[
'scanimage', $d->get('scanimage'),
$d->get('Scan using the scanimage frontend.')
],
[
'scanimage-perl',
$d->get('scanimage-perl'),
$d->get('Scan using the scanimage-perl frontend.')
],
[
'scanadf-perl', $d->get('scanadf-perl'),
$d->get('Scan using the scanadf-perl frontend.')
],
);
push @frontends,
[
'scanadf', $d->get('scanadf'),
$d->get('Scan using the scanadf frontend.')
],
if ( $dependencies{scanadf} );
my $combob = combobox_from_array(@frontends);
my $cbcsh =
Gtk2::CheckButton->new_with_label( $d->get('Cycle SANE handle after scan') );
$hbox->pack_end( $combob, TRUE, TRUE, 0 );
$tooltips->set_tip( $hbox, $d->get("Interface used for scanner access") );
# Cycle SANE handle after scan
$cbcsh->set_active( $SETTING{'cycle sane handle'} )
if ( defined $SETTING{'cycle sane handle'} );
$vbox1->pack_start( $cbcsh, FALSE, FALSE, 0 );
# scan command prefix
my $hboxp = Gtk2::HBox->new;
$vbox1->pack_start( $hboxp, FALSE, FALSE, 0 );
$label = Gtk2::Label->new( $d->get('Scan command prefix') );
$hboxp->pack_start( $label, FALSE, FALSE, 0 );
my $preentry = Gtk2::Entry->new;
$hboxp->add($preentry);
$preentry->set_text( $SETTING{'scan prefix'} )
if defined( $SETTING{'scan prefix'} );
# Cache options?
my $cbc = Gtk2::CheckButton->new_with_label(
$d->get('Cache device-dependent options') );
$cbc->set_active(TRUE) if ( $SETTING{'cache options'} );
$vbox1->pack_start( $cbc, FALSE, FALSE, 0 );
# Clear options cache
my $buttonc =
Gtk2::Button->new( $d->get('Clear device-dependent options cache') );
$vbox1->pack_start( $buttonc, FALSE, FALSE, 0 );
$buttonc->signal_connect(
clicked => sub {
delete $SETTING{cache} if ( defined $SETTING{cache} );
$windows->set( 'options-cache', undef ) if ( defined $windows );
}
);
# Option visibility
my $oframe = Gtk2::Frame->new( $d->get('Option visibility & control') );
$vbox1->pack_start( $oframe, TRUE, TRUE, 0 );
my $vvbox = Gtk2::VBox->new;
$vvbox->set_border_width($border_width);
$oframe->add($vvbox);
my $scwin = Gtk2::ScrolledWindow->new;
$vvbox->pack_start( $scwin, TRUE, TRUE, 0 );
$scwin->set_policy(qw/never automatic/);
$option_visibility_list = Gtk2::Ex::Simple::List->new(
$d->get('Title') => 'text',
$d->get('Type') => 'text',
$d->get('Show') => 'bool',
$d->get('Reload') => 'bool'
);
$option_visibility_list->get_selection->set_mode('multiple');
$scwin->add($option_visibility_list);
my $bhbox = Gtk2::HBox->new;
$vvbox->pack_start( $bhbox, FALSE, FALSE, 0 );
my $sbutton = Gtk2::Button->new( $d->get('Show') );
$sbutton->signal_connect(
clicked => sub {
for ( $option_visibility_list->get_selected_indices ) {
$option_visibility_list->{data}[$_][2] = TRUE;
}
}
);
$bhbox->pack_start( $sbutton, TRUE, TRUE, 0 );
my $hbutton = Gtk2::Button->new( $d->get('Hide') );
$hbutton->signal_connect(
clicked => sub {
for ( $option_visibility_list->get_selected_indices ) {
$option_visibility_list->{data}[$_][2] = FALSE;
}
}
);
$bhbox->pack_start( $hbutton, TRUE, TRUE, 0 );
my $fbutton = Gtk2::Button->new( $d->get('List current optionts') );
$fbutton->signal_connect(
clicked => sub {
if ( defined $windows ) {
@{ $option_visibility_list->{data} } = ();
my $options = $windows->get('available-scan-options');
for ( my $i = 1 ; $i < $options->num_options ; ++$i ) {
my $opt = $options->by_index($i);
push @{ $option_visibility_list->{data} },
[ $opt->{title}, $opt->{type}, TRUE, FALSE ];
}
push @{ $option_visibility_list->{data} },
[ 'Paper size', undef, TRUE, FALSE ];
}
else {
show_message_dialog( $windowr, 'error',
'close',
$d->get('No scanner currently open with command line frontend.') );
}
return;
}
);
$bhbox->pack_start( $fbutton, TRUE, TRUE, 0 );
my $show_not_listed =
Gtk2::CheckButton->new_with_label( $d->get('Show options not listed') );
$vvbox->pack_start( $show_not_listed, FALSE, FALSE, 0 );
# fill the list
if ( defined $SETTING{'visible-scan-options'} ) {
my %reload;
$SETTING{'scan-reload-triggers'} = [ $SETTING{'scan-reload-triggers'} ]
if ( ref( $SETTING{'scan-reload-triggers'} ) ne 'ARRAY' );
for ( @{ $SETTING{'scan-reload-triggers'} } ) {
$reload{$_} = 1;
}
for ( sort { $a cmp $b } keys %{ $SETTING{'visible-scan-options'} } ) {
push @{ $option_visibility_list->{data} },
[ $_, undef, $SETTING{'visible-scan-options'}{$_},
defined( $reload{$_} ) ];
}
}
$combob->signal_connect(
changed => sub {
if ( $frontends[ $combob->get_active ][0] eq 'libsane-perl' ) {
$cbcsh->set_sensitive(TRUE);
$hboxp->set_sensitive(FALSE);
$cbc->set_sensitive(FALSE);
$buttonc->set_sensitive(FALSE);
$oframe->set_sensitive(FALSE);
}
else {
$cbcsh->set_sensitive(FALSE);
$hboxp->set_sensitive(TRUE);
$cbc->set_sensitive(TRUE);
$buttonc->set_sensitive(TRUE);
$oframe->set_sensitive(TRUE);
}
}
);
combobox_set_active( $combob, $SETTING{frontend}, @frontends );
my $vbox2 = Gtk2::VBox->new;
$notebook->append_page( $vbox2, $d->get('General options') );
$vbox2->set_border_width($border_width);
# Restore window setting
my $cbw = Gtk2::CheckButton->new_with_label(
$d->get('Restore window settings on startup') );
$cbw->set_active(TRUE) if ( $SETTING{'restore window'} );
$vbox2->pack_start( $cbw, TRUE, TRUE, 0 );
# View saved files
my $cbv = Gtk2::CheckButton->new_with_label( $d->get('View files on saving') );
$cbv->set_active( $SETTING{'view files toggle'} )
if ( defined $SETTING{'view files toggle'} );
$vbox2->pack_start( $cbv, TRUE, TRUE, 0 );
# Default filename
$hbox = Gtk2::HBox->new;
$vbox2->pack_start( $hbox, TRUE, TRUE, 0 );
$label = Gtk2::Label->new( $d->get('Default filename for PDFs') );
$hbox->pack_start( $label, FALSE, FALSE, 0 );
my $fileentry = Gtk2::Entry->new;
$tooltips->set_tip(
$fileentry,
$d->get(
"\%a\t author\n\%t\t title\n\%y\t document's year\n\%Y\t today's year\n\%m\t document's month\n\%M\t today's month\n\%d\t document's day\n\%D\t today's day"
)
);
$hbox->add($fileentry);
$fileentry->set_text( $SETTING{'default filename'} )
if defined( $SETTING{'default filename'} );
# Temporary directory settings
$hbox = Gtk2::HBox->new;
$vbox2->pack_start( $hbox, TRUE, TRUE, 0 );
$label = Gtk2::Label->new( $d->get('Temporary directory') );
$hbox->pack_start( $label, FALSE, FALSE, 0 );
my $tmpentry = Gtk2::Entry->new;
$hbox->add($tmpentry);
$tmpentry->set_text( dirname($session) );
my $button = Gtk2::Button->new( $d->get('Browse') );
$button->signal_connect(
clicked => sub {
my $file_chooser = Gtk2::FileChooserDialog->new(
$d->get('Select temporary directory'),
$windowr, 'select-folder',
'gtk-cancel' => 'cancel',
'gtk-ok' => 'ok'
);
$file_chooser->set_current_folder( $tmpentry->get_text );
if ( 'ok' eq $file_chooser->run ) {
$tmpentry->set_text( $file_chooser->get_filename );
}
$file_chooser->destroy;
}
);
$hbox->pack_end( $button, TRUE, TRUE, 0 );
# Blank page standard deviation threshold
$hbox = Gtk2::HBox->new;
$vbox2->pack_start( $hbox, TRUE, TRUE, 0 );
$label = Gtk2::Label->new( $d->get('Blank threshold') );
$hbox->pack_start( $label, FALSE, FALSE, 0 );
my $spinbuttonb = Gtk2::SpinButton->new_with_range( 0, 1, 0.001 );
$spinbuttonb->set_value( $SETTING{'Blank threshold'} );
$tooltips->set_tip( $spinbuttonb,
$d->get('Threshold used for selecting blank pages') );
$hbox->add($spinbuttonb);
# Dark page mean threshold
$hbox = Gtk2::HBox->new;
$vbox2->pack_start( $hbox, TRUE, TRUE, 0 );
$label = Gtk2::Label->new( $d->get('Dark threshold') );
$hbox->pack_start( $label, FALSE, FALSE, 0 );
my $spinbuttond = Gtk2::SpinButton->new_with_range( 0, 1, 0.01 );
$spinbuttond->set_value( $SETTING{'Dark threshold'} );
$tooltips->set_tip( $spinbuttond,
$d->get('Threshold used for selecting dark pages') );
$hbox->add($spinbuttond);
# OCR output
$hbox = Gtk2::HBox->new;
$vbox2->pack_start( $hbox, TRUE, TRUE, 0 );
$label = Gtk2::Label->new( $d->get('OCR output') );
$hbox->pack_start( $label, FALSE, FALSE, 0 );
my @array = (
[
'replace',
$d->get('Replace'),
$d->get(
'Replace the contents of the text buffer with that from the OCR output.')
],
[
'prepend', $d->get('Prepend'),
$d->get('Prepend the OCR output to the text buffer.')
],
[
'append', $d->get('Append'),
$d->get('Append the OCR output to the text buffer.')
],
);
my $comboo = combobox_from_array(@array);
combobox_set_active( $comboo, $SETTING{'OCR output'}, @array );
$hbox->pack_end( $comboo, TRUE, TRUE, 0 );
# User-defined tools
my $frame = Gtk2::Frame->new( $d->get('User-defined tools') );
$vbox2->pack_start( $frame, TRUE, TRUE, 0 );
my $vboxt = Gtk2::VBox->new;
$vboxt->set_border_width($border_width);
$frame->add($vboxt);
for my $tool (@user_defined_tools) {
add_user_defined_tool_entry( $vboxt, $tool );
}
my $abutton = Gtk2::Button->new_from_stock('gtk-add');
$vboxt->pack_start( $abutton, TRUE, TRUE, 0 );
$abutton->signal_connect(
clicked => sub {
my %tool = ( cmd => 'my-tool %i %o' );
add_user_defined_tool_menu( \%tool );
add_user_defined_tool_entry( $vboxt, \%tool );
$vboxt->reorder_child( $abutton, -1 );
$SETTING{user_defined_tools} = list_user_defined_tools($vboxt);
}
);
# Apply button
$hbox = _hbox_with_apply_cancel_buttons(
sub {
$windowr->hide;
if ( $SETTING{frontend} ne $frontends[ $combob->get_active ][0] ) {
$SETTING{frontend} = $frontends[ $combob->get_active ][0];
$windows->hide;
undef $windows;
}
else {
$SETTING{'visible-scan-options'} = ();
$SETTING{'scan-reload-triggers'} = ();
for ( @{ $option_visibility_list->{data} } ) {
$SETTING{'visible-scan-options'}{ $_->[0] } = $_->[2];
push @{ $SETTING{'scan-reload-triggers'} }, $_->[0] if ( $_->[3] );
}
if ( $SETTING{frontend} ne 'libsane-perl' ) {
$windows->set( 'visible-scan-options', $SETTING{'visible-scan-options'} );
$windows->set( 'reload-triggers', $SETTING{'scan-reload-triggers'} );
$SETTING{'scan prefix'} = $preentry->get_text;
$SETTING{'cache options'} = $cbc->get_active;
if ( defined $windows ) {
$windows->set( 'prefix', $SETTING{'scan prefix'} );
$windows->set( 'cache-options', $SETTING{'cache options'} );
}
delete $SETTING{cache}
if ( defined $SETTING{cache} and not $SETTING{'cache options'} );
}
}
$SETTING{'auto-open-scan-dialog'} = $cbo->get_active;
$SETTING{'cycle sane handle'} = $cbcsh->get_active;
$SETTING{'default filename'} = $fileentry->get_text;
$SETTING{'restore window'} = $cbw->get_active;
my @tmpdirs = File::Spec->splitdir($session);
pop @tmpdirs; # Remove the top level
my $tmp = File::Spec->catdir(@tmpdirs);
# Expand tildes in the filename
my $newdir = expand_tildes( $tmpentry->get_text );
if ( $newdir ne $tmp ) {
$SETTING{TMPDIR} = $newdir;
show_message_dialog(
$window,
'warning',
'close',
$d->get(
'You will have to restart gscanp2df for changes to the temporary directory to take effect.'
)
);
}
$SETTING{'Blank threshold'} = $spinbuttonb->get_value;
$SETTING{'Dark threshold'} = $spinbuttond->get_value;
$SETTING{'OCR output'} = $array[ $comboo->get_active ][0];
# Store viewer preferences
$SETTING{'view files toggle'} = $cbv->get_active;
},
sub {
$windowr->hide;
}
);
$vbox->pack_start( $hbox, FALSE, FALSE, 0 );
$windowr->show_all;
return;
}
sub _hbox_with_apply_cancel_buttons {
my ( $apply_callback, $cancel_callback ) = @_;
my $hbox = Gtk2::HBox->new;
# Apply button
my $button = Gtk2::Button->new_from_stock('gtk-apply');
$hbox->pack_start( $button, TRUE, TRUE, 0 );
$button->signal_connect( clicked => $apply_callback );
# Cancel button
$button = Gtk2::Button->new_from_stock('gtk-cancel');
$hbox->pack_end( $button, TRUE, TRUE, 0 );
$button->signal_connect( clicked => $cancel_callback );
return $hbox;
}
# Return list of user-defined tools
sub list_user_defined_tools {
my ($vbox) = @_;
my @list;
for my $hbox ( $vbox->get_children ) {
if ( $hbox->isa('Gtk2::HBox') ) {
for my $widget ( $hbox->get_children ) {
push @list, $widget->get_text if ( $widget->isa('Gtk2::Entry') );
}
}
}
return \@list;
}
# Add user-defined tool menu item
sub add_user_defined_tool_menu {
my ($tool) = @_;
my $action_group = Gtk2::ActionGroup->new("actions");
$tool->{name} = "$action_group";
my $tool_ui = <<"EOS";
EOS
# add the basic XML description of the GUI
$tool->{merge_id} = $uimanager->add_ui_from_string($tool_ui);
my @action_item = (
# Fields for each action item:
# [name, stock_id, value, label, accelerator, tooltip, callback]
[ $tool->{name}, undef, $tool->{cmd}, undef, undef, \&user_defined_tool ],
);
$action_group->add_actions( \@action_item, undef );
# Add the actiongroup to the uimanager
$uimanager->insert_action_group( $action_group, 0 );
$tool->{action_group} = $action_group;
return;
}
# Add user-defined tool entry
sub add_user_defined_tool_entry {
my ( $vbox, $tool ) = @_;
my $hbox = Gtk2::HBox->new;
$vbox->pack_start( $hbox, TRUE, TRUE, 0 );
my $entry = Gtk2::Entry->new;
$entry->set_text( $tool->{cmd} );
$entry->signal_connect(
changed => sub {
my $action = $tool->{action_group}->get_action( $tool->{name} );
$action->set( 'label', $entry->get_text );
$SETTING{user_defined_tools} = list_user_defined_tools($vbox);
() # this callback must return either 2 or 0 items.
}
);
$tooltips->set_tip(
$entry,
$d->get(
"Use \%i and \%o for the input and output filenames respectively, or a single \%i if the image is to be modified in-place.\n\nThe other variable available is:\n\n\%r resolution"
)
);
$hbox->pack_start( $entry, TRUE, TRUE, 0 );
my $button = Gtk2::Button->new;
$button->set_image( Gtk2::Image->new_from_stock( 'gtk-delete', 'button' ) );
$button->signal_connect(
clicked => sub {
$uimanager->remove_ui( $tool->{merge_id} );
$hbox->destroy;
$SETTING{user_defined_tools} = list_user_defined_tools($vbox);
}
);
$hbox->pack_end( $button, FALSE, FALSE, 0 );
$hbox->show_all;
return;
}
sub properties {
if ( defined $windowp ) {
$windowp->present;
return;
}
$windowp = Gscan2pdf::Dialog->new(
'transient-for' => $window,
title => $d->get('Properties'),
'hide-on-delete' => TRUE,
border_width => $border_width
);
my $vbox = $windowp->get('vbox');
my $hbox = Gtk2::HBox->new;
$vbox->pack_start( $hbox, TRUE, TRUE, 0 );
my $label = Gtk2::Label->new( $d->get('Resolution') );
$hbox->pack_start( $label, FALSE, FALSE, 0 );
my $entry = Gtk2::Entry->new;
$entry->set_width_chars(4);
$entry->set_activates_default(TRUE);
$entry->signal_connect(
'insert-text' => sub {
my ( $widget, $string, $len, $position ) = @_;
# only allow a valid positive real number
for ( split '', $string ) {
if (( $_ ne '.' and ( $_ lt '0' or $_ gt '9' ) )
or ( $_ eq '.' and $entry->get_text =~ /\./ ) )
{
$entry->signal_stop_emission_by_name('insert-text');
last;
}
}
() # this callback must return either 2 or 0 items.
}
);
$entry->set_text( get_selected_properties() );
$slist->get_selection->signal_connect(
changed => sub {
$entry->set_text( get_selected_properties() );
}
);
$hbox->pack_end( $entry, TRUE, TRUE, 0 );
$hbox = Gtk2::HBox->new;
$vbox->pack_start( $hbox, TRUE, TRUE, 0 );
# Apply button
my $button = Gtk2::Button->new_from_stock('gtk-apply');
$button->can_default(TRUE);
$windowp->set_default($button);
$hbox->pack_start( $button, TRUE, TRUE, 0 );
$button->signal_connect(
clicked => sub {
$windowp->hide;
my $resolution = $entry->get_text;
$slist->get_model->signal_handler_block( $slist->{row_changed_signal} );
for ( $slist->get_selected_indices ) {
$slist->{data}[$_][2]{resolution} = $resolution;
}
$slist->get_model->signal_handler_unblock( $slist->{row_changed_signal} );
}
);
# Cancel button
$button = Gtk2::Button->new_from_stock('gtk-cancel');
$hbox->pack_end( $button, TRUE, TRUE, 0 );
$button->signal_connect(
clicked => sub {
$windowp->hide;
}
);
$windowp->show_all;
return;
}
# Helper function for properties()
sub get_selected_properties {
my @page = $slist->get_selected_indices;
my $resolution = '';
$resolution = $slist->{data}[ shift @page ][2]{resolution} if ( @page > 0 );
for (@page) {
if ( $slist->{data}[$_][2]{resolution} != $resolution ) {
$resolution = '';
last;
}
}
# round the value to a sensible number of significant figures
return $resolution eq '' ? '' : sprintf( "%g", $resolution );
}
# Helper function to display a message dialog, wait for a response, and return it
sub show_message_dialog {
my ( $parent, $type, $buttons, $text ) = @_;
my $dialog =
Gtk2::MessageDialog->new( $parent, 'destroy-with-parent', $type, $buttons,
$text );
my $response = $dialog->run;
$dialog->destroy;
return $response;
}
Gtk2->main;
__END__
=encoding utf8
=head1 Name
gscan2pdf - A GUI to produce PDFs or DjVus from scanned documents
=for html
Screenshot: Main page v0.9.30
=head1 Synopsis
=over
=item 1. Scan one or several pages in with File/Scan
=item 2. Create PDF of selected pages with File/Save
=back
=head1 Description
gscan2pdf has the following command-line options:
=over
=item --device=
Specifies the device to use, instead of getting the list of devices from via the SANE API.
This can be useful if the scanner is on a remote computer which is not broadcasting its existence.
=item --help
Displays this help page and exits.
=item --log=
Specifies a file to store logging messages.
=item --(debug|info|warn|error|fatal)
Defines the log level. If a log file is specified, this defaults to 'debug', otherwise 'warn'.
=item --version
Displays the program version and exits.
=back
Scanning is handled with SANE via scanimage.
PDF conversion is done by PDF::API2.
TIFF export is handled by libtiff (faster and smaller memory footprint for
multipage files).
=head1 Download
gscan2pdf is available on Sourceforge
(L).
=head2 Debian-based
If you are using Debian, you should find that sid has the latest version already
packaged.
If you are using a Ubuntu-based system, you can automatically keep up to date
with the latest version via the ppa:
C
If you are you are using Synaptic, then use menu
I, search for gscan2pdf in the package list,
and lo and behold, you can install the nice shiny new version.
From the command line:
C
C
=head2 RPMs
Download the rpm from Sourceforge, and then install it with
C
=head2 From source
The source is hosted in the files section of the gscan2pdf project on
Sourceforge (L).
=head2 From the repository
gscan2pdf uses Git for its Revision Control System. You can browse the
tree at L.
Git users can clone the complete tree with
C
=head1 Building gscan2pdf from source
Having downloaded the source either from a Sourceforge file release, or from the
Git repository, unpack it if necessary with
C
C, will create the Makefile.
There is a C, but this is not machine-dependent, and therefore really
just for my benefit to make sure I haven't broken the device-dependent options
parsing routine.
You can install directly from the source with C, but building the
appropriate package for your distribution should be as straightforward as
C or C. However, you will
additionally need the rpm, devscripts, fakeroot, debhelper and gettext packages.
=head1 Dependencies
The list below looks daunting, but all packages are available from any
reasonable up-to-date distribution. If you are using Synaptic, having installed
gscan2pdf, locate the gscan2pdf entry in Synaptic, right-click it and you can
install them under I. Note also that the library names given below
are the Debian/Ubuntu ones. Those distributions using RPM typically use
perl(module) where Debian has libmodule-perl.
=over
=item Required
=over
=item libgtk2.0-0 (>= 2.4)
The GTK+ graphical user interface library.
=item libglib-perl (>= 1.100-1)
Perl interface to the GLib and GObject libraries
=item libgtk2-perl (>= 1:1.043-1)
Perl interface to the 2.x series of the Gimp Toolkit library
=item libgtk2-imageview-perl
Perl bindings to the gtkimageview widget.
See L
=item libgtk2-ex-simple-list-perl
A simple interface to Gtk2's complex MVC list widget
=item liblocale-gettext-perl (>= 1.05)
Using libc functions for internationalization in Perl
=item libpdf-api2-perl
provides the functions for creating PDF documents in Perl
=item libsane
API library for scanners
=item libsane-perl
Perl bindings for libsane.
=item libset-intspan-perl
manages sets of integers
=item libtiff-tools
TIFF manipulation and conversion tools
=item Imagemagick
Image manipulation programs
=item perlmagick
A perl interface to the libMagick graphics routines
=item sane-utils
API library for scanners -- utilities.
=back
=item Optional
=over
=item sane
scanner graphical frontends. Only required for the scanadf frontend.
=item libgtk2-ex-podviewer-perl
Perl Gtk2 widget for displaying Plain Old Documentation (POD). Not required if
you don't need the gscan2pdf documentation (which is anyway repeated on the
website).
=item unpaper
post-processing tool for scanned pages. See L.
=item xdg-utils
Desktop integration utilities from freedesktop.org. Required for Email as PDF.
See L
=item djvulibre-bin
Utilities for the DjVu image format. See L
=item gocr
A command line OCR. See L.
=item tesseract
A command line OCR. See L
=item ocropus
A command line OCR. See L
=item cuneiform
A command line OCR. See L
=back
=back
=head1 Support
There are two mailing lists for gscan2pdf:
=over
=item gscan2pdf-announce
A low-traffic list for announcements, mostly of new releases. You can subscribe
at L
=item gscan2pdf-help
General support, questions, etc.. You can subscribe at
L
=back
=head1 Reporting bugs
Before reporting bugs, please read the L<"FAQs"> section.
Please report any bugs found, preferably against the Debian package[1][2].
You do not need to be a Debian user, or set up an account to do this.
=over
=item 1. http://packages.debian.org/sid/gscan2pdf
=item 2. http://www.debian.org/Bugs/
=back
Alternatively, there is a bug tracker for the gscan2pdf project on
Sourceforge (L).
Please include the log file created by C with any new bug report.
=head1 Translations
gscan2pdf has already been partly translated several languages.
If you would like to contribute to an existing or new translation, please check
out Rosetta: L
Note that the translations for the scanner options are taken
directly from sane-backends. If you would like to contribute to these, you can
do so either at contact the sane-devel mailing list
(sane-devel@lists.alioth.debian.org) and have a look at the po/ directory in
the source code L.
Alternatively, Ubuntu has its own translation project. For the 9.04 release, the
translations are available at
L
=head1 Menus
=head2 File
=head3 New
Clears the page list.
=head3 Open
Opens any format that imagemagick supports. PDFs will have their embedded
images extracted and imported one per page.
=head3 Scan
Sets options before scanning via SANE.
=head4 Device
Chooses between available scanners.
=head4 # Pages
Selects the number of pages, or all pages to scan.
=head4 Source document
Selects between single sided or double sides pages.
This affects the page numbering.
Single sided scans are numbered consecutively.
Double sided scans are incremented (or decremented, see below) by 2, i.e. 1, 3,
5, etc..
=head4 Side to scan
If double sided is selected above, assuming a non-duplex scanner, i.e. a
scanner that cannot automatically scan both sides of a page, this determines
whether the page number is incremented or decremented by 2.
To scan both sides of three pages, i.e. 6 sides:
=over
=item 1. Select:
# Pages = 3 (or "all" if your scanner can detect when it is out of paper)
Double sided
Facing side
=item 2. Scans sides 1, 3 & 5.
=item 3. Put pile back with scanner ready to scan back of last page.
=item 4. Select:
# Pages = 3 (or "all" if your scanner can detect when it is out of paper)
Double sided
Reverse side
=item 5. Scans sides 6, 4 & 2.
=item 6. gscan2pdf automatically sorts the pages so that they appear in the
correct order.
=back
=head4 Device-dependent options
These, naturally, depend on your scanner.
They can include
=over
=item Page size.
=item Mode (colour/black & white/greyscale)
=item Resolution (in PPI)
=item Batch-scan
Guarantees that a "no documents" condition will be returned after the last
scanned page, to prevent endless flatbed scans after a batch scan.
=item Wait-for-button/Button-wait
After sending the scan command, wait until the button on the scanner is pressed
before actually starting the scan process.
=item Source
Selects the document source.
Possible options can include Flatbed or ADF.
On some scanners, this is the only way of generating an out-of-documents signal.
=back
=head3 Save
Saves the selected or all pages as a PDF, DjVu, TIFF, PNG, JPEG, PNM or
GIF.
=head4 PDF Metadata
Metadata are information that are not visible when viewing the PDF, but are
embedded in the file and so searchable and can be examined, typically with the
"Properties" option of the PDF viewer.
The metadata are completely optional, but can also be used to generate the
filename see preferences for details.
=head4 DjVu
Both black and white, and colour images produce better
compression than PDF. See L for more details.
=head3 Email as PDF
Attaches the selected or all pages as a PDF to a blank email.
This requires xdg-email, which is in the xdg-utils package.
If this is not present, the option is ghosted out.
=head3 Print
Prints the selected or all pages.
=head3 Compress temporary files
If your temporary ($TMPDIR) directory is getting full, this function can be useful -
compressing all images at LZW-compressed TIFFs. These require much less space than
the PNM files that are typically produced by SANE or by importing a PDF.
=head2 Edit
=head3 Delete
Deletes the selected page.
=head3 Renumber
Renumbers the pages from 1..n.
Note that the page order can also be changed by drag and drop in the thumbnail
view.
=head3 Select
The select menus can be used to select, all, even, odd, blank, dark or modified
pages. Selecting blank or dark pages runs imagemagick to make the decision.
Selecting modified pages selects those which have modified by threshold,
unsharp, etc., since the last OCR run was made.
=head3 Preferences
The preferences menu item allows the control of the default behviour of various
functions. Most of these are self-explanatory.
=head4 Frontend
gscan2pdf supports two frontends, scanimage and scanadf.
scanadf support was added when it was realised that scanadf works better than
scanimage with some scanners. On Debian-based systems, scanadf is in the sane package,
not, like scanimage, in sane-utils. If scanadf is not present, the option is
obviously ghosted out.
In 0.9.27, Perl bindings for SANE were introduced and two further frontends,
scanimage-perl and scanadf-perl (scanimage and scanadf transliterated from C into
Perl) were added.
Before 1.2.0, options available through CLI frontends like scanimage were made
visible as users asked for them. In 1.2.0, all options can be shown or hidden
via Edit/Preferences, along with the ability to specify which options trigger a
reload.
=head4 Default filename for PDF files
The following variables are available, which are replaced by the corresponding
metadata:
%a author
%t title
%y document's year
%Y today's year
%m document's month
%M today's month
%d document's day
%D today's day
=head2 View
=head3 Zoom 100%
Zooms to 1:1. How this appears depends on the desktop resolution.
=head3 Zoom to fit
Scales the view such that all the page is visible.
=head3 Zoom in
=head3 Zoom out
=head3 Rotate 90 clockwise
The rotate options require the package imagemagick and, if this is not present,
are ghosted out.
=head3 Rotate 180
=head3 Rotate 90 anticlockwise
=head2 Tools
=head3 Threshold
Changes all pixels darker than the given value to black; all others become
white.
=head3 Unsharp mask
The unsharp option sharpens an image. The image is convolved with a Gaussian
operator of the given radius and standard deviation (sigma). For reasonable
results, radius should be larger than sigma. Use a radius of 0 to have the
method select a suitable radius.
=head3 Crop
=head3 unpaper
unpaper (see L) is a utility for cleaning up a scan.
=head3 OCR (Optical Character Recognition)
The gocr, tesseract, ocropus or cuneiform utilities are used to produce text from
an image.
There is an OCR output buffer for each page and is embedded as
plain text behind the scanned image in the PDF
produced. This way, Beagle can index (i.e. search) the plain text.
In DjVu files, the OCR output buffer is embedded in the hidden text layer.
Thus these can also be indexed by Beagle.
There is an interesting review of OCR software at
L.
An important conclusion was that 400ppi is necessary for decent results.
Up to v2.04, the only way to tell which languages were available to tesseract
was to look for the language files. Therefore, gscan2pdf checks the path
returned by:
tesseract '' '' -l ''
If there are no language files in the above location, then gscan2pdf
assumes that tesseract v1.0 is installed, which had no language files.
=head3 Variables for user-defined tools
The following variables are available:
%i input filename
%o output filename
%r resolution
An image can be modified in-place by just specifying %i.
=head1 FAQs
=head2 Why isn't option xyz available in the scan window?
Possibly because SANE or your scanner doesn't support it.
If an option listed in the output of C that you would like to
use isn't available, send me the output and I will look at implementing it.
=head2 I've only got an old flatbed scanner with no automatic sheetfeeder.
How do I scan a multipage document?
If you are lucky, you have an option like Wait-for-button or Button-wait, where
the scanner will wait for you to press the scan button on the device before it
starts the scan, allowing you to scan multiple pages without touching the
computer.
Otherwise, you have to set the number of pages to scan to 1 and hit the scan
button on the scan window for each page.
=head2 Why is option xyz ghosted out?
Probably because the package required for that option is not installed.
Email as PDF requires xdg-email (xdg-utils), unpaper and the rotate options
require imagemagick.
=head2 Why can I not scan from the flatbed of my HP scanner?
Generally for HP scanners with an ADF, to scan from the flatbed, you should
set "# Pages" to "1", and possibly "Batch scan" to "No".
=head2 When I update gscan2pdf using the Update Manager in Ubuntu, why is the list of changes never displayed?
As far as I can tell, this is pulled from changelogs.ubuntu.com, and therefore
only the changelogs from official Ubuntu builds are displayed.
=head2 Why can gscan2pdf not find my scanner?
If your scanner is not connected directly to the machine on which you are
running gscan2pdf and you have not installed the SANE daemon, saned,
gscan2pdf cannot automatically find it. In this case, you can specify the
scanner device on the command line:
C>
=head2 How can I search for text in the OCR layer of the finished PDF or DJVU file?
pdftotext or djvutxt can extract the text layer from PDF or DJVU files. See the
respective man pages for details.
Having opened a PDF or DJVU file in evince or Acrobat Reader, the search
function will typically find the page with the requested text and highlight it.
There are various tools for searching or indexing files, including PDF and DJVU:
=over
=item *
(meta) Tracker (L)
=item *
plone (L)
=item *
pdfgrep (L
=item *
swish-e (L)
=item *
recoll (L)
=item *
terrier (L)
=back
=head1 See Also
Xsane
http://scantailor.sourceforge.net/
=head1 Author
Jeffrey Ratcliffe (ra28145 at users dot sf dot net)
=head1 Thanks to
=over
=item *
all the people who have sent patches, translations, bugs and feedback.
=item *
the GTK2 project for a most excellent graphics toolkit.
=item *
the Gtk2-Perl project for their superb Perl bindings for GTK2.
=item *
The SANE project for scanner access
=item *
Björn Lindqvist for the gtkimageview widget
=item *
Sourceforge for hosting the project.
=back
=for html
=cut
gscan2pdf-1.2.3/bin/scanimage-perl 0000755 0001750 0001750 00000144711 12107507061 015366 0 ustar jeff jeff #!/usr/bin/perl
use warnings;
use strict;
use feature "switch";
use Sane;
use Getopt::Long qw(:config no_ignore_case pass_through);
use File::Basename;
use IO::Handle;
#$Sane::DEBUG = 1;
my (
%options, @window_val_user, @window_option, @window_val,
@window, $num_dev_options, $device, $format,
$devname, %option_number, $batch_count,
);
my $verbose = 0;
my $help = 0;
my $all = 0;
my $test = 0;
my $batch = 0;
my $batch_start_at = 1;
my $batch_increment = 1;
my $buffer_size = ( 32 * 1024 ); # default size
my $tl_x = 0;
my $tl_y = 0;
my $br_x = 0;
my $br_y = 0;
my $resolution_optind = -1;
my $resolution_value = 0;
my $progress = 0;
my $batch_double = 0;
my $batch_prompt = 0;
my $dont_scan = 0;
my $prog_name = basename($0);
my @args = (
\%options,
'd|device-name=s' => \$devname,
'L|list-devices',
'f|formatted-device-list=s',
'b|batch:s' => \$format,
'batch-start=i' => \$batch_start_at,
'batch-count=i' => \$batch_count,
'batch-increment=i' => \$batch_increment,
'batch-double' => \$batch_double,
'batch-prompt' => \$batch_prompt,
'p|progress' => \$progress,
'n|dont-scan' => \$dont_scan,
'T|test' => \$test,
'A|all-options' => \$all,
'h|help' => \$help,
'v|verbose+' => \$verbose,
'B|buffer-size=i' => \$buffer_size,
'V|version'
);
sub sighandler {
my $signum = shift;
my $first_time = SANE_TRUE;
if ($device) {
print STDERR "$prog_name: received signal $signum\n";
if ($first_time) {
$first_time = SANE_FALSE;
print STDERR "$prog_name: trying to stop scanner\n";
$device->cancel;
}
else {
print STDERR "$prog_name: aborting\n";
_exit(0);
}
}
return;
}
sub print_unit {
my ($unit) = @_;
given ($unit) {
when (SANE_UNIT_PIXEL) {
print "pel";
}
when (SANE_UNIT_BIT) {
print "bit";
}
when (SANE_UNIT_MM) {
print "mm";
}
when (SANE_UNIT_DPI) {
print "dpi";
}
when (SANE_UNIT_PERCENT) {
print "%";
}
when (SANE_UNIT_MICROSECOND) {
print "us";
}
}
return;
}
sub print_option {
( $device, my $opt_num, my $opt, my $ro ) = @_;
if ( $opt->{type} == SANE_TYPE_GROUP ) {
printf( " %s:\n", $opt->{title} );
return;
}
# if both of these are set, option is invalid
if ( $opt->{cap} & SANE_CAP_SOFT_SELECT
and $opt->{cap} & SANE_CAP_HARD_SELECT )
{
print STDERR "$prog_name: invalid option caps, SS+HS\n";
return;
}
# invalid to select but not detect
if ( $opt->{cap} & SANE_CAP_SOFT_SELECT
and not( $opt->{cap} & SANE_CAP_SOFT_DETECT ) )
{
print STDERR "$prog_name: invalid option caps, SS!SD\n";
return;
}
# standard allows this, though it makes little sense
# if($opt->{cap} & SANE_CAP_HARD_SELECT and !($opt->{cap} & SANE_CAP_SOFT_DETECT)){
# print STDERR "$prog_name: invalid option caps, HS!SD\n";
# return;
# }
# if one of these three is not set, option is useless, skip it
if (
not( $opt->{cap} &
( SANE_CAP_SOFT_SELECT | SANE_CAP_HARD_SELECT | SANE_CAP_SOFT_DETECT ) )
)
{
return;
}
# print the option
if ( $opt->{name} =~ /^(?:x|y|t|l)$/x ) {
printf " -%s", $opt->{name};
}
else {
printf " --%s", $opt->{name};
}
print_option_choices($opt);
print_current_option_value( $opt, $opt_num );
if ( $opt->{cap} & SANE_CAP_INACTIVE ) {
print " [inactive]";
}
elsif ( $opt->{cap} & SANE_CAP_HARD_SELECT ) {
print " [hardware]";
}
elsif ( not( $opt->{cap} & SANE_CAP_SOFT_SELECT )
and $opt->{cap} & SANE_CAP_SOFT_DETECT )
{
print " [read-only]";
}
print "\n ";
my $column = 8;
my $last_break = 0;
my $start = 0;
for ( my $pos = 0 ; $pos < length( $opt->{desc} ) ; ++$pos ) {
++$column;
if ( substr( $opt->{desc}, $pos, 1 ) eq ' ' ) {
$last_break = $pos;
}
elsif ( substr( $opt->{desc}, $pos, 1 ) eq "\n" ) {
$column = 80;
$last_break = $pos;
}
if ( $column >= 79 and $last_break ) {
print substr( $opt->{desc}, $start++, 1 ) while ( $start < $last_break );
$start = $last_break + 1; # skip blank
print "\n ";
$column = 8 + $pos - $start;
}
}
print substr( $opt->{desc}, $start++, 1 )
while ( $start < length( $opt->{desc} ) );
print "\n";
return;
}
sub print_option_choices { ## no critic (ProhibitExcessComplexity)
my ($opt) = @_;
if ( $opt->{type} == SANE_TYPE_BOOL ) {
print "[=(";
print "auto|" if ( $opt->{cap} & SANE_CAP_AUTOMATIC );
print "yes|no)]";
}
elsif ( $opt->{type} != SANE_TYPE_BUTTON ) {
print ' ';
if ( $opt->{cap} & SANE_CAP_AUTOMATIC ) {
print "auto|";
}
if ( $opt->{constraint_type} == SANE_CONSTRAINT_NONE ) {
if ( $opt->{type} == SANE_TYPE_INT ) {
print "";
}
elsif ( $opt->{type} == SANE_TYPE_FIXED ) {
print "";
}
elsif ( $opt->{type} == SANE_TYPE_STRING ) {
print "";
}
print ",..." if ( $opt->{max_values} > 1 );
}
elsif ( $opt->{constraint_type} == SANE_CONSTRAINT_RANGE ) {
my $string_format = "%g..%g";
$string_format = "%d..%d" if ( $opt->{type} == SANE_TYPE_INT );
if ( $opt->{name} eq "x" ) {
printf $string_format, $opt->{constraint}{min},
$opt->{constraint}{max} - $tl_x;
}
elsif ( $opt->{name} eq "y" ) {
printf $string_format, $opt->{constraint}{min},
$opt->{constraint}{max} - $tl_y;
}
else {
printf $string_format, $opt->{constraint}{min}, $opt->{constraint}{max};
}
print_unit( $opt->{unit} );
print ",..." if ( $opt->{max_values} > 1 );
print " (in steps of $opt->{constraint}{quant})"
if ( $opt->{constraint}{quant} );
}
elsif ( $opt->{constraint_type} == SANE_CONSTRAINT_STRING_LIST
or $opt->{constraint_type} == SANE_CONSTRAINT_WORD_LIST )
{
for ( my $i = 0 ; $i < @{ $opt->{constraint} } ; ++$i ) {
print '|' if ( $i > 0 );
my $string_format = $opt->{type} == SANE_TYPE_FIXED ? '%g' : '%s';
printf $string_format, $opt->{constraint}[$i];
}
if ( $opt->{constraint_type} == SANE_CONSTRAINT_WORD_LIST ) {
print_unit( $opt->{unit} );
print ",..." if ( $opt->{max_values} > 1 );
}
}
}
return;
}
sub print_current_option_value {
my ( $opt, $opt_num ) = @_;
if ( $opt->{max_values} == 1 ) {
if ( not( $opt->{cap} & SANE_CAP_INACTIVE ) ) {
my $val = $device->get_option($opt_num);
print " [";
if ( $opt->{type} == SANE_TYPE_BOOL ) {
print( $val ? "yes" : "no" );
}
elsif ( $opt->{type} == SANE_TYPE_INT or $opt->{type} == SANE_TYPE_FIXED ) {
my $string_format = "%g";
$string_format = "%d" if ( $opt->{type} == SANE_TYPE_INT );
given ( $opt->{name} ) {
when ("l") {
$tl_x = $val;
printf $string_format, $tl_x;
}
when ("t") {
$tl_y = $val;
printf $string_format, $tl_y;
}
when ("x") {
$br_x = $val;
printf $string_format, $br_x - $tl_x;
}
when ("y") {
$br_y = $val;
printf $string_format, $br_y - $tl_y;
}
default {
printf $string_format, $val;
}
}
}
elsif ( $opt->{type} == SANE_TYPE_STRING ) {
print $val;
}
print ']';
}
}
return;
}
# A scalar has the following syntax:
#
# V [ U ]
#
# V is the value of the scalar. It is either an integer or a
# floating point number, depending on the option type.
#
# U is an optional unit. If not specified, the default unit is used.
# The following table lists which units are supported depending on
# what the option's default unit is:
#
# Option's unit: Allowed units:
#
# SANE_UNIT_NONE:
# SANE_UNIT_PIXEL: pel
# SANE_UNIT_BIT: b (bit), B (byte)
# SANE_UNIT_MM: mm (millimeter), cm (centimeter), in or " (inches),
# SANE_UNIT_DPI: dpi
# SANE_UNIT_PERCENT: %
# SANE_UNIT_MICROSECOND: us
sub parse_scalar {
my ( $opt, $str ) = @_;
my ( $v, $unit );
if (
$str =~ /^
(\d*\.?\d*) # value
(cm|mm|in|\"|b|B|dpi|%|us)? # optional unit
/x
)
{
$v = $1;
$unit = $2;
$unit = '' unless defined $unit;
}
else {
print STDERR
"$prog_name: option --$opt->{name}: bad option value (rest of option: $str)\n";
exit(1);
}
if ( $opt->{unit} == SANE_UNIT_BIT ) {
$v *= 8 if ( $unit eq 'B' );
}
elsif ( $opt->{unit} == SANE_UNIT_MM ) {
if ( $unit eq 'cm' ) {
$v *= 10;
}
elsif ( $unit eq 'in' ) {
$v *= 25.4;
}
}
return $v, substr( $str, length($v) + length($unit), length($str) );
}
# A vector has the following syntax:
#
# [ '[' I ']' ] S { [','|'-'] [ '[' I ']' S }
#
# The number in brackets (I), if present, determines the index of the
# vector element to be set next. If I is not present, the value of
# last index used plus 1 is used. The first index value used is 0
# unless I is present.
#
# S is a scalar value as defined by parse_scalar().
#
# If two consecutive value specs are separated by a comma (,) their
# values are set independently. If they are separated by a dash (-),
# they define the endpoints of a line and all vector values between
# the two endpoints are set according to the value of the
# interpolated line. For example, [0]15-[255]15 defines a vector of
# 256 elements whose value is 15. Similarly, [0]0-[255]255 defines a
# vector of 256 elements whose value starts at 0 and increases to
# 255.
sub parse_vector {
my ( $opt, $str ) = @_;
my $index = -1;
my $prev_value = 0;
my $prev_index = 0;
my $separator = '';
my ( @vector, $value );
do {
if ( $str =~ /^\[(\d*\.?\d*)(\])?/x ) {
$index = $1;
unless ( $2 eq '\]' ) {
print STDERR "$prog_name: option --$opt->{name}: closing bracket missing "
. "(rest of option: $str)\n";
exit(1);
}
}
else {
++$index;
}
if ( $index < 0 or $index >= length($str) ) {
printf STDERR
"$prog_name: option --$opt->{name}: index $index out of range [0..%d]\n",
length($str);
exit(1);
}
# read value
( $value, $str ) = parse_scalar( $opt, $str );
if ( $str ne '' and $str !~ /^[-,]/x ) {
print STDERR
"$prog_name: option --$opt->{name}: illegal separator (rest of option: $str)\n";
exit(1);
}
# store value:
$vector[$index] = $value;
if ( $separator eq '-' ) {
# interpolate
my $v = $prev_value;
my $slope = ( $value - $v ) / ( $index - $prev_index );
for ( my $i = $prev_index + 1 ; $i < $index ; ++$i ) {
$v += $slope;
$vector[$i] = $v;
}
}
$prev_index = $index;
$prev_value = $value;
$separator = substr( $str, 0, 1 );
} while ( $separator eq ',' or $separator eq '-' );
if ( $verbose > 2 ) {
print STDERR "$prog_name: value for --$opt->{name} is: ";
for (@vector) {
print STDERR "$_ ";
}
print STDERR "\n";
}
return @vector;
}
sub fetch_options {
$device = shift;
my $opt = $device->get_option_descriptor(0);
if ( not defined($opt) ) {
print STDERR "Could not get option descriptor for option 0\n";
exit(1);
}
$num_dev_options = $device->get_option(0);
if ( $Sane::STATUS != SANE_STATUS_GOOD ) {
print STDERR "Could not get value for option 0: $Sane::STATUS\n";
exit(1);
}
# build the full table of long options
for ( my $i = 1 ; $i < $num_dev_options ; ++$i ) {
$opt = $device->get_option_descriptor($i);
if ( not defined($opt) ) {
print STDERR "Could not get option descriptor for option $i\n";
exit(1);
}
next if ( not( $opt->{cap} & SANE_CAP_SOFT_SELECT ) );
$option_number{ $opt->{name} } = $i;
# Look for scan resolution
$resolution_optind = $i
if ( ( $opt->{type} == SANE_TYPE_FIXED or $opt->{type} == SANE_TYPE_INT )
and ( $opt->{unit} == SANE_UNIT_DPI )
and ( $opt->{name} eq SANE_NAME_SCAN_RESOLUTION ) );
update_geometry( $opt, $i );
if ( $opt->{type} == SANE_TYPE_BOOL ) {
push @args, "$opt->{name}:s";
}
elsif ( $opt->{type} == SANE_TYPE_BUTTON ) {
push @args, $opt->{name};
}
else {
push @args, "$opt->{name}=s";
}
}
# Initialize width & height options based on backend default
# values for top-left x/y and bottom-right x/y:
for ( my $i = 0 ; $i < 2 ; ++$i ) {
if ( $window[$i] and not $window_val_user[$i] ) {
$window_val[$i] = $device->get_option( $window[$i] );
if ( $window[ $i + 2 ] ) {
my $pos = $device->get_option( $window[ $i + 2 ] );
$window_val[$i] -= $pos;
}
}
}
return;
}
# Keep track of top-left corner options (if they exist at
# all) and replace the bottom-right corner options by a
# width/height option (if they exist at all).
sub update_geometry {
my ( $opt, $i ) = @_;
if ( ( $opt->{type} == SANE_TYPE_FIXED or $opt->{type} == SANE_TYPE_INT )
and ( $opt->{unit} == SANE_UNIT_MM or $opt->{unit} == SANE_UNIT_PIXEL ) )
{
given ( $opt->{name} ) {
when (SANE_NAME_SCAN_BR_X) {
$window[0] = $i;
$opt->{name} = 'x';
$window_option[0] = $opt;
$window_option[0]->{title} = 'Scan width';
$window_option[0]->{desc} = 'Width of scan-area.';
$window_option[0]->{name} = 'x';
}
when (SANE_NAME_SCAN_BR_Y) {
$window[1] = $i;
$opt->{name} = 'y';
$window_option[1] = $opt;
$window_option[1]->{title} = 'Scan height';
$window_option[1]->{desc} = 'Height of scan-area.';
$window_option[1]->{name} = 'y';
}
when (SANE_NAME_SCAN_TL_X) {
$window[2] = $i;
$window_option[2] = $opt;
$window_option[2]->{name} = 'l';
}
when (SANE_NAME_SCAN_TL_Y) {
$window[3] = $i;
$window_option[3] = $opt;
$window_option[3]->{name} = 't';
}
}
}
return;
}
sub set_option {
( $device, my $optnum, my $value ) = @_;
my $opt = $device->get_option_descriptor($optnum);
if ( $opt and ( $opt->{cap} & SANE_CAP_INACTIVE ) ) {
print STDERR
"$prog_name: ignored request to set inactive option $opt->{name}\n"
if ( $verbose > 0 );
return;
}
my $info = $device->set_option( $optnum, $value );
if ( $Sane::STATUS != SANE_STATUS_GOOD ) {
print STDERR
"$prog_name: setting of option --$opt->{name} failed ($Sane::STATUS)\n";
exit(1);
}
if ( ( $info & SANE_INFO_INEXACT ) and $opt->{max_values} == 1 ) {
my $orig = $value;
$value = $device->get_option($optnum);
if ( $opt->{type} == SANE_TYPE_INT ) {
printf STDERR "$prog_name: rounded value of $opt->{name} from %d to %d\n",
$orig, $value;
}
elsif ( $opt->{type} == SANE_TYPE_FIXED ) {
printf STDERR "$prog_name: rounded value of $opt->{name} from %g to %g\n",
$orig, $value;
}
}
fetch_options($device) if ( $info & SANE_INFO_RELOAD_OPTIONS );
return;
}
sub process_backend_option {
( $device, my $optnum, my $optarg ) = @_;
my $opt = $device->get_option_descriptor($optnum);
if ( $opt and ( $opt->{cap} & SANE_CAP_INACTIVE ) ) {
print STDERR "$prog_name: attempted to set inactive option $opt->{name}\n";
exit(1);
}
if ( ( $opt->{cap} & SANE_CAP_AUTOMATIC )
and $optarg
and $optarg =~ /^auto$/xi )
{
$device->set_auto($optnum);
if ( $Sane::STATUS != SANE_STATUS_GOOD ) {
printf STDERR
"$prog_name: failed to set option --$opt->{name} to automatic ($Sane::STATUS)\n";
exit(1);
}
return;
}
my $value;
given ( $opt->{type} ) {
when (SANE_TYPE_BOOL) {
$value = 1; # no argument means option is set
if ($optarg) {
if ( $optarg =~ /^yes$/xi ) {
$value = 1;
}
elsif ( $optarg =~ /^no$/xi ) {
$value = 0;
}
else {
die "$prog_name: option --$opt->{name}: bad option value `$optarg'\n";
}
}
}
when ( $opt->{type} == SANE_TYPE_INT or $opt->{type} == SANE_TYPE_FIXED ) {
my @vector = parse_vector( $opt, $optarg );
$value = \@vector;
}
when (SANE_TYPE_STRING) {
$value = $optarg;
}
when (SANE_TYPE_BUTTON) {
$value = 0; # value doesn't matter
}
default {
warn "$prog_name: duh, got unknown option type $opt->{type}\n";
return;
}
}
set_option( $device, $optnum, $value );
return;
}
sub write_pnm_header {
my ( $frame_format, $width, $height, $depth ) = @_;
# The netpbm-package does not define raw image data with maxval > 255.
# But writing maxval 65535 for 16bit data gives at least a chance
# to read the image.
if ($frame_format == SANE_FRAME_RED
or $frame_format == SANE_FRAME_GREEN
or $frame_format == SANE_FRAME_BLUE
or $frame_format == SANE_FRAME_RGB )
{
printf "P6\n# SANE data follows\n%d %d\n%d\n", $width, $height,
( $depth <= 8 ) ? 255 : 65535;
}
else {
if ( $depth == 1 ) {
printf "P4\n# SANE data follows\n%d %d\n", $width, $height;
}
else {
printf "P5\n# SANE data follows\n%d %d\n%d\n", $width, $height,
( $depth <= 8 ) ? 255 : 65535;
}
}
return;
}
sub scan_it {
my $first_frame = 1;
my $offset = 0;
my $must_buffer = 0;
my $min = 0xff;
my $max = 0;
my %image;
my @format_name = ( "gray", "RGB", "red", "green", "blue" );
my $total_bytes = 0;
# my $hang_over = -1;
my $parm;
{
do { # extra braces to get last to work.
log_frame_info( $parm, $total_bytes, $first_frame, @format_name );
( $must_buffer, $offset ) = initialise_scan( $parm, $first_frame );
my $hundred_percent = $parm->{bytes_per_line} * $parm->{lines} * (
( $parm->{format} == SANE_FRAME_RGB or $parm->{format} == SANE_FRAME_GRAY )
? 1
: 3
);
while (1) {
my ( $buffer, $len ) = $device->read($buffer_size);
$total_bytes += $len;
my $progr = ( ( $total_bytes * 100. ) / $hundred_percent );
$progr = 100. if ( $progr > 100. );
printf STDERR "Progress: %3.1f%%\r", $progr if ($progress);
if ( $Sane::STATUS != SANE_STATUS_GOOD ) {
printf STDERR "$prog_name: min/max graylevel value = %d/%d\n", $min, $max
if ( $verbose and $parm->{depth} == 8 );
if ( $Sane::STATUS != SANE_STATUS_EOF ) {
print STDERR "$prog_name: sane_read: $Sane::STATUS\n";
return;
}
last;
}
$offset =
buffer_data( $parm, $buffer, $len, \%image, $offset, $must_buffer );
if ( $verbose and $parm->{depth} == 8 ) {
for ( split( //, $buffer ) ) {
my $c = ord;
if ( $c >= $max ) {
$max = $c;
}
elsif ( $c < $min ) {
$min = $c;
}
}
}
}
$first_frame = 0;
} while ( not $parm->{last_frame} );
}
if ($must_buffer) {
write_buffer( \%image, $parm );
}
# flush the output buffer
STDOUT->flush;
log_bytes_read( $parm, $total_bytes );
return;
}
sub log_frame_info {
my ( $parm, $total_bytes, $first_frame, @format_name ) = @_;
if ( not $first_frame ) {
$device->start;
if ( $Sane::STATUS != SANE_STATUS_GOOD ) {
printf STDERR "$prog_name: sane_start: $Sane::STATUS\n";
log_bytes_read( $parm, $total_bytes );
}
}
$parm = $device->get_parameters;
if ( $Sane::STATUS != SANE_STATUS_GOOD ) {
printf STDERR "$prog_name: sane_get_parameters: $Sane::STATUS\n";
log_bytes_read( $parm, $total_bytes );
}
if ($verbose) {
if ($first_frame) {
if ( $parm->{lines} >= 0 ) {
printf STDERR "$prog_name: scanning image of size %dx%d pixels at "
. "%d bits/pixel\n",
$parm->{pixels_per_line}, $parm->{lines},
8 * $parm->{bytes_per_line} / $parm->{pixels_per_line};
}
else {
printf STDERR "$prog_name: scanning image %d pixels wide and "
. "variable height at %d bits/pixel\n",
$parm->{pixels_per_line},
8 * $parm->{bytes_per_line} / $parm->{pixels_per_line};
}
}
printf STDERR "$prog_name: acquiring %s frame\n",
$parm->{format} <= SANE_FRAME_BLUE
? $format_name[ $parm->{format} ]
: "Unknown";
}
return;
}
sub log_bytes_read {
my ( $parm, $total_bytes ) = @_;
my $expected_bytes = $parm->{bytes_per_line} * $parm->{lines} * (
( $parm->{format} == SANE_FRAME_RGB or $parm->{format} == SANE_FRAME_GRAY )
? 1
: 3
);
$expected_bytes = 0 if ( $parm->{lines} < 0 );
if ( $total_bytes > $expected_bytes and $expected_bytes != 0 ) {
printf STDERR "%s: WARNING: read more data than announced by backend "
. "(%u/%u)\n", $prog_name, $total_bytes, $expected_bytes;
}
elsif ($verbose) {
printf STDERR "%s: read %u bytes in total\n", $prog_name, $total_bytes;
}
return;
}
sub initialise_scan {
my ( $parm, $first_frame ) = @_;
my ( $must_buffer, $offset );
if ($first_frame) {
if ($parm->{format} == SANE_FRAME_RED
or $parm->{format} == SANE_FRAME_GREEN
or $parm->{format} == SANE_FRAME_BLUE )
{
die # FIXME: compare message with SANE source, and give them patch if necessary
"Error: frame format $parm->{format}, but image depth=$parm->{depth} (expected 8)\n"
unless ( $parm->{depth} == 8 );
$must_buffer = 1;
$offset = $parm->{format} - SANE_FRAME_RED;
}
elsif ( $parm->{format} == SANE_FRAME_RGB ) {
die # FIXME: compare message with SANE source, and give them patch if necessary
"Error: frame format $parm->{format}, but image depth=$parm->{depth} (expected 8 or 16)\n"
unless ( ( $parm->{depth} == 8 ) or ( $parm->{depth} == 16 ) );
}
if ($parm->{format} == SANE_FRAME_RGB
or $parm->{format} == SANE_FRAME_GRAY )
{
die # FIXME: compare message with SANE source, and give them patch if necessary
"Error: frame format $parm->{format}, but image depth=$parm->{depth} (expected 1, 8 or 16)\n"
unless ( ( $parm->{depth} == 1 )
or ( $parm->{depth} == 8 )
or ( $parm->{depth} == 16 ) );
if ( $parm->{lines} < 0 ) {
$must_buffer = 1;
$offset = 0;
}
else {
# if ($output_format == OUTPUT_TIFF) {
# sanei_write_tiff_header ($parm->{format},
# $parm->{pixels_per_line}, $parm->{lines},
# $parm->{depth}, $resolution_value,
# icc_profile);
# else {
write_pnm_header(
$parm->{format}, $parm->{pixels_per_line},
$parm->{lines}, $parm->{depth}
);
# }
}
}
}
else {
die # FIXME: compare message with SANE source, and give them patch if necessary
"Error: frame format $parm->{format}, but expected SANE_FRAME_RED, SANE_FRAME_GREEN, or SANE_FRAME_BLUE\n"
if ( $parm->{format} < SANE_FRAME_RED
or $parm->{format} > SANE_FRAME_BLUE );
$offset = $parm->{format} - SANE_FRAME_RED;
}
return $must_buffer, $offset;
}
sub buffer_data { ## no critic (ProhibitManyArgs)
my ( $parm, $buffer, $len, $image, $offset, $must_buffer ) = @_;
if ($must_buffer) {
# We're either scanning a multi-frame image or the
# scanner doesn't know what the eventual image height
# will be (common for hand-held scanners). In either
# case, we need to buffer all data before we can write
# the image
if ($parm->{format} == SANE_FRAME_RED
or $parm->{format} == SANE_FRAME_GREEN
or $parm->{format} == SANE_FRAME_BLUE )
{
for ( my $i = 0 ; $i < $len ; ++$i ) {
$image->{data}[ $offset + 3 * $i ] = substr( $buffer, $i, 1 );
}
$offset += 3 * $len;
}
elsif ( $parm->{format} == SANE_FRAME_RGB
or $parm->{format} == SANE_FRAME_GRAY )
{
for ( my $i = 0 ; $i < $len ; ++$i ) {
$image->{data}[ $offset + $i ] = substr( $buffer, $i, 1 );
}
$offset += $len;
}
}
else { # ! must_buffer
# if (($output_format == OUTPUT_TIFF) or ($parm->{depth} != 16)) {
# print $buffer;
# }
# else {
##if !defined(WORDS_BIGENDIAN)
# my $start = 0;
#
# # check if we have saved one byte from the last sane_read
# if ($hang_over > -1) {
# if ($len > 0) {
# print $buffer;
# $buffer = $hang_over.$buffer;
# $hang_over = -1;
# $start = 1;
# }
# }
# # now do the byte-swapping
# $buffer = reverse $buffer;
#
# # check if we have an odd number of bytes
# if ((($len - $start) % 2) != 0) {
# $hang_over = substr($buffer, $len - 1, 1);
# $len--;
# }
##endif
print $buffer;
# }
}
return $offset;
}
sub write_buffer {
my ( $image, $parm ) = @_;
if ( $parm->{lines} > 0 ) {
$image->{height} = $parm->{lines};
}
else {
$image->{height} = @{ $image->{data} } / $parm->{pixels_per_line};
$image->{height} /= 3
if ( $parm->{format} == SANE_FRAME_RED
or $parm->{format} == SANE_FRAME_GREEN
or $parm->{format} == SANE_FRAME_BLUE );
}
# if ($output_format == OUTPUT_TIFF) {
# sanei_write_tiff_header ($parm->{format}, $parm->{pixels_per_line},
# $parm->{lines}, $parm->{depth}, $resolution_value,
# icc_profile);
# }
# else {
write_pnm_header(
$parm->{format}, $parm->{pixels_per_line},
$image->{height}, $parm->{depth}
);
# }
# if (($output_format == OUTPUT_TIFF) or ($image->{Bpp} == 1)
# or ($image->{Bpp} == 3)) {
# print $image->{data};
# }
# else { # $image->{Bpp} == 2 or $image->{Bpp} == 6 assumed
##if !defined(WORDS_BIGENDIAN)
# for (my $i = 0; $i < $image->{Bpp} * $image->{height} * $image->{width}; $i += 2) {
# my $LSB = $image->{data}[$i];
# $image->{data}[$i] = $image->{data}[$i + 1];
# $image->{data}[$i + 1] = $LSB;
# }
##endif
for ( @{ $image->{data} } ) { print; }
# }
return;
}
sub scan_pages { ## no critic (ProhibitExcessComplexity)
my $n = $batch_start_at;
if ( $batch and ( not defined($format) or $format eq '' ) ) {
# if ($output_format == OUTPUT_TIFF) {
# $format = "out%d.tif";
# }
# else {
$format = "out%d.pnm";
# }
}
printf STDERR "Scanning %d pages, incrementing by %d, numbering from %d\n",
$batch_count, $batch_increment, $batch_start_at
if ($batch);
{ # extra braces to get last to work
do {
my ( $path, $part_path, $fh );
if ($batch) { # format is NULL unless batch mode
$path = sprintf $format, $n;
$part_path = "$path.part";
}
if ($batch) {
if ($batch_prompt) {
printf STDERR "Place document no. %d on the scanner.\n", $n;
printf STDERR "Press to continue.\n";
printf STDERR "Press Ctrl + D to terminate.\n";
if ( not defined(<>) ) {
printf STDERR "Batch terminated, %d pages scanned\n",
( $n - $batch_increment );
last; # get out of this loop
}
}
printf STDERR "Scanning page %d\n", $n;
}
$device->start;
if ( $Sane::STATUS != SANE_STATUS_GOOD ) {
print STDERR "$prog_name: sane_start: $Sane::STATUS\n";
last;
}
# write to .part file while scanning is in progress
if (
$batch
and not(
open( $fh, '>', $part_path ) ## no critic (RequireBriefOpen)
and STDOUT->fdopen( $fh, '>' )
)
)
{
print STDERR "cannot open $part_path\n";
$device->cancel;
exit SANE_STATUS_ACCESS_DENIED;
}
scan_it();
if ($batch) {
printf STDERR "Scanned page %d.", $n;
printf STDERR " (scanner status = %d)\n", $Sane::STATUS;
}
if ( $Sane::STATUS == SANE_STATUS_EOF ) {
if ($batch) {
# close output file by redirecting, do not close stdout here!
if (
open( $fh, '>', '/dev/null' ) ## no critic (RequireBriefOpen)
and STDOUT->fdopen( $fh, '>' )
)
{
# let the fully scanned file show up
if ( not rename( $part_path, $path ) ) {
print STDERR "cannot rename $part_path to $path\n";
$device->cancel;
return SANE_STATUS_ACCESS_DENIED;
}
}
else {
printf STDERR "cannot open /dev/null\n";
$device->cancel;
return SANE_STATUS_ACCESS_DENIED;
}
}
}
elsif ( $Sane::STATUS != SANE_STATUS_GOOD ) {
if ($batch) {
close($fh);
unlink($part_path);
}
last;
}
$n += $batch_increment;
} while ( ( $batch and ( $batch_count == -1 or --$batch_count ) )
and
( $Sane::STATUS == SANE_STATUS_GOOD or $Sane::STATUS == SANE_STATUS_EOF ) );
}
$device->cancel;
return;
}
sub pass_fail {
my ( $max, $len, $buffer ) = @_;
if ( $Sane::STATUS != SANE_STATUS_GOOD )
{ ## no critic (ProhibitCascadingIfElse)
print STDERR "FAIL Error: $Sane::STATUS\n";
}
elsif ( $len < length($buffer) ) {
printf STDERR "FAIL Cheat: %d bytes\n", length($buffer);
}
elsif ( $len > $max ) {
printf STDERR "FAIL Overflow: %d bytes\n", $len;
}
elsif ( $len == 0 ) {
print STDERR "FAIL No data\n";
}
else {
print STDERR "PASS\n";
}
return;
}
sub test_it {
my %image;
my @format_name = ( "gray", "RGB", "red", "green", "blue" );
$device->start;
if ( $Sane::STATUS != SANE_STATUS_GOOD ) {
print STDERR "$prog_name: sane_start: $Sane::STATUS\n";
goto cleanup;
}
my $parm = $device->get_parameters;
if ( $Sane::STATUS != SANE_STATUS_GOOD ) {
print STDERR "$prog_name: sane_get_parameters: $Sane::STATUS\n";
goto cleanup;
}
if ( $parm->{lines} >= 0 ) {
printf STDERR "$prog_name: scanning image of size %dx%d pixels at "
. "%d bits/pixel\n", $parm->{pixels_per_line}, $parm->{lines},
8 * $parm->{bytes_per_line} / $parm->{pixels_per_line};
}
else {
printf STDERR "$prog_name: scanning image %d pixels wide and "
. "variable height at %d bits/pixel\n", $parm->{pixels_per_line},
8 * $parm->{bytes_per_line} / $parm->{pixels_per_line};
}
printf STDERR "$prog_name: acquiring %s frame, %d bits/sample\n",
$parm->{format} <= SANE_FRAME_BLUE
? $format_name[ $parm->{format} ]
: "Unknown",
$parm->{depth};
printf STDERR "$prog_name: reading one scanline, %d bytes...\t",
$parm->{bytes_per_line};
( $image{data}, my $len ) = $device->read( $parm->{bytes_per_line} );
pass_fail( $parm->{bytes_per_line}, $len, $image{data} );
goto cleanup if ( $Sane::STATUS != SANE_STATUS_GOOD );
print STDERR "$prog_name: reading one byte...\t\t";
( $image{data}, $len ) = $device->read(1);
pass_fail( 1, $len, $image{data} );
goto cleanup if ( $Sane::STATUS != SANE_STATUS_GOOD );
my $i;
for ( $i = 2 ; $i < $parm->{bytes_per_line} * 2 ; $i *= 2 ) {
printf STDERR "$prog_name: stepped read, %d bytes... \t", $i;
( $image{data}, $len ) = $device->read($i);
pass_fail( $i, $len, $image{data} );
goto cleanup if ( $Sane::STATUS != SANE_STATUS_GOOD );
}
for ( $i /= 2 ; $i > 2 ; $i /= 2 ) {
printf STDERR "$prog_name: stepped read, %d bytes... \t", $i - 1;
( $image{data}, $len ) = $device->read( $i - 1 );
pass_fail( $i - 1, $len, $image{data} );
goto cleanup if ( $Sane::STATUS != SANE_STATUS_GOOD );
}
cleanup:
$device->cancel;
return;
}
# @brief print device options to stdout
#
# @param device struct of the opened device to describe
# @param num_dev_options number of device options
# @param ro SANE_TRUE to print read-only options
sub print_options {
( $device, my $num_dev_options, my $ro ) = @_;
for ( my $i = 1 ; $i < $num_dev_options ; ++$i ) {
my $opt;
# scan area uses modified option struct
for ( my $j = 0 ; $j < 4 ; ++$j ) {
if ( $i == $window[$j] ) {
$opt = $window_option[$j];
}
}
$opt = $device->get_option_descriptor($i) if ( not defined($opt) );
print_option( $device, $i, $opt )
if ( $ro
or $opt->{cap} & SANE_CAP_SOFT_SELECT
or $opt->{type} == SANE_TYPE_GROUP );
}
print "\n" if ($num_dev_options);
return;
}
sub process_arguments {
# re-enable error printing and arg permutation
Getopt::Long::Configure('no_pass_through');
# There seems to be a bug in Getopt::Long 2.37 where l is treated as L whilst
# l is not in @args. Therefore the workaround is to rename l to m for the first
# scan and back to l for the second.
for (@ARGV) {
$_ = '-l' if ( $_ eq '-m' );
$_ = '-t' if ( $_ eq '-u' );
}
my @ARGV_old = @ARGV;
exit 1 if ( not GetOptions(@args) );
# As it isn't possible to get the argument order from Getopt::Long 2.37, do
# this myself
for (@ARGV_old) {
my $ch;
if (/--(.*)/x) {
$ch = $1;
my $i = index( $ch, '=' );
$ch = substr( $ch, 0, $i ) if ( $i > -1 );
}
elsif (/-(.)/x) {
$ch = $1;
}
else {
next;
}
if ( defined $options{$ch} ) {
given ($ch) {
when ('x') {
$window_val_user[0] = 1;
( $window_val[0] ) = parse_vector( $window_option[0], $options{x} );
}
when ('y') {
$window_val_user[1] = 1;
( $window_val[1] ) = parse_vector( $window_option[1], $options{y} );
}
when ('l') { # tl-x
process_backend_option( $device, $window[2], $options{l} );
}
when ('t') { # tl-y
process_backend_option( $device, $window[3], $options{t} );
}
default {
process_backend_option( $device, $option_number{$ch}, $options{$ch} );
}
}
}
}
# convert x/y to br_x/br_y
for ( my $index = 0 ; $index < 2 ; ++$index ) {
if ( $window[$index] and defined( $window_val[$index] ) ) {
my $val = $window_val[$index];
if ( $window[ $index + 2 ] ) {
my $pos = $device->get_option( $window[ $index + 2 ] );
$val += $pos;
}
set_option( $device, $window[$index], $val );
}
}
return;
}
sub list_device_names {
print
"Type ``$prog_name --help -d DEVICE'' to get list of all options for DEVICE.\n\nList of available devices:";
my @device_list = Sane->get_devices;
if ( $Sane::STATUS == SANE_STATUS_GOOD ) {
my $column = 80;
foreach (@device_list) {
if ( $column + length( $_->{name} ) + 1 >= 80 ) {
print "\n ";
$column = 4;
}
if ( $column > 4 ) {
print ' ';
$column += 1;
}
print $_->{name};
$column += length( $_->{name} );
}
}
print "\n";
return;
}
sub list_devices_verbose {
my @device_list = Sane->get_devices;
if ( $Sane::STATUS != SANE_STATUS_GOOD ) {
print STDERR "$prog_name: sane_get_devices() failed: $Sane::STATUS\n";
exit(1);
}
if ( defined( $options{L} ) ) {
foreach (@device_list) {
printf "device `%s' is a %s %s %s\n", $_->{name}, $_->{vendor},
$_->{model}, $_->{type};
}
printf "\nNo scanners were identified. If you were expecting "
. "something different,\ncheck that the scanner is plugged "
. "in, turned on and detected by the\nsane-find-scanner tool "
. "(if appropriate). Please read the documentation\nwhich came "
. "with this software (README, FAQ, manpages).\n"
if ( $#device_list == -1 );
}
else {
for ( my $i = 0 ; $i < @device_list ; $i++ ) {
my $string_format = $options{f};
$string_format =~ s/%d/$device_list[$i]->{name}/g;
$string_format =~ s/%v/$device_list[$i]->{vendor}/g;
$string_format =~ s/%m/$device_list[$i]->{model}/g;
$string_format =~ s/%t/$device_list[$i]->{type}/g;
$string_format =~ s/%i/$i/g;
print $string_format;
}
}
printf "default device is `%s'\n", $ENV{'SANE_DEFAULT_DEVICE'}
if ( defined( $ENV{'SANE_DEFAULT_DEVICE'} ) );
return;
}
sub open_device {
unless ($devname) {
# If no device name was specified explicitly, we look at the
# environment variable SANE_DEFAULT_DEVICE. If this variable
# is not set, we open the first device we find (if any):
if ( defined( $ENV{'SANE_DEFAULT_DEVICE'} ) ) {
$devname = $ENV{'SANE_DEFAULT_DEVICE'};
}
else {
my @device_list = Sane->get_devices;
if ( $Sane::STATUS != SANE_STATUS_GOOD ) {
print STDERR "$prog_name: sane_get_devices() failed: $Sane::STATUS\n";
exit(1);
}
if ( $#device_list == -1 ) {
print STDERR "$prog_name: no SANE devices found\n";
exit(1);
}
$devname = $device_list[0]{name};
}
}
$device = Sane::Device->open($devname);
if ( $Sane::STATUS != SANE_STATUS_GOOD ) {
print STDERR "$prog_name: open of device $devname failed: $Sane::STATUS\n";
print STDERR "\nYou seem to have specified a UNIX device name, "
. "or filename instead of selecting\nthe SANE scanner or "
. "image acquisition device you want to use. As an example,\n"
. "you might want \"epson:/dev/sg0\" or "
. "\"hp:/dev/usbscanner0\". If any supported\ndevices are "
. "installed in your system, you should be able to see a "
. "list with\n\"$prog_name --list-devices\".\n"
if ( $devname =~ /^\// );
if ($help) {
undef $device;
}
else {
exit(1);
}
}
return;
}
# There seems to be a bug in Getopt::Long 2.37 where l is treated as L whilst
# l is not in @args. Therefore the workaround is to rename l to m for the first
# scan and back to l for the second.
for (@ARGV) {
$_ = '-m' if ( $_ eq '-l' );
$_ = '-u' if ( $_ eq '-t' );
}
# make a first pass through the options with error printing and argument
# permutation disabled:
GetOptions(@args);
if ( defined( $options{L} ) or defined( $options{f} ) ) {
list_devices_verbose();
exit(0);
}
if ( defined( $options{V} ) ) {
printf "%s %s; backend version %d.%d.%d\n", $prog_name,
$Sane::VERSION, Sane->get_version;
exit(0);
}
if ($help) {
printf <<'EOS', $prog_name;
Usage: %s [OPTION]...
Start image acquisition on a scanner device and write image data to
standard output.
Parameters are separated by a blank from single-character options (e.g.
-d epson) and by a "=" from multi-character options (e.g. --device-name=epson).
-d, --device-name=DEVICE use a given scanner device (e.g. hp:/dev/scanner)
--format=pnm|tiff file format of output file
-i, --icc-profile=PROFILE include this ICC profile into TIFF file
-L, --list-devices show available scanner devices
-f, --formatted-device-list=FORMAT similar to -L, but the FORMAT of the output
can be specified: %%d (device name), %%v (vendor),
%%m (model), %%t (type), %%i (index number), and
%%n (newline)
-b, --batch[=FORMAT] working in batch mode, FORMAT is `out%%d.pnm' or
`out%%d.tif' by default depending on --format
--batch-start=# page number to start naming files with
--batch-count=# how many pages to scan in batch mode
--batch-increment=# increase page number in filename by #
--batch-double increment page number by two, same as
--batch-increment=2
--batch-prompt ask for pressing a key before scanning a page
--accept-md5-only only accept authorization requests using md5
-p, --progress print progress messages
-n, --dont-scan only set options, don't actually scan
-T, --test test backend thoroughly
-A, --all-options list all available backend options
-h, --help display this help message and exit
-v, --verbose give even more status messages
-B, --buffer-size=# change input buffer size (in kB, default 32)
-V, --version print version information
EOS
}
open_device();
if ( defined($device) ) {
fetch_options($device);
process_arguments();
# output device-specific help
if ($help) {
printf "\nOptions specific to device `%s':\n", $devname;
print_options( $device, $num_dev_options, SANE_FALSE );
}
# list all device-specific options
if ($all) {
printf( "\nAll options specific to device `%s':\n", $devname );
print_options( $device, $num_dev_options, SANE_TRUE );
exit 0;
}
}
# output device list
if ($help) {
list_device_names();
exit(0);
}
exit(0) if ($dont_scan);
local $SIG{HUP} = \&sighandler;
local $SIG{INT} = \&sighandler;
local $SIG{PIPE} = \&sighandler;
local $SIG{TERM} = \&sighandler;
$batch_increment = 2 if ($batch_double);
$batch = 1 if ( defined $format );
if ($batch_count) {
$batch = 1;
}
elsif ($batch) {
$batch_count = -1;
}
else {
$batch_count = 1;
}
if ( $test == 0 ) {
scan_pages();
}
else {
test_it();
}
exit $Sane::STATUS;
__END__
=head1 NAME
scanimage - scan an image
=head1 SYNOPSIS
B
B<[ -d | --device-name>
I
B<[ --format>
I
B<[ -i | --icc-profile>
I
B<[ -L | --list-devices ]>
B<[ -f | --formatted-device-list >
I
B<[ --batch >
I<[= format ]]>
B<[ --batch-start>
I
B<[ --batch-count>
I
B<[ --batch-increment>
I
B<[ --batch-double ]>
B<[ --accept-md5-only ]>
B<[ -p | --progress ]>
B<[ -n | --dont-scan ]>
B<[ -T | --test ]>
B<[ -h | --help ]>
B<[ -v | --verbose ]>
B<[ -B | --buffersize ]>
B<[ -V | --version ]>
I<[ device-specific-options ]>
=head1 DESCRIPTION
B
is a command-line interface to control image acquisition devices such
as flatbed scanners or cameras. The device is controlled via
command-line options. After command-line processing,
B
normally proceeds to acquire an image. The image data is written to
standard output in one of the PNM (portable aNyMaP) formats (PBM for
black-and-white images, PGM for grayscale images, and PPM for color
images) or in TIFF (black-and-white, grayscale or color).
B
accesses image acquisition devices through the
B
(Scanner Access Now Easy) interface and can thus support any device for which
there exists a
B
backend (try
B
I
to get a list of available backends).
=head1 EXAMPLES
To get a list of devices:
scanimage -L
To scan with default settings to the file image.pnm:
scanimage >image.pnm
To scan 100x100 mm to the file image.tiff (-x and -y may not be available with
all devices):
scanimage -x 100 -y 100 --format=tiff >image.tiff
To print all available options:
scanimage -h
=head1 OPTIONS
Parameters are separated by a blank from single-character options (e.g.
-d epson) and by a "=" from multi-character options (e.g. --device-name=epson).
The
B<-d>
or
B<--device-name>
options must be followed by a
B
device-name like
I<` epson:/dev/sg0 '>
or
I<` hp:/dev/usbscanner0 '.>
A (partial) list of available devices can be obtained with the
B<--list-devices>
option (see below). If no device-name is specified explicitly,
B
reads a device-name from the environment variable
B
If this variable is not set,
B
will attempt to open the first available device.
The
B<--format >
I
option selects how image data is written to standard output.
I
can be
B
or
B
If
B<--format>
is not used, PNM is written.
The
B<-i>
or
B<--icc-profile>
option is used to include an ICC profile into a TIFF file.
The
B<-L>
or
B<--list-devices>
option requests a (partial) list of devices that are available. The
list is not complete since some devices may be available, but are not
listed in any of the configuration files (which are typically stored
in directory
I
This is particularly the case when accessing scanners through the network. If
a device is not listed in a configuration file, the only way to access it is
by its full device name. You may need to consult your system administrator to
find out the names of such devices.
The
B<-f>
or
B<--formatted-device-list>
option works similar to
B<--list-devices ,>
but requires a format string.
B
replaces the placeholders
B<%d %v %m %t %i>
with the device name, vendor name, model name, scanner type and an index
number respectively. The command
=over
=item B
I<\*(lq scanner number %i device %d is a %t, model %m, produced by %v \*(rq>
=back
will produce something like:
=over
=item scanner number 0 device sharp:/dev/sg1 is a flatbed scanner, model JX250
SCSI, produced by SHARP
=back
The
B<--batch*>
options provide the features for scanning documents using document
feeders.
B<--batch>
I<[ format ]>
is used to specify the format of the filename that each page will be written
to. Each page is written out to a single file. If
I
is not specified, the default of out%d.pnm (or out%d.tif for --format tiff)
will be used.
I
is given as a printf style string with one integer parameter.
B<--batch-start>
I
selects the page number to start naming files with. If this option is not
given, the counter will start at 0.
B<--batch-count>
I
specifies the number of pages to attempt to scan. If not given,
scanimage will continue scanning until the scanner returns a state
other than OK. Not all scanners with document feeders signal when the
ADF is empty, use this command to work around them.
With
B<--batch-increment>
I
you can change the amount that the number in the filename is incremented
by. Generally this is used when you are scanning double-sided documents
on a single-sided document feeder. A specific command is provided to
aid this:
B<--batch-double>
will automatically set the increment to 2.
B<--batch-prompt>
will ask for pressing RETURN before scanning a page. This can be used for
scanning multiple pages without an automatic document feeder.
The
B<--accept-md5-only>
option only accepts user authorization requests that support MD5 security. The
B
network daemon
B<( saned )>
is capable of doing such requests. See
B
The
B<-p>
or
B<--progress>
option requests that
B
prints a progress counter. It shows how much image data of the current image has
already been received by
B
(in percent).
The
B<-n>
or
B<--dont-scan>
option requests that
B
only sets the options provided by the user but doesn't actually perform a
scan. This option can be used to e.g. turn off the scanner's lamp (if
supported by the backend).
The
B<-T>
or
B<--test>
option requests that
B
performs a few simple sanity tests to make sure the backend works as
defined by the
B
API (in particular the
B
function is exercised by this test).
The
B<-h>
or
B<--help>
options request help information. The information is printed on
standard output and in this case, no attempt will be made to acquire
an image.
The
B<-v>
or
B<--verbose>
options increase the verbosity of the operation of
B
The option may be specified repeatedly, each time increasing the verbosity
level.
The
B<-B>
or
B<--buffersize>
option changes the input buffersize that
B
uses from default 32*1024 to 1024*1024 kbytes.
The
B<-V>
or
B<--version>
option requests that
B
prints the program and package name, the version number of
the
B
distribution that it came with and the version of the backend that it
loads. Usually that's the dll backend. If more information about the version
numbers of the backends are necessary, the
B
variable for the dll backend can be used. Example: SANE_DEBUG_DLL=3 scanimage
-L.
As you might imagine, much of the power of
B
comes from the fact that it can control any
B
backend. Thus, the exact set of command-line options depends on the
capabilities of the selected device. To see the options for a device named
I
invoke
B
via a command-line of the form:
=over
=item B
I
=back
The documentation for the device-specific options printed by
B<--help>
is best explained with a few examples:
-l 0..218mm [0]
Top-left x position of scan area.
=over
=item The description above shows that option
B<-l>
expects an option value in the range from 0 to 218 mm. The
value in square brackets indicates that the current option value is 0
mm. Most backends provide similar geometry options for top-left y position (-t),
width (-x) and height of scan-area (-y).
=back
--brightness -100..100% [0]
Controls the brightness of the acquired image.
=over
=item The description above shows that option
B<--brightness>
expects an option value in the range from -100 to 100 percent. The
value in square brackets indicates that the current option value is 0
percent.
=back
--default-enhancements
Set default values for enhancement controls.
=over
=item The description above shows that option
B<--default-enhancements>
has no option value. It should be thought of as having an immediate
effect at the point of the command-line at which it appears. For
example, since this option resets the
B<--brightness>
option, the option-pair
B<--brightness 50 --default-enhancements>
would effectively be a no-op.
=back
--mode Lineart|Gray|Color [Gray]
Selects the scan mode (e.g., lineart or color).
=over
=item The description above shows that option
B<--mode>
accepts an argument that must be one of the strings
B
B
or
B
The value in the square bracket indicates that the option is currently
set to
B
For convenience, it is legal to abbreviate the string values as long as
they remain unique. Also, the case of the spelling doesn't matter. For
example, option setting
B<--mode col>
is identical to
B<"--mode Color" .>
=back
--custom-gamma[=(yes|no)] [inactive]
Determines whether a builtin or a custom gamma-table
should be used.
=over
=item The description above shows that option
B<--custom-gamma>
expects either no option value, a "yes" string, or a "no" string.
Specifying the option with no value is equivalent to specifying "yes".
The value in square-brackets indicates that the option is not
currently active. That is, attempting to set the option would result
in an error message. The set of available options typically depends
on the settings of other options. For example, the
B<--custom-gamma>
table might be active only when a grayscale or color scan-mode has
been requested.
=back
Note that the
B<--help>
option is processed only after all other options have been processed.
This makes it possible to see the option settings for a particular
mode by specifying the appropriate mode-options along
with the
B<--help>
option. For example, the command-line:
B< scanimage --help --mode>
I
would print the option settings that are in effect when the color-mode
is selected.
--gamma-table 0..255,...
Gamma-correction table. In color mode this option
equally affects the red, green, and blue channels
simultaneously (i.e., it is an intensity gamma table).
=over
=item The description above shows that option
B<--gamma-table>
expects zero or more values in the range 0 to 255. For example, a
legal value for this option would be "3,4,5,6,7,8,9,10,11,12". Since
it's cumbersome to specify long vectors in this form, the same can be
expressed by the abbreviated form "[0]3-[9]12". What this means is
that the first vector element is set to 3, the 9-th element is set to
12 and the values in between are interpolated linearly. Of course, it
is possible to specify multiple such linear segments. For example,
"[0]3-[2]3-[6]7,[7]10-[9]6" is equivalent to "3,3,3,4,5,6,7,10,8,6".
The program
B
can be used to generate such gamma tables (see
B
for details).
=back
--filename [/tmp/input.ppm]
The filename of the image to be loaded.
=over
=item The description above is an example of an option that takes an
arbitrary string value (which happens to be a filename). Again,
the value in brackets show that the option is current set to the
filename
B
=back
=head1 ENVIRONMENT
=over
=item B
The default device-name.
=back
=head1 FILES
=over
=item I
This directory holds various configuration files. For details, please
refer to the manual pages listed below.
=item I<~/.sane/pass>
This file contains lines of the form
=item user:password:resource
scanimage uses this information to answer user authorization requests
automatically. The file must have 0600 permissions or stricter. You should
use this file in conjunction with the --accept-md5-only option to avoid
server-side attacks. The resource may contain any character but is limited
to 127 characters.
=back
=head1 SEE ALSO
B
B
B
B
B
B
B
B
B
=head1 AUTHOR
Transliterated from the C original by Jeffrey Ratcliffe.
=head1 BUGS
All the bugs of scanimage and much, much more.
gscan2pdf-1.2.3/bin/scanadf-perl 0000755 0001750 0001750 00000113506 12105002475 015031 0 ustar jeff jeff #!/usr/bin/perl
use warnings;
use strict;
use feature "switch";
use Sane;
use Data::Dumper;
use Getopt::Long qw(:config no_ignore_case pass_through);
use File::Basename;
use IO::Handle;
#$Sane::DEBUG = 1;
my ( %options, @window_val_user, @window_option, @window_val, @window, $device,
$devname, %option_number );
my $num_dev_options = 0;
my $verbose = 0;
my $help = 0;
my $test = 0;
my $batch_start_at = 1;
my $batch_count = -1;
my $batch_increment = 1;
my $buffer_size = ( 32 * 1024 ); # default size
my $tl_x = 0;
my $tl_y = 0;
my $br_x = 0;
my $br_y = 0;
my $w_x = 0;
my $h_y = 0;
my $resolution_optind = -1;
my $resolution_value = 0;
my $prog_name = basename($0);
my $SANE_FRAME_TEXT = 10;
my $SANE_FRAME_JPEG = 11;
my $SANE_FRAME_G31D = 12;
my $SANE_FRAME_G32D = 13;
my $SANE_FRAME_G42D = 14;
my $no_overwrite = 0;
my $outputFile = "image-%04d"; # file name(format) to write output to
my $raw = SANE_FALSE;
my $scanScript; # script to run at end of scan
my $startNum = 1, my $endNum = -1; # start/end numbers of pages to scan
my @args = (
\%options,
'd|device-name=s' => \$devname,
'L|list-devices',
'h|help' => \$help,
'v|verbose+' => \$verbose,
'N|no-overwrite' => \$no_overwrite,
'o|output-file:s' => \$outputFile,
's|start-count=i' => \$startNum,
'e|end-count=i' => \$endNum,
'r|raw' => \$raw
);
sub sane_strframe {
my $frame = shift;
my %frame = (
SANE_FRAME_GRAY => "gray",
SANE_FRAME_RGB => "RGB",
SANE_FRAME_RED => "red",
SANE_FRAME_GREEN => "green",
SANE_FRAME_BLUE => "blue",
$SANE_FRAME_TEXT => "text",
$SANE_FRAME_JPEG => "jpeg",
$SANE_FRAME_G31D => "g31d",
$SANE_FRAME_G32D => "g32d",
$SANE_FRAME_G42D => "g42d",
);
if ( defined $frame{$frame} ) {
return $frame{$frame};
}
else {
return "unknown";
}
}
sub sane_isbasicframe {
my $frame = shift;
return
$frame == SANE_FRAME_GRAY
|| $frame == SANE_FRAME_RGB
|| $frame == SANE_FRAME_RED
|| $frame == SANE_FRAME_GREEN
|| $frame == SANE_FRAME_BLUE;
}
sub sighandler {
my $signum = shift;
if ($device) {
print STDERR "$prog_name: stopping scanner...\n";
$device->cancel;
}
return;
}
sub print_unit {
my ($unit) = @_;
given ($unit) {
when (SANE_UNIT_PIXEL) {
print "pel";
}
when (SANE_UNIT_BIT) {
print "bit";
}
when (SANE_UNIT_MM) {
print "mm";
}
when (SANE_UNIT_DPI) {
print "dpi";
}
when (SANE_UNIT_PERCENT) {
print "%";
}
when (SANE_UNIT_MICROSECOND) {
print "us";
}
}
return;
}
sub print_option {
( $device, my $opt_num, my $short_name ) = @_;
my $opt = $device->get_option_descriptor($opt_num);
if ($short_name) {
printf " -%s", $short_name;
}
else {
printf " --%s", $opt->{name};
}
print_option_choices($opt);
print_current_option_value( $opt, $opt_num );
print " [inactive]"
if ( $opt->{type} != SANE_TYPE_BUTTON and $opt->{cap} & SANE_CAP_INACTIVE );
print "\n ";
if ( $short_name eq 'x' ) {
print "Width of scan-area.";
}
elsif ( $short_name eq 'y' ) {
print "Height of scan-area.";
}
else {
my $column = 8;
my $last_break = 0;
my $start = 0;
for ( my $pos = 0 ; $pos < length( $opt->{desc} ) ; ++$pos ) {
++$column;
$last_break = $pos if ( substr( $opt->{desc}, $pos, 1 ) eq ' ' );
if ( $column >= 79 and $last_break ) {
print substr( $opt->{desc}, $start++, 1 ) while ( $start < $last_break );
$start = $last_break + 1; # skip blank
print "\n ";
$column = 8 + $pos - $start;
}
}
print substr( $opt->{desc}, $start++, 1 )
while ( $start < length( $opt->{desc} ) );
}
print "\n";
return;
}
sub print_option_choices { ## no critic (ProhibitExcessComplexity)
my ($opt) = @_;
if ( $opt->{type} == SANE_TYPE_BOOL ) {
print "[=(";
print "auto|" if ( $opt->{cap} & SANE_CAP_AUTOMATIC );
print "yes|no)]";
}
elsif ( $opt->{type} != SANE_TYPE_BUTTON ) {
print ' ';
if ( $opt->{cap} & SANE_CAP_AUTOMATIC ) {
print "auto|";
}
if ( $opt->{constraint_type} == SANE_CONSTRAINT_NONE ) {
if ( $opt->{type} == SANE_TYPE_INT ) {
print "";
}
elsif ( $opt->{type} == SANE_TYPE_FIXED ) {
print "";
}
elsif ( $opt->{type} == SANE_TYPE_STRING ) {
print "";
}
print ",..." if ( $opt->{max_values} > 1 );
}
elsif ( $opt->{constraint_type} == SANE_CONSTRAINT_RANGE ) {
my $string_format = "%g..%g";
$string_format = "%d..%d" if ( $opt->{type} == SANE_TYPE_INT );
if ( $opt->{name} eq SANE_NAME_SCAN_BR_X ) {
printf $string_format, $opt->{constraint}{min},
$opt->{constraint}{max} - $tl_x;
}
elsif ( $opt->{name} eq SANE_NAME_SCAN_BR_Y ) {
printf $string_format, $opt->{constraint}{min},
$opt->{constraint}{max} - $tl_y;
}
else {
printf $string_format, $opt->{constraint}{min}, $opt->{constraint}{max};
}
print_unit( $opt->{unit} );
print ",..." if ( $opt->{max_values} > 1 );
print " (in steps of $opt->{constraint}{quant})"
if ( $opt->{constraint}{quant} );
}
elsif ( $opt->{constraint_type} == SANE_CONSTRAINT_STRING_LIST
or $opt->{constraint_type} == SANE_CONSTRAINT_WORD_LIST )
{
for ( my $i = 0 ; $i < @{ $opt->{constraint} } ; ++$i ) {
print '|' if ( $i > 0 );
my $string_format = $opt->{type} == SANE_TYPE_FIXED ? '%g' : '%s';
printf $string_format, $opt->{constraint}[$i];
}
if ( $opt->{constraint_type} == SANE_CONSTRAINT_WORD_LIST ) {
print_unit( $opt->{unit} );
print ",..." if ( $opt->{max_values} > 1 );
}
}
}
return;
}
sub print_current_option_value {
my ( $opt, $opt_num ) = @_;
if ( $opt->{max_values} == 1 ) {
# print current option value
if ( !( $opt->{cap} & SANE_CAP_INACTIVE ) ) {
my $val = $device->get_option($opt_num);
print " [";
if ( $opt->{type} == SANE_TYPE_BOOL ) {
print( $val ? "yes" : "no" );
}
elsif ( $opt->{type} == SANE_TYPE_INT or $opt->{type} == SANE_TYPE_FIXED ) {
my $string_format = "%g";
$string_format = "%d" if ( $opt->{type} == SANE_TYPE_INT );
given ( $opt->{name} ) {
when (SANE_NAME_SCAN_TL_X) {
$tl_x = $val;
printf $string_format, $tl_x;
}
when (SANE_NAME_SCAN_TL_Y) {
$tl_y = $val;
printf $string_format, $tl_y;
}
when (SANE_NAME_SCAN_BR_X) {
$br_x = $val;
$w_x = $br_x - $tl_x;
printf $string_format, $w_x;
}
when (SANE_NAME_SCAN_BR_Y) {
$br_y = $val;
$h_y = $br_y - $tl_y;
printf $string_format, $h_y;
}
default {
printf $string_format, $val;
}
}
}
elsif ( $opt->{type} == SANE_TYPE_STRING ) {
print $val;
}
print ']';
}
}
return;
}
# A scalar has the following syntax:
#
# V [ U ]
#
# V is the value of the scalar. It is either an integer or a
# floating point number, depending on the option type.
#
# U is an optional unit. If not specified, the default unit is used.
# The following table lists which units are supported depending on
# what the option's default unit is:
#
# Option's unit: Allowed units:
#
# SANE_UNIT_NONE:
# SANE_UNIT_PIXEL: pel
# SANE_UNIT_BIT: b (bit), B (byte)
# SANE_UNIT_MM: mm (millimeter), cm (centimeter), in or " (inches),
# SANE_UNIT_DPI: dpi
# SANE_UNIT_PERCENT: %
# SANE_UNIT_MICROSECOND: us
sub parse_scalar {
my ( $opt, $str ) = @_;
my ( $v, $unit );
if (
$str =~ /^
(\d*\.?\d*) # value
(cm|mm|in|\"|b|B|dpi|%|us)? # optional unit
/x
)
{
$v = $1;
$unit = $2;
$unit = '' if not defined $unit;
}
else {
print STDERR
"$prog_name: option --$opt->{name}: bad option value (rest of option: $str)\n";
exit(1);
}
if ( $opt->{unit} == SANE_UNIT_BIT ) {
$v *= 8 if ( $unit eq 'B' );
}
elsif ( $opt->{unit} == SANE_UNIT_MM ) {
if ( $unit eq 'cm' ) {
$v *= 10;
}
elsif ( $unit eq 'in' ) {
$v *= 25.4;
}
}
return $v, substr( $str, length($v) + length($unit), length($str) );
}
# A vector has the following syntax:
#
# [ '[' I ']' ] S { [','|'-'] [ '[' I ']' S }
#
# The number in brackets (I), if present, determines the index of the
# vector element to be set next. If I is not present, the value of
# last index used plus 1 is used. The first index value used is 0
# unless I is present.
#
# S is a scalar value as defined by parse_scalar().
#
# If two consecutive value specs are separated by a comma (,) their
# values are set independently. If they are separated by a dash (-),
# they define the endpoints of a line and all vector values between
# the two endpoints are set according to the value of the
# interpolated line. For example, [0]15-[255]15 defines a vector of
# 256 elements whose value is 15. Similarly, [0]0-[255]255 defines a
# vector of 256 elements whose value starts at 0 and increases to
# 255.
sub parse_vector {
my ( $opt, $str ) = @_;
my $index = -1;
my $prev_value = 0;
my $prev_index = 0;
my $separator = '';
my ( @vector, $value );
do {
if ( $str =~ /^\[(\d*\.?\d*)(\])?/x ) {
$index = $1;
unless ( $2 eq '\]' ) {
print STDERR "$prog_name: option --$opt->{name}: closing bracket missing "
. "(rest of option: $str)\n";
exit(1);
}
}
else {
++$index;
}
if ( $index < 0 or $index >= length($str) ) {
printf STDERR
"$prog_name: option --$opt->{name}: index $index out of range [0..%d]\n",
length($str);
exit(1);
}
# read value
( $value, $str ) = parse_scalar( $opt, $str );
if ( $str ne '' and $str !~ /^[-,]/x ) {
print STDERR
"$prog_name: option --$opt->{name}: illegal separator (rest of option: $str)\n";
exit(1);
}
# store value:
$vector[$index] = $value;
if ( $separator eq '-' ) {
# interpolate
my $v = $prev_value;
my $slope = ( $value - $v ) / ( $index - $prev_index );
for ( my $i = $prev_index + 1 ; $i < $index ; ++$i ) {
$v += $slope;
$vector[$i] = $v;
}
}
$prev_index = $index;
$prev_value = $value;
$separator = substr( $str, 0, 1 );
} while ( $separator eq ',' || $separator eq '-' );
if ( $verbose > 2 ) {
print STDERR "$prog_name: value for --$opt->{name} is: ";
for (@vector) {
print STDERR "$_ ";
}
print STDERR "\n";
}
return @vector;
}
sub fetch_options {
$device = shift;
# We got a device, find out how many options it has:
$num_dev_options = $device->get_option(0);
if ( $Sane::STATUS != SANE_STATUS_GOOD ) {
print STDERR "$prog_name: unable to determine option count\n";
exit(1);
}
for ( my $i = 0 ; $i < $num_dev_options ; ++$i ) {
my $opt = $device->get_option_descriptor($i);
next if ( !( $opt->{cap} & SANE_CAP_SOFT_SELECT ) );
$option_number{ $opt->{name} } = $i;
# Look for scan resolution
$resolution_optind = $i
if ( ( $opt->{type} == SANE_TYPE_FIXED || $opt->{type} == SANE_TYPE_INT )
and ( $opt->{unit} == SANE_UNIT_DPI )
and ( $opt->{name} eq SANE_NAME_SCAN_RESOLUTION ) );
update_geometry( $opt, $i );
if ( $opt->{type} == SANE_TYPE_BOOL ) {
push @args, "$opt->{name}:s";
}
elsif ( $opt->{type} == SANE_TYPE_BUTTON ) {
push @args, $opt->{name};
}
else {
push @args, "$opt->{name}=s";
}
}
# Initialize width & height options based on backend default
# values for top-left x/y and bottom-right x/y:
for ( my $i = 0 ; $i < 2 ; ++$i ) {
if ( $window[$i] and $window[ $i + 2 ] and not $window_val_user[$i] ) {
my $pos = $device->get_option( $window[ $i + 2 ] );
$window_val[$i] = $window_val[$i] - $pos if ( defined $pos );
}
}
return;
}
# Keep track of top-left corner options (if they exist at
# all) and replace the bottom-right corner options by a
# width/height option (if they exist at all).
sub update_geometry {
my ( $opt, $i ) = @_;
if ( ( $opt->{type} == SANE_TYPE_FIXED || $opt->{type} == SANE_TYPE_INT )
and ( $opt->{unit} == SANE_UNIT_MM || $opt->{unit} == SANE_UNIT_PIXEL ) )
{
given ( $opt->{name} ) {
when (SANE_NAME_SCAN_TL_X) {
$window[2] = $i;
$opt->{name} = 'l';
}
when (SANE_NAME_SCAN_TL_Y) {
$window[3] = $i;
$opt->{name} = 't';
}
when (SANE_NAME_SCAN_BR_X) {
$window[0] = $i;
$opt->{name} = 'x';
$window_option[0] = $opt;
$window_option[0]->{title} = 'Scan width';
$window_option[0]->{desc} = 'Width of scanning area.';
$window_val[0] = $device->get_option($i)
if ( !$window_val_user[0] );
}
when (SANE_NAME_SCAN_BR_Y) {
$window[1] = $i;
$opt->{name} = 'y';
$window_option[1] = $opt;
$window_option[1]->{title} = 'Scan height';
$window_option[1]->{desc} = 'Height of scanning area.';
$window_val[1] = $device->get_option($i)
if ( !$window_val_user[1] );
}
}
}
return;
}
sub set_option {
( $device, my $optnum, my $value ) = @_;
my $opt = $device->get_option_descriptor($optnum);
if ( $opt and ( $opt->{cap} & SANE_CAP_INACTIVE ) ) {
print STDERR
"$prog_name: ignored request to set inactive option $opt->{name}\n"
if ( $verbose > 0 );
return;
}
my $info = $device->set_option( $optnum, $value );
if ( $Sane::STATUS != SANE_STATUS_GOOD ) {
print STDERR
"$prog_name: setting of option --$opt->{name} failed ($Sane::STATUS)\n";
exit(1);
}
if ( ( $info & SANE_INFO_INEXACT ) and $opt->{max_values} == 1 ) {
my $orig = $value;
$value = $device->get_option($optnum);
if ( $opt->{type} == SANE_TYPE_INT ) {
printf STDERR "$prog_name: rounded value of $opt->{name} from %d to %d\n",
$orig, $value;
}
elsif ( $opt->{type} == SANE_TYPE_FIXED ) {
printf STDERR "$prog_name: rounded value of $opt->{name} from %g to %g\n",
$orig, $value;
}
}
fetch_options($device) if ( $info & SANE_INFO_RELOAD_OPTIONS );
return;
}
sub process_backend_option {
( $device, my $optnum, my $optarg ) = @_;
my $opt = $device->get_option_descriptor($optnum);
if ( $opt and ( $opt->{cap} & SANE_CAP_INACTIVE ) ) {
print STDERR "$prog_name: attempted to set inactive option $opt->{name}\n";
exit(1);
}
if ( ( $opt->{cap} & SANE_CAP_AUTOMATIC )
and $optarg
and $optarg =~ /^auto$/ix )
{
$device->set_auto($optnum);
if ( $Sane::STATUS != SANE_STATUS_GOOD ) {
printf STDERR
"$prog_name: failed to set option --$opt->{name} to automatic ($Sane::STATUS)\n";
exit(1);
}
return;
}
my $value;
given ( $opt->{type} ) {
when (SANE_TYPE_BOOL) {
$value = 1; # no argument means option is set
if ($optarg) {
if ( $optarg =~ /^yes$/ix ) {
$value = 1;
}
elsif ( $optarg =~ /^no$/ix ) {
$value = 0;
}
else {
printf STDERR
"$prog_name: option --$opt->{name}: bad option value `$optarg'\n";
exit(1);
}
}
}
when ( $opt->{type} == SANE_TYPE_INT or $opt->{type} == SANE_TYPE_FIXED ) {
my @vector = parse_vector( $opt, $optarg );
$value = \@vector;
}
when (SANE_TYPE_STRING) {
$value = $optarg;
}
when (SANE_TYPE_BUTTON) {
$value = 0; # value doesn't matter
}
default {
printf STDERR "$prog_name: duh, got unknown option type $opt->{type}\n";
return;
}
}
set_option( $device, $optnum, $value );
return;
}
sub write_pnm_header_to_file {
my ( $fh, $frame_format, $width, $height, $depth ) = @_;
# The netpbm-package does not define raw image data with maxval > 255.
# But writing maxval 65535 for 16bit data gives at least a chance
# to read the image.
if ($frame_format == SANE_FRAME_RED
or $frame_format == SANE_FRAME_GREEN
or $frame_format == SANE_FRAME_BLUE
or $frame_format == SANE_FRAME_RGB )
{
printf $fh "P6\n# SANE data follows\n%d %d\n%d\n", $width, $height,
( $depth <= 8 ) ? 255 : 65535;
}
elsif ( $frame_format == SANE_FRAME_GRAY ) {
if ( $depth == 1 ) {
printf $fh "P4\n# SANE data follows\n%d %d\n", $width, $height;
}
else {
printf $fh "P5\n# SANE data follows\n%d %d\n%d\n", $width, $height,
( $depth <= 8 ) ? 255 : 65535;
}
}
return;
}
sub scan_it_raw {
( my $fname, $raw, my $script ) = @_;
my $first_frame = 1, my $offset = 0, my $must_buffer = 0;
my $min = 0xff, my $max = 0;
my ( %image, $fp );
my $parm;
{
do { # extra braces to get last to work.
log_frame_info( $parm, $fp, $fname, $first_frame );
my ( $must_buffer, $offset ) = initialise_scan( $parm, $first_frame, $fp );
while (1) {
my ( $buffer, $len ) = $device->read($buffer_size);
if ( $Sane::STATUS != SANE_STATUS_GOOD ) {
printf STDERR "$prog_name: min/max graylevel value = %d/%d\n", $min, $max
if ( $verbose && $parm->{depth} == 8 );
if ( $Sane::STATUS != SANE_STATUS_EOF ) {
print STDERR "$prog_name: sane_read: $Sane::STATUS\n";
return;
}
last;
}
$offset =
buffer_data( $fp, $parm, $buffer, $len, \%image, $offset, $must_buffer );
if ( $verbose && $parm->{depth} == 8 ) {
for ( split( //, $buffer ) ) {
my $c = ord;
if ( $c >= $max ) {
$max = $c;
}
elsif ( $c < $min ) {
$min = $c;
}
}
}
}
$first_frame = 0;
} while ( !$parm->{last_frame} );
}
if ($must_buffer) {
write_buffer( $fp, \%image, $parm );
}
if ($fp) {
close $fp;
undef $fp;
}
cleanup:
close $fp if ($fp);
return;
}
sub log_frame_info {
my ( $parm, $fp, $fname, $first_frame ) = @_;
$device->start;
if ( $Sane::STATUS != SANE_STATUS_GOOD ) {
print STDERR "$prog_name: sane_start: $Sane::STATUS\n"
if ( $Sane::STATUS != SANE_STATUS_NO_DOCS );
goto cleanup;
}
$parm = $device->get_parameters;
if ( $Sane::STATUS != SANE_STATUS_GOOD ) {
print STDERR "$prog_name: sane_get_parameters: $Sane::STATUS\n";
goto cleanup;
}
unless ( open $fp, '>', $fname ) ## no critic (RequireBriefOpen)
{
print STDERR "Error opening output `$fname': $@\n";
$Sane::_status = ## no critic (ProhibitPackageVars ProtectPrivateVars)
SANE_STATUS_IO_ERROR;
goto cleanup;
}
if ($verbose) {
if ($first_frame) {
if ( sane_isbasicframe( $parm->{format} ) ) {
if ( $parm->{lines} >= 0 ) {
printf STDERR "$prog_name: scanning image of size %dx%d pixels at "
. "%d bits/pixel\n",
$parm->{pixels_per_line}, $parm->{lines},
8 * $parm->{bytes_per_line} / $parm->{pixels_per_line};
}
else {
printf STDERR "$prog_name: scanning image %d pixels wide and "
. "variable height at %d bits/pixel\n",
$parm->{pixels_per_line},
8 * $parm->{bytes_per_line} / $parm->{pixels_per_line};
}
}
else {
printf STDERR "$prog_name: receiving %s frame "
. "bytes/line=%d, "
. "pixels/line=%d, "
. "lines=%d, "
. "depth=%d\n",, sane_strframe( $parm->{format} ),
$parm->{bytes_per_line},
$parm->{pixels_per_line},
$parm->{lines},
$parm->{depth};
}
}
printf STDERR "$prog_name: acquiring %s frame\n",
sane_strframe( $parm->{format} );
}
return;
}
sub initialise_scan { ## no critic (ProhibitExcessComplexity)
my ( $parm, $first_frame, $fp ) = @_;
my ( $must_buffer, $offset );
if ($first_frame) {
if ($parm->{format} == SANE_FRAME_RED
or $parm->{format} == SANE_FRAME_GREEN
or $parm->{format} == SANE_FRAME_BLUE )
{
die # FIXME: compare message with SANE source, and give them patch if necessary
"Error: frame format $parm->{format}, but image depth=$parm->{depth} (expected 8)\n"
unless ( $parm->{depth} == 8 );
$must_buffer = 1;
$offset = $parm->{format} - SANE_FRAME_RED;
}
elsif ( $parm->{format} == SANE_FRAME_RGB ) {
die # FIXME: compare message with SANE source, and give them patch if necessary
"Error: frame format $parm->{format}, but image depth=$parm->{depth} (expected 8)\n"
unless ( $parm->{depth} == 8 );
}
if ($parm->{format} == SANE_FRAME_RGB
or $parm->{format} == SANE_FRAME_GRAY )
{
die # FIXME: compare message with SANE source, and give them patch if necessary
"Error: frame format $parm->{format}, but image depth=$parm->{depth} (expected 1 or 8)\n"
unless ( ( $parm->{depth} == 1 ) || ( $parm->{depth} == 8 ) );
# if we're writing raw, we skip the header and never
# have to buffer a single frame format.
if ( $raw == SANE_FALSE ) {
if ( $parm->{lines} < 0 ) {
$must_buffer = 1;
$offset = 0;
}
else {
write_pnm_header_to_file( $fp, $parm->{format}, $parm->{pixels_per_line},
$parm->{lines}, $parm->{depth} );
}
}
}
elsif ( $parm->{format} == $SANE_FRAME_TEXT
or $parm->{format} == $SANE_FRAME_JPEG
or $parm->{format} == $SANE_FRAME_G31D
or $parm->{format} == $SANE_FRAME_G32D
or $parm->{format} == $SANE_FRAME_G42D )
{
if ( !$parm->{last_frame} ) {
$Sane::_status = ## no critic (ProhibitPackageVars ProtectPrivateVars)
SANE_STATUS_INVAL;
printf STDERR "$prog_name: bad %s frame: must be last_frame\n",
sane_strframe( $parm->{format} );
goto cleanup;
}
}
# write them out without a header; don't buffer
else {
# Default action for unknown frametypes; write them out
# without a header; issue a warning in verbose mode.
# Since we're not writing a header, there's no need to
# buffer.
printf STDERR "$prog_name: unknown frame format $parm->{format}\n"
if ($verbose);
if ( !$parm->{last_frame} ) {
$Sane::_status = ## no critic (ProhibitPackageVars ProtectPrivateVars)
SANE_STATUS_INVAL;
printf STDERR "$prog_name: bad %s frame: must be last_frame\n",
sane_strframe( $parm->{format} );
goto cleanup;
}
}
}
else {
die # FIXME: compare message with SANE source, and give them patch if necessary
"Error: frame format $parm->{format}, but expected SANE_FRAME_RED, SANE_FRAME_GREEN, or SANE_FRAME_BLUE\n"
if ( $parm->{format} < SANE_FRAME_RED
or $parm->{format} > SANE_FRAME_BLUE );
$offset = $parm->{format} - SANE_FRAME_RED;
}
return $must_buffer, $offset;
}
sub buffer_data { ## no critic (ProhibitManyArgs)
my ( $fp, $parm, $buffer, $len, $image, $offset, $must_buffer ) = @_;
if ($must_buffer) {
# We're either scanning a multi-frame image or the
# scanner doesn't know what the eventual image height
# will be (common for hand-held scanners). In either
# case, we need to buffer all data before we can write
# the image
if ($parm->{format} == SANE_FRAME_RED
or $parm->{format} == SANE_FRAME_GREEN
or $parm->{format} == SANE_FRAME_BLUE )
{
for ( my $i = 0 ; $i < $len ; ++$i ) {
$image->{data}[ $offset + 3 * $i ] = substr( $buffer, $i, 1 );
}
$offset += 3 * $len;
}
elsif ( $parm->{format} == SANE_FRAME_RGB
or $parm->{format} == SANE_FRAME_GRAY )
{
for ( my $i = 0 ; $i < $len ; ++$i ) {
$image->{data}[ $offset + $i ] = substr( $buffer, $i, 1 );
}
$offset += $len;
}
else {
# optional frametypes are never buffered
printf STDERR "$prog_name: ERROR: trying to buffer %s frametype\n",
sane_strframe( $parm->{format} );
}
}
else {
print $fp $buffer;
}
return $offset;
}
sub write_buffer {
my ( $fp, $image, $parm ) = @_;
if ( $parm->{lines} > 0 ) {
$image->{height} = $parm->{lines};
}
else {
$image->{height} = @{ $image->{data} } / $parm->{pixels_per_line};
$image->{height} /= 3
if ( $parm->{format} == SANE_FRAME_RED
or $parm->{format} == SANE_FRAME_GREEN
or $parm->{format} == SANE_FRAME_BLUE );
}
if ( $raw == SANE_FALSE ) {
# if we're writing raw, we skip the header
write_pnm_header_to_file( $fp, $parm->{format}, $parm->{pixels_per_line},
$image->{height}, $parm->{depth} );
}
for ( @{ $image->{data} } ) { print $fp $_; }
return;
}
sub scan_docs {
my ( $start, $end, $outfmt, $script ) = @_;
$Sane::_status = ## no critic (ProhibitPackageVars ProtectPrivateVars)
SANE_STATUS_GOOD;
my $scannedPages = 0;
while ( $end < 0 || $start <= $end ) {
#!!! buffer overflow; need protection
my $fname = sprintf( $outfmt, $start );
# does the filename already exist?
if ( $no_overwrite and -r $fname ) {
$Sane::_status = ## no critic (ProhibitPackageVars ProtectPrivateVars)
SANE_STATUS_INVAL;
print STDERR "Filename $fname already exists; will not overwrite\n";
}
# Scan the document
scan_it_raw( $fname, $raw, $script ) if ( $Sane::STATUS == SANE_STATUS_GOOD );
# Any scan errors?
if ( $Sane::STATUS == SANE_STATUS_NO_DOCS ) {
# out of paper in the hopper; this is our normal exit
$Sane::_status = ## no critic (ProhibitPackageVars ProtectPrivateVars)
SANE_STATUS_GOOD;
last;
}
elsif ( $Sane::STATUS == SANE_STATUS_EOF ) {
# done with this doc
$Sane::_status = ## no critic (ProhibitPackageVars ProtectPrivateVars)
SANE_STATUS_GOOD;
print STDERR "Scanned document $fname\n";
$scannedPages++;
$start++;
}
else {
# unexpected error
print STDERR "$Sane::STATUS\n";
last;
}
}
print STDERR "Scanned $scannedPages pages\n";
return;
}
sub process_arguments {
# re-enable error printing and arg permutation
Getopt::Long::Configure('no_pass_through');
# There seems to be a bug in Getopt::Long 2.37 where l is treated as L whilst
# l is not in @args. Therefore the workaround is to rename l to m for the first
# scan and back to l for the second.
for (@ARGV) {
$_ = '-l' if ( $_ eq '-m' );
$_ = '-t' if ( $_ eq '-u' );
}
my @ARGV_old = @ARGV;
exit 1 if ( !GetOptions(@args) );
# As it isn't possible to get the argument order from Getopt::Long 2.37, do
# this myself
for (@ARGV_old) {
my $ch;
if (/--(.*)/x) {
$ch = $1;
my $i = index( $ch, '=' );
$ch = substr( $ch, 0, $i ) if ( $i > -1 );
}
elsif (/-(.)/x) {
$ch = $1;
}
else {
next;
}
if ( defined $options{$ch} ) {
given ($ch) {
when ('x') {
$window_val_user[0] = 1;
( $window_val[0] ) = parse_vector( $window_option[0], $options{x} );
}
when ('y') {
$window_val_user[1] = 1;
( $window_val[1] ) = parse_vector( $window_option[1], $options{y} );
}
when ('l') { # tl-x
process_backend_option( $device, $window[2], $options{l} );
}
when ('t') { # tl-y
process_backend_option( $device, $window[3], $options{t} );
}
default {
process_backend_option( $device, $option_number{$ch}, $options{$ch} );
}
}
}
}
for ( my $index = 0 ; $index < 2 ; ++$index ) {
if ( $window[$index] and defined( $window_val[$index] ) ) {
my $val = $window_val[$index] - 1;
if ( $window[ $index + 2 ] ) {
my $pos = $device->get_option( $window[ $index + 2 ] );
$val = $pos + $window_val[$index] if ( defined $pos );
}
set_option( $device, $window[$index], $val );
}
}
return;
}
sub print_options {
printf "\nOptions specific to device `%s':\n", $devname;
for ( my $i = 0 ; $i < $num_dev_options ; ++$i ) {
my $short_name = '';
my $opt = 0;
for ( my $j = 0 ; $j < 4 ; ++$j ) {
if ( $i == $window[$j] ) {
$short_name = substr( "xylt", $j, 1 );
$opt = $window_option[$j] if ( $j < 2 );
}
}
$opt = $device->get_option_descriptor($i) if ( !$opt );
printf " %s:\n", $opt->{title} if ( $opt->{type} == SANE_TYPE_GROUP );
next if ( !( $opt->{cap} & SANE_CAP_SOFT_SELECT ) );
print_option( $device, $i, $short_name );
}
print "\n" if ($num_dev_options);
return;
}
sub list_device_names {
printf
"Type ``$prog_name --help -d DEVICE'' to get list of all options for DEVICE.\n\nList of available devices:";
my @device_list = Sane->get_devices;
if ( $Sane::STATUS == SANE_STATUS_GOOD ) {
my $column = 80;
foreach (@device_list) {
if ( $column + length( $_->{name} ) + 1 >= 80 ) {
printf "\n ";
$column = 4;
}
if ( $column > 4 ) {
print ' ';
$column += 1;
}
print $_->{name};
$column += length( $_->{name} );
}
}
print "\n";
return;
}
# There seems to be a bug in Getopt::Long 2.37 where l is treated as L whilst
# l is not in @args. Therefore the workaround is to rename l to m for the first
# scan and back to l for the second.
for (@ARGV) {
$_ = '-m' if ( $_ eq '-l' );
$_ = '-u' if ( $_ eq '-t' );
}
# make a first pass through the options with error printing and argument
# permutation disabled:
GetOptions(@args);
if ( defined $options{L} ) {
my @device_list = Sane->get_devices;
if ( $Sane::STATUS != SANE_STATUS_GOOD ) {
print STDERR "$prog_name: sane_get_devices() failed: $Sane::STATUS\n";
exit(1);
}
foreach (@device_list) {
printf "device `%s' is a %s %s %s\n", $_->{name}, $_->{vendor},
$_->{model}, $_->{type};
}
printf "\nNo scanners were identified. If you were expecting "
. "something different,\ncheck that the scanner is plugged "
. "in, turned on and detected by the\nsane-find-scanner tool "
. "(if appropriate). Please read the documentation\nwhich came "
. "with this software (README, FAQ, manpages).\n"
if ( $#device_list == -1 );
printf "default device is `%s'\n", $ENV{'SANE_DEFAULT_DEVICE'}
if ( defined( $ENV{'SANE_DEFAULT_DEVICE'} ) );
exit(0);
}
if ( defined( $options{V} ) ) {
printf "$prog_name (sane-backends) %s\n", Sane->get_version;
exit(0);
}
if ($help) {
print <<"EOS";
Usage: $prog_name [OPTION]...
Start image acquisition on a scanner device and write image data to
output files.
[ -d | --device-name ] use a given scanner device.
[ -h | --help ] display this help message and exit.
[ -L | --list-devices ] show available scanner devices.
[ -v | --verbose ] give even more status messages.
[ -V | --version ] print version information.
[ -N | --no-overwrite ] don't overwrite existing files.
[ -o | --output-file ] name of file to write image data
(\%d replacement in output file name).
[ -S | --scan-script ] name of script to run after every scan.
[ --script-wait ] wait for scripts to finish before exit
[ -s | --start-count ] page count of first scanned image.
[ -e | --end-count ] last page number to scan.
[ -r | --raw ] write raw image data to file.
EOS
}
if ( !$devname ) {
# If no device name was specified explicitly,
# we open the first device we find (if any):
my @device_list = Sane->get_devices;
if ( $Sane::STATUS != SANE_STATUS_GOOD ) {
print STDERR "$prog_name: sane_get_devices() failed: $Sane::STATUS\n";
exit(1);
}
if ( $#device_list == -1 ) {
print STDERR "$prog_name: no SANE devices found\n";
exit(1);
}
$devname = $device_list[0]{name};
}
$device = Sane::Device->open($devname);
if ( $Sane::STATUS != SANE_STATUS_GOOD ) {
print STDERR "$prog_name: open of device $devname failed: $Sane::STATUS\n";
if ($help) {
undef $device;
}
else {
exit(1);
}
}
if ( defined($device) ) {
fetch_options($device);
process_arguments();
if ($help) {
print_options();
}
}
if ($help) {
list_device_names();
exit(0);
}
local $SIG{HUP} = \&sighandler;
local $SIG{INT} = \&sighandler;
local $SIG{PIPE} = \&sighandler;
local $SIG{TERM} = \&sighandler;
scan_docs( $startNum, $endNum, $outputFile, $scanScript );
exit $Sane::STATUS;
__END__
=head1 NAME
scanadf - acquire multiple images from a scanner equipped with an ADF
=head1 SYNOPSIS
B
B<[ -d | --device-name>
I
B<[ -h | --help ]>
B<[ -L | --list-devices ]>
B<[ -v | --verbose ]>
B<[ -V | --version ]>
B<[ -o | --output-file>
I
B<[ -N | --no-overwrite ]>
B<[ -S | --scan-script>
I
B<[ --script-wait ] >
B<[ -s | --start-count>
I
B<[ -e | --end-count>
I
B<[ -r | --raw ]>
I<[ device-specific-options ]>
=head1 DESCRIPTION
B
is a command-line interface to control image acquisition devices which
are capable of returning a series of images (e.g. a scanner with an
automatic document feeder (ADF)). The device is controlled via
command-line options. After command-line processing,
B
normally proceeds to acquire a series of images until the device returns
the
B
status code.
The images are written to output files, specified by the
B<--output-file>
option. These files are typically written in one of the PNM (portable aNyMaP)
formats (PBM for black-and-white images, PGM for grayscale images,
and PPM for color images). Several optional frame formats (SANE_FRAME_JPEG,
SANE_FRAME_G31D, SANE_FRAME_G32D, SANE_FRAME_G42D, and SANE_FRAME_TEXT)
are supported. In each case, the data is written out to the output file
as-is without a header. Unrecognized frame formats are handled in
the same way, although a warning message is printed in verbose mode.
Typically, the optional frame formats are used in conjunction with a scan
script (specified by the
B<--scanscript>
option) which is invoked for each acquired image. The script is provided
with a series of environment variables which describe the parameters
and format of the image file.
B
accesses image acquisition devices through the SANE (Scanner Access
Now Easy) interface and can thus support any device for which there
exists a SANE backend (try "apropos sane\-" to get a list of available
backends).
=head1 OPTIONS
The
B<-d>
or
B<--device-name>
options must be followed by a SANE device-name. A (partial) list of
available devices can be obtained with the
B<--list-devices>
option (see below). If no device-name is specified explicitly,
B
will attempt to open the first available device.
The
B<-h>
or
B<--help>
options request help information. The information is printed on
standard output and in this case, no attempt will be made to acquire
an image.
The
B<-L>
or
B<--list-devices>
option requests a (partial) list of devices that are available. The
list is not complete since some devices may be available, but are not
listed in any of the configuration files (which are typically stored
in directory /etc/sane.d). This is particularly the case when
accessing scanners through the network. If a device is not listed in
a configuration file, the only way to access it is by its full device
name. You may need to consult your system administrator to find out
the names of such devices.
The
B<-v>
or
B<--verbose>
options increase the verbosity of the operation of
B
The option may be specified repeatedly, each time increasing the verbosity
level.
The
B<-V>
or
B<--version>
option requests that
B
print the program and package name, as well as the version number of
the SANE distribution that it came with.
The
B<-o>
or
B<--output-file>
option specifies a format string used to generate the name of file to
write the image data to. You can use %d replacement in the output file
name; this will be replaced with the current page number. The default
format string is image-%04d.
The
B<-N>
or
B<--no-overwrite>
option prevents
B
from overwriting existing image files.
The
B<-S>
or
B<--scan-script>
option specifies the name of script to run after each scanned image
is acquired. The script receives the name of the image output file
as its first and only command line argument. Additionally the scan
script can reference the following environment variables to get
information about the parameters of the image.
=over
=item B
- the image resolution (in DPI)
=item B
- the image width (in pixels)
=item B
- the image height (in pixels)
=item B
- the image bit-depth (in bits)
=item B
- a string representing the image format (e.g. gray, g42d, text, etc)
=item B
- the numeric image format identifier
=back
If the
B<--scipt-wait>
option is given, scanadf will wait until all scan-scripts have been finished before
exiting. That will be useful if scanadf is used in conjunction with tools to modify
the scanned images.
The
B<-s>
or
B<--start-count>
option specifies the page number of first scanned image.
The
B<-e>
or
B<--end-count>
option specifies the last page number to scan. Using this option,
you can request a specific number of pages to be scanned, rather than
scanning until there are no more images available.
The
B<-r>
or
B<--raw>
option specifies that the raw image data be written to the output file
as-is without interpretation. This disables the writing of the PNM
header for basic frame types. This feature is usually used in
conjunction with the
B<--scan-script>
option where the scan script uses the environment variables to
understand the format and parameters of the image and converts
the file to a more useful format. NOTE: With support for the
optional frame types and the default handling of unrecognized
frametypes, this option becomes less and less useful.
As you might imagine, much of the power of
B
comes from the fact that it can control any SANE backend. Thus, the
exact set of command-line options depends on the capabilities of the
selected device. To see the options for a device named
I
invoke
B
via a command-line of the form:
=over
scanadf --help --device
I
=back
The documentation for the device-specific options printed by
B<--help>
is explained in the manual page for
B
=head1 FILES
=over
=item I
This directory holds various configuration files. For details, please
refer to the manual pages listed below.
=back
=head1 "SEE ALSO"
scanimage(1), xscanimage(1), sane(7)
=head1 AUTHOR
Transliterated from the C original by Jeffrey Ratcliffe.
=head1 BUGS
All the bugs of scanadf and much, much more.
This program relies on the backend to return the
B
status code when the automatic document feeder is out of paper. Use of
this program with backends that do not support ADFs (e.g. flatbed scanners)
will likely result in repeated scans of the same document. In this
case, it is essential to use the start-count and end-count to
control the number of images acquired.
Only a subset of the SANE backends support feeders and return
SANE_STATUS_NO_DOCS appropriately. Backends which are known to
work at this time are:
=over
=item B
- Bell+Howell Copiscan II series scanners.
=item B
- Hewlett Packard scanners. A patch to the sane-hp backend
is necessary. The --scantype=ADF option must be specified (earlier
versions of the backend used the --scan-from-adf option, instead).
=item B
- UMAX scanners. Support exists in build 12 and later.
The --source="Automatic Document Feeder" option must be specified.
=back
gscan2pdf-1.2.3/scanner.svg 0000644 0001750 0001750 00000065136 12053230657 014162 0 ustar jeff jeff
gscan2pdf-1.2.3/scanners/ 0000755 0001750 0001750 00000000000 12271546566 013624 5 ustar jeff jeff gscan2pdf-1.2.3/scanners/hp_scanjet6390c 0000644 0001750 0001750 00000010356 12053230657 016344 0 ustar jeff jeff Usage: scanimage [OPTION]...
Start image acquisition on a scanner device and write PNM image data to standard output.
-d, --device-name=DEVICE use a given scanner device (e.g. hp:/dev/scanner)
--format=pnm|tiff file format of output file
-i, --icc-profile=PROFILE include this ICC profile into TIFF file
-L, --list-devices show available scanner devices
-f, --formatted-device-list=FORMAT similar to -L, but the FORMAT of the output
can be specified: %d (device name), %v (vendor),
%m (model), %t (type), and %i (index number)
-b, --batch[=FORMAT] working in batch mode, FORMAT is `out%d.pnm' or
`out%d.tif' by default depending on --format
--batch-start=# page number to start naming files with
--batch-count=# how many pages to scan in batch mode
--batch-increment=# increase number in filename by an amount of #
--batch-double increment page number by two for 2sided originals
being scanned in a single sided scanner
--batch-prompt ask for pressing a key before scanning a page
--accept-md5-only only accept authorization requests using md5
-p, --progress print progress messages
-n, --dont-scan only set options, don't actually scan
-T, --test test backend thoroughly
-h, --help display this help message and exit
-v, --verbose give even more status messages
-B, --buffer-size change default input buffersize
-V, --version print version information
Options specific to device `hp:libusb:001:003':
Scan Mode:
--preview[=(yes|no)] [no]
Request a preview-quality scan.
--mode Lineart|Halftone|Grayscale|Color [Lineart]
Selects the scan mode (e.g., lineart, monochrome, or color).
--resolution 12..3200dpi (in steps of 1) [300]
Sets the resolution of the scanned image.
Enhancement:
--brightness -127..127 (in steps of 1) [0]
Controls the brightness of the acquired image.
--contrast -127..127 (in steps of 1) [0]
Controls the contrast of the acquired image.
--auto-threshold[=(yes|no)] [no]
Enable automatic determination of threshold for line-art scans.
Advanced Options:
--custom-gamma[=(yes|no)] [no]
Determines whether a builtin or a custom gamma-table should be used.
--gamma-table 0..255,... (in steps of 1.52588e-05) [inactive]
Gamma-correction table. In color mode this option equally affects the
red, green, and blue channels simultaneously (i.e., it is an intensity
gamma table).
--matrix-type Auto|NTSC Gray|Red|Green|Blue [Auto]
Set the scanners color matrix.
--matrix-rgb -3.99219..3.99219,... (in steps of 1.52588e-05) [inactive]
Custom color matrix.
--halftone-pattern Coarse|Fine|Bayer|Vertical|Horizontal|Custom [inactive]
Defines the halftoning (dithering) pattern for scanning halftoned
images.
--speed Auto|Slow|Normal|Fast|Extra Fast [Auto]
Determines the speed at which the scan proceeds.
--depth 1 [inactive]
Number of bits per sample, typical values are 1 for "line-art" and 8
for multibit scans.
--output-8bit[=(yes|no)] [inactive]
Use bit depth greater eight internally, but output only eight bits.
--source Normal|ADF|XPA [Normal]
Selects the scan source (such as a document-feeder).
--button-wait[=(yes|no)] [no]
Wait to scan for front-panel button push.
--lamp-off []
Shut off scanner lamp.
--change-document []
Change Document.
Geometry:
-l 0..215.788mm (in steps of 1.52588e-05) [0]
Top-left x position of scan area.
-t 0..296.888mm (in steps of 1.52588e-05) [0]
Top-left y position of scan area.
-x 0..215.788mm (in steps of 1.52588e-05) [215.788]
Width of scan-area.
-y 0..296.888mm (in steps of 1.52588e-05) [296.888]
Height of scan-area.
--mirror-horizontal Off|On [Off]
Mirror image horizontally.
--mirror-vertical Off|On [Off]
Mirror image vertically.
Type ``scanimage --help -d DEVICE'' to get list of all options for DEVICE.
List of available devices:
hp:libusb:001:003
gscan2pdf-1.2.3/scanners/hp_v40 0000644 0001750 0001750 00000007413 12053230657 014641 0 ustar jeff jeff Usage: scanimage [OPTION]...
Start image acquisition on a scanner device and write PNM image data to
standard output.
-d, --device-name=DEVICE use a given scanner device (e.g . hp:/dev/scanner)
--format=pnm|tiff file format of output file
-i, --icc-profile=PROFILE include this ICC profile into TIFF file
-L, --list-devices show available scanner devices
-f, --formatted-device-list=FORMAT similar to -L, but the FORMAT of the output
can be specified: %d (device name), %v (vendor),
%m (model), %t (type), and %i (index number)
-b, --batch[=FORMAT] working in batch mode, FORMAT is `out%d.pnm' or
`out%d.tif' by default depending on --format
--batch-start=# page number to start naming files with
--batch-count=# how many pages to scan in batch mode
--batch-increment=# increase number in filename by an amount of #
--batch-double increment page number by two for 2sided originals
being scanned in a single sided scanner
--batch-prompt ask for pressing a key before scanning a page
--accept-md5-only only accept authorization requests using md5
-p, --progress print progress messages
-n, --dont-scan only set options, don't actually scan
-T, --test test backend thoroughly
-h, --help display this help message and exit
-v, --verbose give even more status messages
-B, --buffer-size change default input buffersize
-V, --version print version information
Options specific to device `hpaio:/usb/OfficeJet_V40?serial=MY16QB30YRWN':
Scan mode:
--mode Lineart|Grayscale|Color [Color]
Selects the scan mode (e.g., lineart, monochrome, or color).
--resolution 75..600dpi [75]
Sets the resolution of the scanned image.
Advanced:
--contrast 0..100 [inactive]
Controls the contrast of the acquired image.
--compression None|JPEG [JPEG]
Selects the scanner compression method for faster scans, possibly at
the expense of image quality.
--jpeg-compression-factor 0..100 [10]
Sets the scanner JPEG compression factor. Larger numbers mean better
compression, and smaller numbers mean better image quality.
--batch-scan[=(yes|no)] [no]
Guarantees that a "no documents" condition will be returned after the
last scanned page, to prevent endless flatbed scans after a batch scan.
For some models, option changes in the middle of a batch scan don't
take effect until after the last page.
--source ADF [ADF]
Selects the desired scan source for models with both flatbed and
automatic document feeder (ADF) capabilities. The "Auto" setting means
that the ADF will be used if it's loaded, and the flatbed (if present)
will be used otherwise.
--duplex[=(yes|no)] [inactive]
Enables scanning on both sides of the page for models with
duplex-capable document feeders. For pages printed in "book"-style
duplex mode, one side will be scanned upside-down. This feature is
experimental.
Geometry:
--length-measurement Unknown|Approximate|Padded [Padded]
Selects how the scanned image length is measured and reported, which
is impossible to know in advance for scrollfed scans.
-l 0..215.9mm [0]
Top-left x position of scan area.
-t 0..381mm [0]
Top-left y position of scan area.
-x 0..215.9mm [215.9]
Width of scan-area.
-y 0..381mm [381]
Height of scan-area.
Type ``scanimage --help -d DEVICE'' to get list of all options for DEVICE.
List of available devices:
hpaio:/usb/OfficeJet_V40?serial=MY16QB30YRWN
gscan2pdf-1.2.3/scanners/officejet_5500 0000644 0001750 0001750 00000007475 12053230657 016160 0 ustar jeff jeff Usage: scanimage [OPTION]...
Start image acquisition on a scanner device and write PNM image data to standard output.
-d, --device-name=DEVICE use a given scanner device (e.g. hp:/dev/scanner)
--format=pnm|tiff file format of output file
-i, --icc-profile=PROFILE include this ICC profile into TIFF file
-L, --list-devices show available scanner devices
-f, --formatted-device-list=FORMAT similar to -L, but the FORMAT of the output
can be specified: %d (device name), %v (vendor),
%m (model), %t (type), and %i (index number)
-b, --batch[=FORMAT] working in batch mode, FORMAT is `out%d.pnm' or
`out%d.tif' by default depending on --format
--batch-start=# page number to start naming files with
--batch-count=# how many pages to scan in batch mode
--batch-increment=# increase number in filename by an amount of #
--batch-double increment page number by two for 2sided originals
being scanned in a single sided scanner
--batch-prompt ask for pressing a key before scanning a page
--accept-md5-only only accept authorization requests using md5
-p, --progress print progress messages
-n, --dont-scan only set options, don't actually scan
-T, --test test backend thoroughly
-h, --help display this help message and exit
-v, --verbose give even more status messages
-B, --buffer-size change default input buffersize
-V, --version print version information
Options specific to device `hpaio:/usb/officejet_5500_series?serial=MY42QF209H96':
Scan mode:
--mode Lineart|Grayscale|Color [Color]
Selects the scan mode (e.g., lineart, monochrome, or color).
--resolution 75..600dpi [75]
Sets the resolution of the scanned image.
Advanced:
--contrast 0..100 [inactive]
Controls the contrast of the acquired image.
--compression None|JPEG [JPEG]
Selects the scanner compression method for faster scans, possibly at
the expense of image quality.
--jpeg-compression-factor 0..100 [10]
Sets the scanner JPEG compression factor. Larger numbers mean better
compression, and smaller numbers mean better image quality.
--batch-scan[=(yes|no)] [no]
Guarantees that a "no documents" condition will be returned after the
last scanned page, to prevent endless flatbed scans after a batch scan.
For some models, option changes in the middle of a batch scan don't
take effect until after the last page.
--source Auto|Flatbed|ADF [Auto]
Selects the desired scan source for models with both flatbed and
automatic document feeder (ADF) capabilities. The "Auto" setting means
that the ADF will be used if it's loaded, and the flatbed (if present)
will be used otherwise.
--duplex[=(yes|no)] [inactive]
Enables scanning on both sides of the page for models with
duplex-capable document feeders. For pages printed in "book"-style
duplex mode, one side will be scanned upside-down. This feature is
experimental.
Geometry:
--length-measurement Unknown|Approximate|Padded [Padded]
Selects how the scanned image length is measured and reported, which
is impossible to know in advance for scrollfed scans.
-l 0..215.9mm [0]
Top-left x position of scan area.
-t 0..381mm [0]
Top-left y position of scan area.
-x 0..215.9mm [215.9]
Width of scan-area.
-y 0..381mm [381]
Height of scan-area.
Type ``scanimage --help -d DEVICE'' to get list of all options for DEVICE.
List of available devices:
v4l:/dev/video1 v4l:/dev/video0
hpaio:/usb/officejet_5500_series?serial=MY42QF209H96
gscan2pdf-1.2.3/scanners/umax 0000644 0001750 0001750 00000017303 12053230657 014512 0 ustar jeff jeff Usage: scanimage [OPTION]...
Start image acquisition on a scanner device and write PNM image data to
standard output.
Parameters are separated by a blank from single-character options (e.g.
-d epson) and by a "=" from multi-character options (e.g. --device-name=epson).
-d, --device-name=DEVICE use a given scanner device (e.g. hp:/dev/scanner)
--format=pnm|tiff file format of output file
-i, --icc-profile=PROFILE include this ICC profile into TIFF file
-L, --list-devices show available scanner devices
-f, --formatted-device-list=FORMAT similar to -L, but the FORMAT of the output
can be specified: %d (device name), %v (vendor),
%m (model), %t (type), and %i (index number)
-b, --batch[=FORMAT] working in batch mode, FORMAT is `out%d.pnm' or
`out%d.tif' by default depending on --format
--batch-start=# page number to start naming files with
--batch-count=# how many pages to scan in batch mode
--batch-increment=# increase number in filename by an amount of #
--batch-double increment page number by two for 2sided originals
being scanned in a single sided scanner
--batch-prompt ask for pressing a key before scanning a page
--accept-md5-only only accept authorization requests using md5
-p, --progress print progress messages
-n, --dont-scan only set options, don't actually scan
-T, --test test backend thoroughly
-h, --help display this help message and exit
-v, --verbose give even more status messages
-B, --buffer-size change default input buffersize
-V, --version print version information
Options specific to device `umax:/dev/sg2':
Scan Mode:
--mode Lineart|Gray|Color [Color]
Selects the scan mode (e.g., lineart, monochrome, or color).
--source Flatbed [Flatbed]
Selects the scan source (such as a document-feeder).
--resolution 5..300dpi (in steps of 5) [100]
Sets the resolution of the scanned image.
--y-resolution 5..600dpi (in steps of 5) [inactive]
Sets the vertical resolution of the scanned image.
--resolution-bind[=(yes|no)] [yes]
Use same values for X and Y resolution
--negative[=(yes|no)] [inactive]
Swap black and white
Geometry:
-l 0..215.9mm [0]
Top-left x position of scan area.
-t 0..297.18mm [0]
Top-left y position of scan area.
-x 0..215.9mm [215.9]
Width of scan-area.
-y 0..297.18mm [297.18]
Height of scan-area.
Enhancement:
--depth 8bit [8]
Number of bits per sample, typical values are 1 for "line-art" and 8
for multibit scans.
--quality-cal[=(yes|no)] [yes]
Do a quality white-calibration
--double-res[=(yes|no)] [inactive]
Use lens that doubles optical resolution
--warmup[=(yes|no)] [inactive]
Warmup lamp before scanning
--rgb-bind[=(yes|no)] [no]
In RGB-mode use same values for each color
--brightness -100..100% (in steps of 1) [inactive]
Controls the brightness of the acquired image.
--contrast -100..100% (in steps of 1) [inactive]
Controls the contrast of the acquired image.
--threshold 0..100% [inactive]
Select minimum-brightness to get a white point
--highlight 0..100% [inactive]
Selects what radiance level should be considered "white".
--highlight-r 0..100% [100]
Selects what red radiance level should be considered "full red".
--highlight-g 0..100% [100]
Selects what green radiance level should be considered "full green".
--highlight-b 0..100% [100]
Selects what blue radiance level should be considered "full blue".
--shadow 0..100% [inactive]
Selects what radiance level should be considered "black".
--shadow-r 0..100% [inactive]
Selects what red radiance level should be considered "black".
--shadow-g 0..100% [inactive]
Selects what green radiance level should be considered "black".
--shadow-b 0..100% [inactive]
Selects what blue radiance level should be considered "black".
--analog-gamma 1..2 (in steps of 0.00999451) [inactive]
Analog gamma-correction
--analog-gamma-r 1..2 (in steps of 0.00999451) [inactive]
Analog gamma-correction for red
--analog-gamma-g 1..2 (in steps of 0.00999451) [inactive]
Analog gamma-correction for green
--analog-gamma-b 1..2 (in steps of 0.00999451) [inactive]
Analog gamma-correction for blue
--custom-gamma[=(yes|no)] [yes]
Determines whether a builtin or a custom gamma-table should be used.
--gamma-table 0..255,...
Gamma-correction table. In color mode this option equally affects the
red, green, and blue channels simultaneously (i.e., it is an intensity
gamma table).
--red-gamma-table 0..255,...
Gamma-correction table for the red band.
--green-gamma-table 0..255,...
Gamma-correction table for the green band.
--blue-gamma-table 0..255,...
Gamma-correction table for the blue band.
--halftone-size 2|4|6|8|12pel [inactive]
Sets the size of the halftoning (dithering) pattern used when scanning
halftoned images.
--halftone-pattern 0..255 [inactive]
Defines the halftoning (dithering) pattern for scanning halftoned
images.
Advanced:
--cal-exposure-time 0..0us [inactive]
Define exposure-time for calibration
--cal-exposure-time-r 0..0us [inactive]
Define exposure-time for red calibration
--cal-exposure-time-g 0..0us [inactive]
Define exposure-time for green calibration
--cal-exposure-time-b 0..0us [inactive]
Define exposure-time for blue calibration
--scan-exposure-time 0..0us [inactive]
Define exposure-time for scan
--scan-exposure-time-r 0..0us [inactive]
Define exposure-time for red scan
--scan-exposure-time-g 0..0us [inactive]
Define exposure-time for green scan
--scan-exposure-time-b 0..0us [inactive]
Define exposure-time for blue scan
--disable-pre-focus[=(yes|no)] [inactive]
Do not calibrate focus
--manual-pre-focus[=(yes|no)] [inactive]
--fix-focus-position[=(yes|no)] [inactive]
--lens-calibration-in-doc-position[=(yes|no)] [inactive]
Calibrate lens focus in document position
--holder-focus-position-0mm[=(yes|no)] [inactive]
Use 0mm holder focus position instead of 0.6mm
--cal-lamp-density 0..100% [inactive]
Define lamp density for calibration
--scan-lamp-density 0..100% [inactive]
Define lamp density for scan
--select-exposure-time[=(yes|no)] [inactive]
Enable selection of exposure-time
--select-calibration-exposure-time[=(yes|no)] [inactive]
Allow different settings for calibration and scan exposure times
--select-lamp-density[=(yes|no)] [inactive]
Enable selection of lamp density
--lamp-on [inactive]
Turn on scanner lamp
--lamp-off [inactive]
Turn off scanner lamp
--lamp-off-at-exit[=(yes|no)] [inactive]
Turn off lamp when program exits
--batch-scan-start[=(yes|no)] [inactive]
set for first scan of batch
--batch-scan-loop[=(yes|no)] [inactive]
set for middle scans of batch
--batch-scan-end[=(yes|no)] [inactive]
set for last scan of batch
--batch-scan-next-tl-y 0..297.18mm [inactive]
Set top left Y position for next scan
--preview[=(yes|no)] [no]
Request a preview-quality scan.
Type ``scanimage --help -d DEVICE'' to get list of all options for DEVICE.
List of available devices:
v4l:/dev/video0 umax:/dev/sg2
gscan2pdf-1.2.3/scanners/officejet_5500.color 0000644 0001750 0001750 00000006215 12053230657 017264 0 ustar jeff jeff Usage: scanimage [OPTION]...
Start image acquisition on a scanner device and write PNM image data to
standard output.
-d, --device-name=DEVICE use a given scanner device (e.g. hp:/dev/scanner)
--format=pnm|tiff file format of output file
-i, --icc-profile=PROFILE include this ICC profile into TIFF file
-L, --list-devices show available scanner devices
-f, --formatted-device-list=FORMAT similar to -L, but the FORMAT of the output
can be specified: %d (device name), %v (vendor),
%m (model), %t (type), and %i (index number)
-b, --batch[=FORMAT] working in batch mode, FORMAT is `out%d.pnm' or
`out%d.tif' by default depending on --format
--batch-start=# page number to start naming files with
--batch-count=# how many pages to scan in batch mode
--batch-increment=# increase number in filename by an amount of #
--batch-double increment page number by two for 2sided originals
being scanned in a single sided scanner
--batch-prompt ask for pressing a key before scanning a page
--accept-md5-only only accept authorization requests using md5
-p, --progress print progress messages
-n, --dont-scan only set options, don't actually scan
-T, --test test backend thoroughly
-h, --help display this help message and exit
-v, --verbose give even more status messages
-B, --buffer-size change default input buffersize
-V, --version print version information
Options specific to device `hpaio:/usb/officejet_5500_series?serial=MY42QF209H96':
Scan mode:
--mode Lineart|Gray|Color [Color]
Selects the scan mode (e.g., lineart, monochrome, or color).
--resolution 75..600dpi [75]
Sets the resolution of the scanned image.
Advanced:
--contrast 0..100 [inactive]
Controls the contrast of the acquired image.
--compression None|JPEG [JPEG]
Selects the scanner compression method for faster scans, possibly at
the expense of image quality.
--jpeg-quality 0..100 [10]
Sets the scanner JPEG compression factor. Larger numbers mean better
compression, and smaller numbers mean better image quality.
--batch-scan[=(yes|no)] [no]
Enables continuous scanning with automatic document feeder (ADF).
--source Auto|Flatbed|ADF [Auto]
Selects the scan source (such as a document-feeder).
Geometry:
--length-measurement Unknown|Approximate|Padded [Padded]
Selects how the scanned image length is measured and reported, which
is impossible to know in advance for scrollfed scans.
-l 0..215.9mm [0]
Top-left x position of scan area.
-t 0..381mm [0]
Top-left y position of scan area.
-x 0..215.9mm [215.9]
Width of scan-area.
-y 0..381mm [381]
Height of scan-area.
Type ``scanimage --help -d DEVICE'' to get list of all options for DEVICE.
List of available devices:
v4l:/dev/video2 v4l:/dev/video1 v4l:/dev/video0
hpaio:/usb/officejet_5500_series?serial=MY42QF209H96
gscan2pdf-1.2.3/scanners/officejet_5500.scanadf 0000644 0001750 0001750 00000006410 12053230657 017542 0 ustar jeff jeff Usage: scanadf [OPTION]...
Start image acquisition on a scanner device and write image data to
output files.
[ -d | --device-name ] use a given scanner device.
[ -h | --help ] display this help message and exit.
[ -L | --list-devices ] show available scanner devices.
[ -v | --verbose ] give even more status messages.
[ -V | --version ] print version information.
[ -N | --no-overwrite ] don't overwrite existing files.
[ -o | --output-file ] name of file to write image data
(%d replacement in output file name).
[ -S | --scan-script ] name of script to run after every scan.
[ --script-wait ] wait for scripts to finish before exit
[ -s | --start-count ] page count of first scanned image.
[ -e | --end-count ] last page number to scan.
[ -r | --raw ] write raw image data to file.
Options specific to device `hpaio:/usb/officejet_5500_series?serial=MY42QF209H96':
Scan mode:
--mode Lineart|Grayscale|Color [Color]
Selects the scan mode (e.g., lineart, monochrome, or color).
--resolution 75..600dpi [75]
Sets the resolution of the scanned image.
Advanced:
--contrast 0..100 [inactive]
Controls the contrast of the acquired image.
--compression None|JPEG [JPEG]
Selects the scanner compression method for faster scans, possibly at
the expense of image quality.
--jpeg-compression-factor 0..100 [10]
Sets the scanner JPEG compression factor. Larger numbers mean better
compression, and smaller numbers mean better image quality.
--batch-scan[=(yes|no)] [no]
Guarantees that a "no documents" condition will be returned after the
last scanned page, to prevent endless flatbed scans after a batch scan.
For some models, option changes in the middle of a batch scan don't
take effect until after the last page.
--source Auto|Flatbed|ADF [Auto]
Selects the desired scan source for models with both flatbed and
automatic document feeder (ADF) capabilities. The "Auto" setting means
that the ADF will be used if it's loaded, and the flatbed (if present)
will be used otherwise.
--duplex[=(yes|no)] [inactive]
Enables scanning on both sides of the page for models with
duplex-capable document feeders. For pages printed in "book"-style
duplex mode, one side will be scanned upside-down. This feature is
experimental.
Geometry:
--length-measurement Unknown|Approximate|Padded [Padded]
Selects how the scanned image length is measured and reported, which
is impossible to know in advance for scrollfed scans.
-l 0..215.9mm [0]
Top-left x position of scan area.
-t 0..381mm [0]
Top-left y position of scan area.
-x 0..215.9mm [215.9]
Width of scan-area.
-y 0..381mm [381]
Height of scan-area.
Type ``scanadf --help -d DEVICE'' to get list of all options for DEVICE.
List of available devices:
hpaio:/usb/officejet_5500_series?serial=MY42QF209H96
hpaio:/usb/officejet_5500_series?serial=MY42QF209H96 v4l:/dev/video1
v4l:/dev/video0
gscan2pdf-1.2.3/scanners/hp_scanjet5470c.scanadf 0000644 0001750 0001750 00000003606 12053230657 017740 0 ustar jeff jeff Usage: scanadf [OPTION]...
Start image acquisition on a scanner device and write image data to
output files.
[ -d | --device-name ] use a given scanner device.
[ -h | --help ] display this help message and exit.
[ -L | --list-devices ] show available scanner devices.
[ -v | --verbose ] give even more status messages.
[ -V | --version ] print version information.
[ -N | --no-overwrite ] don't overwrite existing files.
[ -o | --output-file ] name of file to write image data
(%d replacement in output file name).
[ -S | --scan-script ] name of script to run after every scan.
[ --script-wait ] wait for scripts to finish before exit
[ -s | --start-count ] page count of first scanned image.
[ -e | --end-count ] last page number to scan.
[ -r | --raw ] write raw image data to file.
Options specific to device `hp5400:libusb:002:003':
Geometry:
-l 0..220mm (in steps of 1) [5]
Top-left x position of scan area.
-t 0..300mm (in steps of 1) [52]
Top-left y position of scan area.
-x 0..220mm (in steps of 1) [225]
Width of scan-area.
-y 0..300mm (in steps of 1) [352]
Height of scan-area.
--resolution 75|150|300|600|1200dpi [75]
Sets the resolution of the scanned image.
Image:
--red-gamma-table 0..65535,... (in steps of 1) [0]
Gamma-correction table for the red band.
--green-gamma-table 0..65535,... (in steps of 1) [0]
Gamma-correction table for the green band.
--blue-gamma-table 0..65535,... (in steps of 1) [0]
Gamma-correction table for the blue band.
Type ``scanadf --help -d DEVICE'' to get list of all options for DEVICE.
List of available devices:
hp5400:libusb:002:003
gscan2pdf-1.2.3/scanners/mustek 0000644 0001750 0001750 00000005522 12053230657 015050 0 ustar jeff jeff Usage: scanimage [OPTION]...
Start image acquisition on a scanner device and write PNM image data to
standard output.
-d, --device-name=DEVICE use a given scanner device (e.g. hp:/dev/scanner)
--format=pnm|tiff file format of output file
-i, --icc-profile=PROFILE include this ICC profile into TIFF file
-L, --list-devices show available scanner devices
-f, --formatted-device-list=FORMAT similar to -L, but the FORMAT of the output
can be specified: %d (device name), %v (vendor),
%m (model), %t (type), and %i (index number)
-b, --batch[=FORMAT] working in batch mode, FORMAT is `out%d.pnm' or
`out%d.tif' by default depending on --format
--batch-start=# page number to start naming files with
--batch-count=# how many pages to scan in batch mode
--batch-increment=# increase number in filename by an amount of #
--batch-double increment page number by two for 2sided originals
being scanned in a single sided scanner
--batch-prompt ask for pressing a key before scanning a page
--accept-md5-only only accept authorization requests using md5
-p, --progress print progress messages
-n, --dont-scan only set options, don't actually scan
-T, --test test backend thoroughly
-h, --help display this help message and exit
-v, --verbose give even more status messages
-B, --buffer-size change default input buffersize
-V, --version print version information
Options specific to device `mustek_usb2:libusb:001:003':
Scan Mode:
--mode Color48|Color24|Gray16|Gray8|Lineart [Color24]
Selects the scan mode (e.g., lineart, monochrome, or color).
--source Reflective|Positive|Negative [Reflective]
Selects the scan source (such as a document-feeder).
--resolution 1200|600|300|150|75dpi [300]
Sets the resolution of the scanned image.
--preview[=(yes|no)] [no]
Request a preview-quality scan.
Debugging Options:
--auto-warmup[=(yes|no)] [no]
Warm-up until the lamp's brightness is constant instead of insisting
on 40 seconds warm-up time.
Enhancement:
--threshold 0..255 [inactive]
Select minimum-brightness to get a white point
--gamma-value 0.00999451..5 (in steps of 0.00999451) [inactive]
Sets the gamma value of all channels.
Geometry:
-l 0..210.82mm [0]
Top-left x position of scan area.
-t 0..294.64mm [0]
Top-left y position of scan area.
-x 0..210.82mm [210.82]
Width of scan-area.
-y 0..294.64mm [294.64]
Height of scan-area.
Type ``scanimage --help -d DEVICE'' to get list of all options for DEVICE.
List of available devices:
mustek_usb2:libusb:001:003
gscan2pdf-1.2.3/scanners/test 0000644 0001750 0001750 00000021761 12237446454 014532 0 ustar jeff jeff Usage: scanimage [OPTION]...
Start image acquisition on a scanner device and write image data to
standard output.
Parameters are separated by a blank from single-character options (e.g.
-d epson) and by a "=" from multi-character options (e.g. --device-name=epson).
-d, --device-name=DEVICE use a given scanner device (e.g. hp:/dev/scanner)
--format=pnm|tiff file format of output file
-i, --icc-profile=PROFILE include this ICC profile into TIFF file
-L, --list-devices show available scanner devices
-f, --formatted-device-list=FORMAT similar to -L, but the FORMAT of the output
can be specified: %d (device name), %v (vendor),
%m (model), %t (type), %i (index number), and
%n (newline)
-b, --batch[=FORMAT] working in batch mode, FORMAT is `out%d.pnm' or
`out%d.tif' by default depending on --format
--batch-start=# page number to start naming files with
--batch-count=# how many pages to scan in batch mode
--batch-increment=# increase page number in filename by #
--batch-double increment page number by two, same as
--batch-increment=2
--batch-prompt ask for pressing a key before scanning a page
--accept-md5-only only accept authorization requests using md5
-p, --progress print progress messages
-n, --dont-scan only set options, don't actually scan
-T, --test test backend thoroughly
-A, --all-options list all available backend options
-h, --help display this help message and exit
-v, --verbose give even more status messages
-B, --buffer-size=# change input buffer size (in kB, default 32)
-V, --version print version information
Options specific to device `test:0':
Scan Mode:
--mode Gray|Color [Gray]
Selects the scan mode (e.g., lineart, monochrome, or color).
--depth 1|8|16 [8]
Number of bits per sample, typical values are 1 for "line-art" and 8
for multibit scans.
--hand-scanner[=(yes|no)] [no]
Simulate a hand-scanner. Hand-scanners do not know the image height a
priori. Instead, they return a height of -1. Setting this option
allows to test whether a frontend can handle this correctly. This
option also enables a fixed width of 11 cm.
--three-pass[=(yes|no)] [inactive]
Simulate a three-pass scanner. In color mode, three frames are
transmitted.
--three-pass-order RGB|RBG|GBR|GRB|BRG|BGR [inactive]
Set the order of frames in three-pass color mode.
--resolution 1..1200dpi (in steps of 1) [50]
Sets the resolution of the scanned image.
--source Flatbed|Automatic Document Feeder [Flatbed]
If Automatic Document Feeder is selected, the feeder will be 'empty'
after 10 scans.
Special Options:
--test-picture Solid black|Solid white|Color pattern|Grid [Solid black]
Select the kind of test picture. Available options:
Solid black: fills the whole scan with black.
Solid white: fills the whole scan with white.
Color pattern: draws various color test patterns depending on the mode.
Grid: draws a black/white grid with a width and height of 10 mm per
square.
--invert-endianess[=(yes|no)] [inactive]
Exchange upper and lower byte of image data in 16 bit modes. This
option can be used to test the 16 bit modes of frontends, e.g. if the
frontend uses the correct endianness.
--read-limit[=(yes|no)] [no]
Limit the amount of data transferred with each call to sane_read().
--read-limit-size 1..65536 (in steps of 1) [inactive]
The (maximum) amount of data transferred with each call to
sane_read().
--read-delay[=(yes|no)] [no]
Delay the transfer of data to the pipe.
--read-delay-duration 1000..200000us (in steps of 1000) [inactive]
How long to wait after transferring each buffer of data through the
pipe.
--read-return-value Default|SANE_STATUS_UNSUPPORTED|SANE_STATUS_CANCELLED|SANE_STATUS_DEVICE_BUSY|SANE_STATUS_INVAL|SANE_STATUS_EOF|SANE_STATUS_JAMMED|SANE_STATUS_NO_DOCS|SANE_STATUS_COVER_OPEN|SANE_STATUS_IO_ERROR|SANE_STATUS_NO_MEM|SANE_STATUS_ACCESS_DENIED [Default]
Select the return-value of sane_read(). "Default" is the normal
handling for scanning. All other status codes are for testing how the
frontend handles them.
--ppl-loss -128..128pel (in steps of 1) [0]
The number of pixels that are wasted at the end of each line.
--fuzzy-parameters[=(yes|no)] [no]
Return fuzzy lines and bytes per line when sane_parameters() is called
before sane_start().
--non-blocking[=(yes|no)] [no]
Use non-blocking IO for sane_read() if supported by the frontend.
--select-fd[=(yes|no)] [no]
Offer a select filedescriptor for detecting if sane_read() will return
data.
--enable-test-options[=(yes|no)] [no]
Enable various test options. This is for testing the ability of
frontends to view and modify all the different SANE option types.
--read-length-zero[=(yes|no)] [no]
sane_read() returns data 'x' but length=0 on first call. This is
helpful for testing slow device behavior that returns no data when
background work is in process and zero length with SANE_STATUS_GOOD
although data is NOT filled with 0.
--print-options
Print a list of all options.
Geometry:
-l 0..200mm (in steps of 1) [0]
Top-left x position of scan area.
-t 0..200mm (in steps of 1) [0]
Top-left y position of scan area.
-x 0..200mm (in steps of 1) [80]
Width of scan-area.
-y 0..200mm (in steps of 1) [100]
Height of scan-area.
--page-width 0..300mm (in steps of 1) [200]
Specifies the width of the media. Required for automatic centering of
sheet-fed scans.
--page-height 0..300mm (in steps of 1) [200]
Specifies the height of the media.
Bool test options:
--bool-soft-select-soft-detect[=(yes|no)] [inactive]
(1/6) Bool test option that has soft select and soft detect (and
advanced) capabilities. That's just a normal bool option.
--bool-soft-select-soft-detect-emulated[=(yes|no)] [inactive]
(5/6) Bool test option that has soft select, soft detect, and emulated
(and advanced) capabilities.
--bool-soft-select-soft-detect-auto[=(auto|yes|no)] [inactive]
(6/6) Bool test option that has soft select, soft detect, and
automatic (and advanced) capabilities. This option can be automatically
set by the backend.
Int test options:
--int [inactive]
(1/6) Int test option with no unit and no constraint set.
--int-constraint-range 4..192pel (in steps of 2) [inactive]
(2/6) Int test option with unit pixel and constraint range set.
Minimum is 4, maximum 192, and quant is 2.
--int-constraint-word-list -42|-8|0|17|42|256|65536|16777216|1073741824bit [inactive]
(3/6) Int test option with unit bits and constraint word list set.
--int-constraint-array ,... [inactive]
(4/6) Int test option with unit mm and using an array without
constraints.
--int-constraint-array-constraint-range 4..192dpi,... (in steps of 2) [inactive]
(5/6) Int test option with unit dpi and using an array with a range
constraint. Minimum is 4, maximum 192, and quant is 2.
--int-constraint-array-constraint-word-list -42|-8|0|17|42|256|65536|16777216|1073741824%,... [inactive]
(6/6) Int test option with unit percent and using an array with a word
list constraint.
Fixed test options:
--fixed [inactive]
(1/3) Fixed test option with no unit and no constraint set.
--fixed-constraint-range -42.17..32768us (in steps of 2) [inactive]
(2/3) Fixed test option with unit microsecond and constraint range
set. Minimum is -42.17, maximum 32767.9999, and quant is 2.0.
--fixed-constraint-word-list -32.7|12.1|42|129.5 [inactive]
(3/3) Fixed test option with no unit and constraint word list set.
String test options:
--string [inactive]
(1/3) String test option without constraint.
--string-constraint-string-list First entry|Second entry|This is the very long third entry. Maybe the frontend has an idea how to display it [inactive]
(2/3) String test option with string list constraint.
--string-constraint-long-string-list First entry|Second entry|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|32|33|34|35|36|37|38|39|40|41|42|43|44|45|46 [inactive]
(3/3) String test option with string list constraint. Contains some
more entries...
Button test options:
--button [inactive]
(1/1) Button test option. Prints some text...
Type ``scanimage --help -d DEVICE'' to get list of all options for DEVICE.
List of available devices:
test:0 test:1
gscan2pdf-1.2.3/scanners/FujitsuS510.Lineart 0000644 0001750 0001750 00000010551 12053230657 017135 0 ustar jeff jeff Usage: scanimage [OPTION]...
Start image acquisition on a scanner device and write PNM image data to
standard output.
Parameters are separated by a blank from single-character options (e.g.
-d epson) and by a "=" from multi-character options (e.g. --device-name=epson).
-d, --device-name=DEVICE use a given scanner device (e.g. hp:/dev/scanner)
--format=pnm|tiff file format of output file
-i, --icc-profile=PROFILE include this ICC profile into TIFF file
-L, --list-devices show available scanner devices
-f, --formatted-device-list=FORMAT similar to -L, but the FORMAT of the output
can be specified: %d (device name), %v (vendor),
%m (model), %t (type), and %i (index number)
-b, --batch[=FORMAT] working in batch mode, FORMAT is `out%d.pnm' or
`out%d.tif' by default depending on --format
--batch-start=# page number to start naming files with
--batch-count=# how many pages to scan in batch mode
--batch-increment=# increase number in filename by an amount of #
--batch-double increment page number by two for 2sided originals
being scanned in a single sided scanner
--batch-prompt ask for pressing a key before scanning a page
--accept-md5-only only accept authorization requests using md5
-p, --progress print progress messages
-n, --dont-scan only set options, don't actually scan
-T, --test test backend thoroughly
-h, --help display this help message and exit
-v, --verbose give even more status messages
-B, --buffer-size change default input buffersize
-V, --version print version information
Options specific to device `fujitsu:libusb:007:032':
Scan Mode:
--source ADF Front|ADF Back|ADF Duplex [ADF Front]
Selects the scan source (such as a document-feeder).
--mode Lineart|Halftone|Gray|Color [Lineart]
Selects the scan mode (e.g., lineart, monochrome, or color).
--resolution 50..600dpi (in steps of 1) [600]
Sets the horizontal resolution of the scanned image.
--y-resolution 50..600dpi (in steps of 1) [600]
Sets the vertical resolution of the scanned image.
Geometry:
-l 0..215.872mm (in steps of 0.0211639) [0]
Top-left x position of scan area.
-t 0..279.364mm (in steps of 0.0211639) [0]
Top-left y position of scan area.
-x 0..215.872mm (in steps of 0.0211639) [215.872]
Width of scan-area.
-y 0..279.364mm (in steps of 0.0211639) [279.364]
Height of scan-area.
--pagewidth 0..221.121mm (in steps of 0.0211639) [215.872]
Must be set properly to align scanning window
--pageheight 0..863.489mm (in steps of 0.0211639) [279.364]
Must be set properly to eject pages
Enhancement:
--brightness -127..127 (in steps of 1) [0]
Controls the brightness of the acquired image.
--contrast -127..127 (in steps of 1) [0]
Controls the contrast of the acquired image.
--threshold 0..255 (in steps of 1) [0]
Select minimum-brightness to get a white point
--rif[=(yes|no)] [no]
Reverse image format
Advanced:
--compression None|JPEG [None]
Enable compressed data. May crash your front-end program
--compression-arg 0..7 (in steps of 1) [0]
Level of JPEG compression. 1 is small file, 7 is large file. 0
(default) is same as 4
--dfdetect Default|None|Thickness|Length|Both [Default]
Enable double feed sensors
--dfdiff Default|10mm|15mm|20mm [Default]
Difference in page length to trigger double feed sensor
--dropoutcolor Default|Red|Green|Blue [Default]
One-pass scanners use only one color during gray or binary scanning,
useful for colored paper or ink
--overscan Default|Off|On [Default]
Collect a few mm of background on top side of scan, before paper
enters ADF, and increase maximum scan area beyond paper size, to allow
collection on remaining sides. May conflict with bgcolor option
--sleeptimer 0..60 (in steps of 1) [0]
Time in minutes until the internal power supply switches to sleep mode
Sensors and Buttons:
Type ``scanimage --help -d DEVICE'' to get list of all options for DEVICE.
List of available devices:
v4l:/dev/video0 fujitsu:libusb:007:032
gscan2pdf-1.2.3/scanners/hp_scanjet5300c 0000644 0001750 0001750 00000007607 12053230657 016337 0 ustar jeff jeff Usage: scanimage [OPTION]...
Start image acquisition on a scanner device and write PNM image data to
standard output.
-d, --device-name=DEVICE use a given scanner device (e.g. hp:/dev/scanner)
--format=pnm|tiff file format of output file
-i, --icc-profile=PROFILE include this ICC profile into TIFF file
-L, --list-devices show available scanner devices
-f, --formatted-device-list=FORMAT similar to -L, but the FORMAT of the output
can be specified: %d (device name), %v (vendor),
%m (model), %t (type), and %i (index number)
-b, --batch[=FORMAT] working in batch mode, FORMAT is `out%d.pnm' or
`out%d.tif' by default depending on --format
--batch-start=# page number to start naming files with
--batch-count=# how many pages to scan in batch mode
--batch-increment=# increase number in filename by an amount of #
--batch-double increment page number by two for 2sided originals
being scanned in a single sided scanner
--batch-prompt ask for pressing a key before scanning a page
--accept-md5-only only accept authorization requests using md5
-p, --progress print progress messages
-n, --dont-scan only set options, don't actually scan
-T, --test test backend thoroughly
-h, --help display this help message and exit
-v, --verbose give even more status messages
-B, --buffer-size change default input buffersize
-V, --version print version information
Options specific to device `avision:libusb:001:005':
Scan mode:
--mode Lineart|Dithered|Gray|12bit Gray|Color|12bit Color [Color]
Selects the scan mode (e.g., lineart, monochrome, or color).
--resolution 100..1200dpi (in steps of 5) [150]
Sets the resolution of the scanned image.
--speed 0..4 (in steps of 1) [0]
Determines the speed at which the scan proceeds.
--preview[=(yes|no)] [no]
Request a preview-quality scan.
--source Normal|ADF [Normal]
Selects the scan source (such as a document-feeder).
Geometry:
-l 0..216mm [0]
Top-left x position of scan area.
-t 0..296mm [0]
Top-left y position of scan area.
-x 0..216mm [216]
Width of scan-area.
-y 0..296mm [296]
Height of scan-area.
Enhancement:
--brightness -100..100% (in steps of 1) [0]
Controls the brightness of the acquired image.
--contrast -100..100% (in steps of 1) [0]
Controls the contrast of the acquired image.
--quality-scan[=(yes|no)] [yes]
Turn on quality scanning (slower but better).
--quality-cal[=(yes|no)] [yes]
Do a quality white-calibration
--gamma-table 0..255,...
Gamma-correction table. In color mode this option equally affects the
red, green, and blue channels simultaneously (i.e., it is an intensity
gamma table).
--red-gamma-table 0..255,... [inactive]
Gamma-correction table for the red band.
--green-gamma-table 0..255,... [inactive]
Gamma-correction table for the green band.
--blue-gamma-table 0..255,... [inactive]
Gamma-correction table for the blue band.
--frame 0..0 [inactive]
Selects the number of the frame to scan
--power-save-time [65535]
Allows control of the scanner's power save timer, dimming or turning
off the light.
--nvram-values [Vendor: HP
Model: ScanJet 5300C
Firmware: 4.00
Serial: 3119ME
Manufacturing date: 0-0-0
First scan date: 65535-0-0
Flatbed scans: 65547
Pad scans: -65536
ADF simplex scans: 136183808]
Allows access obtaining the scanner's NVRAM values as pretty printed
text.
Type ``scanimage --help -d DEVICE'' to get list of all options for DEVICE.
List of available devices:
avision:libusb:001:005
gscan2pdf-1.2.3/scanners/epson_GT-X770 0000644 0001750 0001750 00000027000 12053230657 015714 0 ustar jeff jeff Usage: scanadf [OPTION]...
Start image acquisition on a scanner device and write image data to
output files.
[ -d | --device-name ] use a given scanner device.
[ -h | --help ] display this help message and exit.
[ -L | --list-devices ] show available scanner devices.
[ -v | --verbose ] give even more status messages.
[ -V | --version ] print version information.
[ -N | --no-overwrite ] don't overwrite existing files.
[ -o | --output-file ] name of file to write image data
(%d replacement in output file name).
[ -S | --scan-script ] name of script to run after every scan.
[ --script-wait ] wait for scripts to finish before exit
[ -s | --start-count ] page count of first scanned image.
[ -e | --end-count ] last page number to scan.
[ -r | --raw ] write raw image data to file.
Options specific to device `epkowa:interpreter:003:005':
Scan Mode:
--mode Binary|Gray|Color [Gray]
Selects the scan mode (e.g., lineart, monochrome, or color).
--depth 8|16 [8]
Number of bits per sample, typical values are 1 for "line-art" and 8
for multibit scans.
--halftoning None|Halftone A (Hard Tone)|Halftone B (Soft Tone)|Halftone C (Net Screen) [inactive]
Selects the halftone.
--dropout None|Red|Green|Blue [inactive]
Selects the dropout.
--brightness 0..0 [inactive]
Selects the brightness.
--sharpness -2..2 [inactive]
--gamma-correction User defined (Gamma=1.0)|User defined (Gamma=1.8) [User defined (Gamma=1.8)]
Selects the gamma correction value from a list of pre-defined devices
or the user defined table, which can be downloaded to the scanner
--color-correction User defined [inactive]
Sets the color correction table for the selected output device.
--resolution 200|400|800|1600dpi [200]
Sets the resolution of the scanned image.
--x-resolution 100|200|400|600|800|1200|1600|3200|6400dpi [200]
Sets the horizontal resolution of the scanned image.
--y-resolution 80|200|320|400|600|800|1200|1600|2400|3200|4800|6400dpi [320]
Sets the vertical resolution of the scanned image.
--threshold 0..255 [inactive]
Select minimum-brightness to get a white point
Advanced:
--mirror[=(yes|no)] [inactive]
Mirror the image.
--speed[=(yes|no)] [no]
Determines the speed at which the scan proceeds.
--auto-area-segmentation[=(yes|no)] [inactive]
--short-resolution[=(yes|no)] [no]
Display short resolution list
--zoom 50..200 [inactive]
Defines the zoom factor the scanner will use
--red-gamma-table 0..255,... [0]
Gamma-correction table for the red band.
--green-gamma-table 0..255,... [0]
Gamma-correction table for the green band.
--blue-gamma-table 0..255,... [0]
Gamma-correction table for the blue band.
--wait-for-button[=(yes|no)] [no]
After sending the scan command, wait until the button on the scanner
is pressed to actually start the scan process.
--monitor-button[=(yes|no)] [no]
Indicates whether a button on the scanner has been pressed (read-only
option).
Color correction coefficients:
--cct-1 -2..2 [inactive]
Controls red level
--cct-2 -2..2 [inactive]
Adds to red based on green level
--cct-3 -2..2 [inactive]
Adds to red based on blue level
--cct-4 -2..2 [inactive]
Adds to green based on red level
--cct-5 -2..2 [inactive]
Controls green level
--cct-6 -2..2 [inactive]
Adds to green based on blue level
--cct-7 -2..2 [inactive]
Adds to blue based on red level
--cct-8 -2..2 [inactive]
Adds to blue based on green level
--cct-9 -2..2 [inactive]
Control blue level
Preview:
--preview[=(yes|no)] [no]
Request a preview-quality scan.
--preview-speed[=(yes|no)] [no]
Geometry:
-l 0..215.9mm [0]
Top-left x position of scan area.
-t 0..297.18mm [0]
Top-left y position of scan area.
-x 0..215.9mm [215.9]
Width of scan-area.
-y 0..297.18mm [297.18]
Height of scan-area.
--quick-format CD|A5 portrait|A5 landscape|Letter|A4|Max [Max]
Optional equipment:
--source Flatbed|Automatic Document Feeder [Flatbed]
Selects the scan source (such as a document-feeder).
--auto-eject[=(yes|no)] [yes]
Eject document after scanning
--film-type Positive Film|Negative Film [inactive]
--focus-position Focus on glass|Focus 2.5mm above glass [inactive]
Sets the focus position to either the glass or 2.5mm above the glass
--bay 1 | 2 | 3 | 4 | 5 | 6 [inactive]
Select bay to scan
--eject
Eject the sheet in the ADF
--adf-mode Simplex|Duplex [inactive]
Selects the ADF mode (simplex/duplex)
--detect-doc-size[=(yes|no)] [inactive]
Activates document size auto-detection. The scan area will be set to
match the detected document size.
Type ``scanadf --help -d DEVICE'' to get list of all options for DEVICE.
List of available devices:
epkowa:interpreter:003:005
gscan2pdf-1.2.3/scanners/fujitsu 0000644 0001750 0001750 00000006447 12053230657 015240 0 ustar jeff jeff Usage: scanimage [OPTION]...
Start image acquisition on a scanner device and write PNM image data to standard output.
-d, --device-name=DEVICE use a given scanner device (e.g. hp:/dev/scanner)
--format=pnm|tiff file format of output file
-i, --icc-profile=PROFILE include this ICC profile into TIFF file
-L, --list-devices show available scanner devices
-f, --formatted-device-list=FORMAT similar to -L, but the FORMAT of the output
can be specified: %d (device name), %v (vendor),
%m (model), %t (type), and %i (index number)
-b, --batch[=FORMAT] working in batch mode, FORMAT is `out%d.pnm' or
`out%d.tif' by default depending on --format
--batch-start=# page number to start naming files with
--batch-count=# how many pages to scan in batch mode
--batch-increment=# increase number in filename by an amount of #
--batch-double increment page number by two for 2sided originals
being scanned in a single sided scanner
--batch-prompt ask for pressing a key before scanning a page
--accept-md5-only only accept authorization requests using md5
-p, --progress print progress messages
-n, --dont-scan only set options, don't actually scan
-T, --test test backend thoroughly
-h, --help display this help message and exit
-v, --verbose give even more status messages
-B, --buffer-size change default input buffersize
-V, --version print version information
scanimage: rounded value of br-x from 215.872 to 215.872
scanimage: rounded value of br-y from 279.364 to 279.364
Options specific to device `fujitsu:libusb:002:004':
Scan Mode:
--source ADF Front|ADF Back|ADF Duplex [ADF Front]
Selects the scan source (such as a document-feeder).
--mode Gray|Color [Gray]
Selects the scan mode (e.g., lineart, monochrome, or color).
--resolution 100..600dpi (in steps of 1) [600]
Sets the horizontal resolution of the scanned image.
--y-resolution 50..600dpi (in steps of 1) [600]
Sets the vertical resolution of the scanned image.
Geometry:
-l 0..224.846mm (in steps of 0.0211639) [0]
Top-left x position of scan area.
-t 0..863.489mm (in steps of 0.0211639) [0]
Top-left y position of scan area.
-x 0..224.846mm (in steps of 0.0211639) [215.872]
Width of scan-area.
-y 0..863.489mm (in steps of 0.0211639) [279.364]
Height of scan-area.
--pagewidth 0..224.846mm (in steps of 0.0211639) [215.872]
Must be set properly to align scanning window
--pageheight 0..863.489mm (in steps of 0.0211639) [279.364]
Must be set properly to eject pages
Enhancement:
--rif[=(yes|no)] [no]
Reverse image format
Advanced:
--dropoutcolor Default|Red|Green|Blue [Default]
One-pass scanners use only one color during gray or binary scanning,
useful for colored paper or ink
--sleeptimer 0..60 (in steps of 1) [0]
Time in minutes until the internal power supply switches to sleep mode
Sensors and Buttons:
Type ``scanimage --help -d DEVICE'' to get list of all options for DEVICE.
List of available devices:
fujitsu:libusb:002:004
gscan2pdf-1.2.3/scanners/FujitsuS510.Color 0000644 0001750 0001750 00000010134 12053230657 016612 0 ustar jeff jeff Usage: scanimage [OPTION]...
Start image acquisition on a scanner device and write PNM image data to
standard output.
Parameters are separated by a blank from single-character options (e.g.
-d epson) and by a "=" from multi-character options (e.g. --device-name=epson).
-d, --device-name=DEVICE use a given scanner device (e.g. hp:/dev/scanner)
--format=pnm|tiff file format of output file
-i, --icc-profile=PROFILE include this ICC profile into TIFF file
-L, --list-devices show available scanner devices
-f, --formatted-device-list=FORMAT similar to -L, but the FORMAT of the output
can be specified: %d (device name), %v (vendor),
%m (model), %t (type), and %i (index number)
-b, --batch[=FORMAT] working in batch mode, FORMAT is `out%d.pnm' or
`out%d.tif' by default depending on --format
--batch-start=# page number to start naming files with
--batch-count=# how many pages to scan in batch mode
--batch-increment=# increase number in filename by an amount of #
--batch-double increment page number by two for 2sided originals
being scanned in a single sided scanner
--batch-prompt ask for pressing a key before scanning a page
--accept-md5-only only accept authorization requests using md5
-p, --progress print progress messages
-n, --dont-scan only set options, don't actually scan
-T, --test test backend thoroughly
-h, --help display this help message and exit
-v, --verbose give even more status messages
-B, --buffer-size change default input buffersize
-V, --version print version information
Options specific to device `fujitsu:libusb:007:032':
Scan Mode:
--source ADF Front|ADF Back|ADF Duplex [ADF Front]
Selects the scan source (such as a document-feeder).
--mode Lineart|Halftone|Gray|Color [Color]
Selects the scan mode (e.g., lineart, monochrome, or color).
--resolution 50..600dpi (in steps of 1) [600]
Sets the horizontal resolution of the scanned image.
--y-resolution 50..600dpi (in steps of 1) [600]
Sets the vertical resolution of the scanned image.
Geometry:
-l 0..215.872mm (in steps of 0.0211639) [0]
Top-left x position of scan area.
-t 0..279.364mm (in steps of 0.0211639) [0]
Top-left y position of scan area.
-x 0..215.872mm (in steps of 0.0211639) [215.872]
Width of scan-area.
-y 0..279.364mm (in steps of 0.0211639) [279.364]
Height of scan-area.
--pagewidth 0..221.121mm (in steps of 0.0211639) [215.872]
Must be set properly to align scanning window
--pageheight 0..863.489mm (in steps of 0.0211639) [279.364]
Must be set properly to eject pages
Enhancement:
--brightness -127..127 (in steps of 1) [0]
Controls the brightness of the acquired image.
--contrast -127..127 (in steps of 1) [0]
Controls the contrast of the acquired image.
--rif[=(yes|no)] [no]
Reverse image format
Advanced:
--compression None|JPEG [None]
Enable compressed data. May crash your front-end program
--compression-arg 0..7 (in steps of 1) [0]
Level of JPEG compression. 1 is small file, 7 is large file. 0
(default) is same as 4
--dfdetect Default|None|Thickness|Length|Both [Default]
Enable double feed sensors
--dfdiff Default|10mm|15mm|20mm [Default]
Difference in page length to trigger double feed sensor
--overscan Default|Off|On [Default]
Collect a few mm of background on top side of scan, before paper
enters ADF, and increase maximum scan area beyond paper size, to allow
collection on remaining sides. May conflict with bgcolor option
--sleeptimer 0..60 (in steps of 1) [0]
Time in minutes until the internal power supply switches to sleep mode
Sensors and Buttons:
Type ``scanimage --help -d DEVICE'' to get list of all options for DEVICE.
List of available devices:
v4l:/dev/video0 fujitsu:libusb:007:032
gscan2pdf-1.2.3/scanners/officejet_5500.lineart 0000644 0001750 0001750 00000006220 12053230657 017600 0 ustar jeff jeff Usage: scanimage [OPTION]...
Start image acquisition on a scanner device and write PNM image data to
standard output.
-d, --device-name=DEVICE use a given scanner device (e.g. hp:/dev/scanner)
--format=pnm|tiff file format of output file
-i, --icc-profile=PROFILE include this ICC profile into TIFF file
-L, --list-devices show available scanner devices
-f, --formatted-device-list=FORMAT similar to -L, but the FORMAT of the output
can be specified: %d (device name), %v (vendor),
%m (model), %t (type), and %i (index number)
-b, --batch[=FORMAT] working in batch mode, FORMAT is `out%d.pnm' or
`out%d.tif' by default depending on --format
--batch-start=# page number to start naming files with
--batch-count=# how many pages to scan in batch mode
--batch-increment=# increase number in filename by an amount of #
--batch-double increment page number by two for 2sided originals
being scanned in a single sided scanner
--batch-prompt ask for pressing a key before scanning a page
--accept-md5-only only accept authorization requests using md5
-p, --progress print progress messages
-n, --dont-scan only set options, don't actually scan
-T, --test test backend thoroughly
-h, --help display this help message and exit
-v, --verbose give even more status messages
-B, --buffer-size change default input buffersize
-V, --version print version information
Options specific to device `hpaio:/usb/officejet_5500_series?serial=MY42QF209H96':
Scan mode:
--mode Lineart|Gray|Color [Lineart]
Selects the scan mode (e.g., lineart, monochrome, or color).
--resolution 75..600dpi [75]
Sets the resolution of the scanned image.
Advanced:
--contrast 0..100 [inactive]
Controls the contrast of the acquired image.
--compression None [None]
Selects the scanner compression method for faster scans, possibly at
the expense of image quality.
--jpeg-quality 0..100 [inactive]
Sets the scanner JPEG compression factor. Larger numbers mean better
compression, and smaller numbers mean better image quality.
--batch-scan[=(yes|no)] [no]
Enables continuous scanning with automatic document feeder (ADF).
--source Auto|Flatbed|ADF [Auto]
Selects the scan source (such as a document-feeder).
Geometry:
--length-measurement Unknown|Approximate|Padded [Padded]
Selects how the scanned image length is measured and reported, which
is impossible to know in advance for scrollfed scans.
-l 0..215.9mm [0]
Top-left x position of scan area.
-t 0..381mm [0]
Top-left y position of scan area.
-x 0..215.9mm [215.9]
Width of scan-area.
-y 0..381mm [381]
Height of scan-area.
Type ``scanimage --help -d DEVICE'' to get list of all options for DEVICE.
List of available devices:
v4l:/dev/video2 v4l:/dev/video1 v4l:/dev/video0
hpaio:/usb/officejet_5500_series?serial=MY42QF209H96
gscan2pdf-1.2.3/scanners/laserjet_3020 0000644 0001750 0001750 00000006260 12053230657 016015 0 ustar jeff jeff Usage: scanimage [OPTION]...
Start image acquisition on a scanner device and write PNM image data to standard output.
-d, --device-name=DEVICE use a given scanner device (e.g. hp:/dev/scanner)
--format=pnm|tiff file format of output file
-i, --icc-profile=PROFILE include this ICC profile into TIFF file
-L, --list-devices show available scanner devices
-f, --formatted-device-list=FORMAT similar to -L, but the FORMAT of the output
can be specified: %d (device name), %v (vendor),
%m (model), %t (type), and %i (index number)
-b, --batch[=FORMAT] working in batch mode, FORMAT is `out%d.pnm' or
`out%d.tif' by default depending on --format
--batch-start=# page number to start naming files with
--batch-count=# how many pages to scan in batch mode
--batch-increment=# increase number in filename by an amount of #
--batch-double increment page number by two for 2sided originals
being scanned in a single sided scanner
--batch-prompt ask for pressing a key before scanning a page
--accept-md5-only only accept authorization requests using md5
-p, --progress print progress messages
-n, --dont-scan only set options, don't actually scan
-T, --test test backend thoroughly
-h, --help display this help message and exit
-v, --verbose give even more status messages
-B, --buffer-size change default input buffersize
-V, --version print version information
Options specific to device `hpaio:/usb/hp_LaserJet_3020?serial=00CNBM044295':
Scan mode:
--mode Lineart|Gray|Color [Color]
Selects the scan mode (e.g., lineart, monochrome, or color).
--resolution 75|100|150|200|300|600dpi [75]
Sets the resolution of the scanned image.
Advanced:
--contrast 0..100 [50]
Controls the contrast of the acquired image.
--compression None|JPEG [JPEG]
Selects the scanner compression method for faster scans, possibly at
the expense of image quality.
--jpeg-quality 0..100 [10]
Sets the scanner JPEG compression factor. Larger numbers mean better
compression, and smaller numbers mean better image quality.
--batch-scan[=(yes|no)] [no]
Enables continuous scanning with automatic document feeder (ADF).
--source Auto|ADF [Auto]
Selects the scan source (such as a document-feeder).
--duplex[=(yes|no)] [inactive]
Enables scanning on both sides of the page.
Geometry:
--length-measurement Unknown|Unlimited|Approximate|Padded [Padded]
Selects how the scanned image length is measured and reported, which
is impossible to know in advance for scrollfed scans.
-l 0..228.6mm [0]
Top-left x position of scan area.
-t 0..381mm [0]
Top-left y position of scan area.
-x 0..228.6mm [228.6]
Width of scan-area.
-y 0..381mm [381]
Height of scan-area.
Type ``scanimage --help -d DEVICE'' to get list of all options for DEVICE.
List of available devices:
hpaio:/usb/hp_LaserJet_3020?serial=00CNBM044295
gscan2pdf-1.2.3/scanners/epson1 0000644 0001750 0001750 00000013231 12053230657 014741 0 ustar jeff jeff Usage: scanimage [OPTION]...
Start image acquisition on a scanner device and write PNM image data to
standard output.
-d, --device-name=DEVICE use a given scanner device (e.g. hp:/dev/scanner)
--format=pnm|tiff file format of output file
-i, --icc-profile=PROFILE include this ICC profile into TIFF file
-L, --list-devices show available scanner devices
-f, --formatted-device-list=FORMAT similar to -L, but the FORMAT of the output
can be specified: %d (device name), %v (vendor),
%m (model), %t (type), and %i (index number)
-b, --batch[=FORMAT] working in batch mode, FORMAT is `out%d.pnm' or
`out%d.tif' by default depending on --format
--batch-start=# page number to start naming files with
--batch-count=# how many pages to scan in batch mode
--batch-increment=# increase number in filename by an amount of #
--batch-double increment page number by two for 2sided originals
being scanned in a single sided scanner
--batch-prompt ask for pressing a key before scanning a page
--accept-md5-only only accept authorization requests using md5
-n, --dont-scan only set options, don't actually scan
-T, --test test backend thoroughly
-h, --help display this help message and exit
-v, --verbose give even more status messages
-V, --version print version information
Options specific to device `epson:libusb:005:007':
Scan Mode:
--mode Binary|Gray|Color [Binary]
Selects the scan mode (e.g., lineart, monochrome, or color).
--depth 8|16 [inactive]
Number of bits per sample, typical values are 1 for "line-art" and 8
for multibit scans.
--halftoning None|Halftone A (Hard Tone)|Halftone B (Soft Tone)|Halftone C (Net Screen)|Dither A (4x4 Bayer)|Dither B (4x4 Spiral)|Dither C (4x4 Net Screen)|Dither D (8x4 Net Screen)|Text Enhanced Technology|Download pattern A|Download pattern B [Halftone A (Hard Tone)]
Selects the halftone.
--dropout None|Red|Green|Blue [None]
Selects the dropout.
--brightness -4..3 [0]
Selects the brightness.
--sharpness -2..2 [0]
--gamma-correction Default|User defined|High density printing|Low density printing|High contrast printing [Default]
Selects the gamma correction value from a list of pre-defined devices
or the user defined table, which can be downloaded to the scanner
--color-correction No Correction|User defined|Impact-dot printers|Thermal printers|Ink-jet printers|CRT monitors [CRT monitors]
Sets the color correction table for the selected output device.
--resolution 50|60|72|75|80|90|100|120|133|144|150|160|175|180|200|216|240|266|300|320|350|360|400|480|600|720|800|900|1200|1600|1800|2400|3200dpi [50]
Sets the resolution of the scanned image.
--threshold 0..255 [inactive]
Select minimum-brightness to get a white point
Advanced:
--mirror[=(yes|no)] [no]
Mirror the image.
--speed[=(yes|no)] [no]
Determines the speed at which the scan proceeds.
--auto-area-segmentation[=(yes|no)] [yes]
--short-resolution[=(yes|no)] [no]
Display short resolution list
--zoom 50..200 [inactive]
Defines the zoom factor the scanner will use
--red-gamma-table 0..255,... [inactive]
Gamma-correction table for the red band.
--green-gamma-table 0..255,... [inactive]
Gamma-correction table for the green band.
--blue-gamma-table 0..255,... [inactive]
Gamma-correction table for the blue band.
--wait-for-button[=(yes|no)] [no]
After sending the scan command, wait until the button on the scanner
is pressed to actually start the scan process.
Color correction coefficients:
--cct-1 -127..127 [inactive]
Controls green level
--cct-2 -127..127 [inactive]
Adds to red based on green level
--cct-3 -127..127 [inactive]
Adds to blue based on green level
--cct-4 -127..127 [inactive]
Adds to green based on red level
--cct-5 -127..127 [inactive]
Controls red level
--cct-6 -127..127 [inactive]
Adds to blue based on red level
--cct-7 -127..127 [inactive]
Adds to green based on blue level
--cct-8 -127..127 [inactive]
Adds to red based on blue level
--cct-9 -127..127 [inactive]
Controls blue level
Preview:
--preview[=(yes|no)] [no]
Request a preview-quality scan.
--preview-speed[=(yes|no)] [no]
Geometry:
-l 0..215.9mm [0]
Top-left x position of scan area.
-t 0..297.18mm [0]
Top-left y position of scan area.
-x 0..215.9mm [215.9]
Width of scan-area.
-y 0..297.18mm [297.18]
Height of scan-area.
--quick-format CD|A5 portrait|A5 landscape|Letter|A4|Max [Max]
Optional equipment:
--source Flatbed|Transparency Unit [Flatbed]
Selects the scan source (such as a document-feeder).
--auto-eject[=(yes|no)] [inactive]
Eject document after scanning
--film-type Positive Film|Negative Film [inactive]
--focus-position Focus on glass|Focus 2.5mm above glass [Focus on glass]
Sets the focus position to either the glass or 2.5mm above the glass
--bay 1 | 2 | 3 | 4 | 5 | 6 [inactive]
Select bay to scan
--eject [inactive]
Eject the sheet in the ADF
--adf_mode Simplex|Duplex [inactive]
Selects the ADF mode (simplex/duplex)
Type ``scanimage --help -d DEVICE'' to get list of all options for DEVICE.
List of available devices:
epson:libusb:005:007
gscan2pdf-1.2.3/scanners/brother 0000644 0001750 0001750 00000005315 12053230657 015205 0 ustar jeff jeff Usage: scanimage [OPTION]...
Start image acquisition on a scanner device and write PNM image data to standard output.
-d, --device-name=DEVICE use a given scanner device (e.g. hp:/dev/scanner)
--format=pnm|tiff file format of output file
-i, --icc-profile=PROFILE include this ICC profile into TIFF file
-L, --list-devices show available scanner devices
-f, --formatted-device-list=FORMAT similar to -L, but the FORMAT of the output
can be specified: %d (device name), %v (vendor),
%m (model), %t (type), and %i (index number)
-b, --batch[=FORMAT] working in batch mode, FORMAT is `out%d.pnm' or
`out%d.tif' by default depending on --format
--batch-start=# page number to start naming files with
--batch-count=# how many pages to scan in batch mode
--batch-increment=# increase number in filename by an amount of #
--batch-double increment page number by two for 2sided originals
being scanned in a single sided scanner
--batch-prompt ask for pressing a key before scanning a page
--accept-md5-only only accept authorization requests using md5
-p, --progress print progress messages
-n, --dont-scan only set options, don't actually scan
-T, --test test backend thoroughly
-h, --help display this help message and exit
-v, --verbose give even more status messages
-B, --buffer-size change default input buffersize
-V, --version print version information
Options specific to device `brother2:net1;dev0':
Mode:
--mode Black & White|Gray[Error Diffusion]|True Gray|24bit Color|24bit Color[Fast] [24bit Color]
Select the scan mode
--resolution 100|150|200|300|400|600|1200|2400|4800|9600dpi [200]
Sets the resolution of the scanned image.
--source FlatBed|Automatic Document Feeder [Automatic Document Feeder]
Selects the scan source (such as a document-feeder).
--brightness -50..50% (in steps of 1) [inactive]
Controls the brightness of the acquired image.
--contrast -50..50% (in steps of 1) [inactive]
Controls the contrast of the acquired image.
Geometry:
-l 0..210mm (in steps of 0.0999908) [0]
Top-left x position of scan area.
-t 0..297mm (in steps of 0.0999908) [0]
Top-left y position of scan area.
-x 0..210mm (in steps of 0.0999908) [209.981]
Width of scan-area.
-y 0..297mm (in steps of 0.0999908) [296.973]
Height of scan-area.
Type ``scanimage --help -d DEVICE'' to get list of all options for DEVICE.
List of available devices:
brother2:net1;dev0
gscan2pdf-1.2.3/scanners/dummy_scanner 0000644 0001750 0001750 00000007475 12053230657 016415 0 ustar jeff jeff Usage: scanimage [OPTION]...
Start image acquisition on a scanner device and write PNM image data to standard output.
-d, --device-name=DEVICE use a given scanner device (e.g. hp:/dev/scanner)
--format=pnm|tiff file format of output file
-i, --icc-profile=PROFILE include this ICC profile into TIFF file
-L, --list-devices show available scanner devices
-f, --formatted-device-list=FORMAT similar to -L, but the FORMAT of the output
can be specified: %d (device name), %v (vendor),
%m (model), %t (type), and %i (index number)
-b, --batch[=FORMAT] working in batch mode, FORMAT is `out%d.pnm' or
`out%d.tif' by default depending on --format
--batch-start=# page number to start naming files with
--batch-count=# how many pages to scan in batch mode
--batch-increment=# increase number in filename by an amount of #
--batch-double increment page number by two for 2sided originals
being scanned in a single sided scanner
--batch-prompt ask for pressing a key before scanning a page
--accept-md5-only only accept authorization requests using md5
-p, --progress print progress messages
-n, --dont-scan only set options, don't actually scan
-T, --test test backend thoroughly
-h, --help display this help message and exit
-v, --verbose give even more status messages
-B, --buffer-size change default input buffersize
-V, --version print version information
Options specific to device `hpaio:/usb/officejet_5500_series?serial=MY42QF209H96':
Scan mode:
--mode Lineart|Grayscale|Color [Color]
Selects the scan mode (e.g., lineart, monochrome, or color).
--resolution 75..600dpi [75]
Sets the resolution of the scanned image.
Advanced:
--contrast 0..100 [inactive]
Controls the contrast of the acquired image.
--compression None|JPEG [JPEG]
Selects the scanner compression method for faster scans, possibly at
the expense of image quality.
--jpeg-compression-factor 0..100 [10]
Sets the scanner JPEG compression factor. Larger numbers mean better
compression, and smaller numbers mean better image quality.
--batch-scan[=(yes|no)] [no]
Guarantees that a "no documents" condition will be returned after the
last scanned page, to prevent endless flatbed scans after a batch scan.
For some models, option changes in the middle of a batch scan don't
take effect until after the last page.
--source Auto|Flatbed|ADF [Auto]
Selects the desired scan source for models with both flatbed and
automatic document feeder (ADF) capabilities. The "Auto" setting means
that the ADF will be used if it's loaded, and the flatbed (if present)
will be used otherwise.
--duplex[=(yes|no)] [inactive]
Enables scanning on both sides of the page for models with
duplex-capable document feeders. For pages printed in "book"-style
duplex mode, one side will be scanned upside-down. This feature is
experimental.
Geometry:
--length-measurement Unknown|Approximate|Padded [Padded]
Selects how the scanned image length is measured and reported, which
is impossible to know in advance for scrollfed scans.
-l 0..215.9mm [0]
Top-left x position of scan area.
-t 0..381mm [0]
Top-left y position of scan area.
-x 0..115.9mm [215.9]
Width of scan-area.
-y 0..181mm [381]
Height of scan-area.
Type ``scanimage --help -d DEVICE'' to get list of all options for DEVICE.
List of available devices:
v4l:/dev/video1 v4l:/dev/video0
hpaio:/usb/officejet_5500_series?serial=MY42QF209H96
gscan2pdf-1.2.3/scanners/Dell_Laser_MFP_1600n 0000644 0001750 0001750 00000003706 12053230657 017076 0 ustar jeff jeff Usage: scanimage [OPTION]...
Start image acquisition on a scanner device and write PNM image data to standard output.
Parameters are separated by a blank from single-character options (e.g. -d epson) and by a "=" from multi-character options (e.g. --device-name=epson).
-d, --device-name=DEVICE use a given scanner device (e.g. hp:/dev/scanner)
--format=pnm|tiff file format of output file
-i, --icc-profile=PROFILE include this ICC profile into TIFF file
-L, --list-devices show available scanner devices
-f, --formatted-device-list=FORMAT similar to -L, but the FORMAT of the output
can be specified: %d (device name), %v (vendor),
%m (model), %t (type), and %i (index number)
-b, --batch[=FORMAT] working in batch mode, FORMAT is `out%d.pnm' or
`out%d.tif' by default depending on --format
--batch-start=# page number to start naming files with
--batch-count=# how many pages to scan in batch mode
--batch-increment=# increase number in filename by an amount of #
--batch-double increment page number by two for 2sided originals
being scanned in a single sided scanner
--batch-prompt ask for pressing a key before scanning a page
--accept-md5-only only accept authorization requests using md5
-p, --progress print progress messages
-n, --dont-scan only set options, don't actually scan
-T, --test test backend thoroughly
-h, --help display this help message and exit
-v, --verbose give even more status messages
-B, --buffer-size change default input buffersize
-V, --version print version information
Options specific to device `dell1600n_net:192.168.19.136':
Type ``scanimage --help -d DEVICE'' to get list of all options for DEVICE.
List of available devices:
dell1600n_net:192.168.19.136
gscan2pdf-1.2.3/scanners/epson1200 0000644 0001750 0001750 00000013317 12053230657 015170 0 ustar jeff jeff Usage: scanimage [OPTION]...
Start image acquisition on a scanner device and write PNM image data to
standard output.
-d, --device-name=DEVICE use a given scanner device (e.g. hp:/dev/scanner)
--format=pnm|tiff file format of output file
-i, --icc-profile=PROFILE include this ICC profile into TIFF file
-L, --list-devices show available scanner devices
-f, --formatted-device-list=FORMAT similar to -L, but the FORMAT of the output
can be specified: %d (device name), %v (vendor),
%m (model), %t (type), and %i (index number)
-b, --batch[=FORMAT] working in batch mode, FORMAT is `out%d.pnm' or
`out%d.tif' by default depending on --format
--batch-start=# page number to start naming files with
--batch-count=# how many pages to scan in batch mode
--batch-increment=# increase number in filename by an amount of #
--batch-double increment page number by two for 2sided originals
being scanned in a single sided scanner
--batch-prompt ask for pressing a key before scanning a page
--accept-md5-only only accept authorization requests using md5
-p, --progress print progress messages
-n, --dont-scan only set options, don't actually scan
-T, --test test backend thoroughly
-h, --help display this help message and exit
-v, --verbose give even more status messages
-B, --buffer-size change default input buffersize
-V, --version print version information
Options specific to device `net:esche:epson:libusb:001:006':
Scan Mode:
--mode Binary|Gray|Color [Binary]
Selects the scan mode (e.g., lineart, monochrome, or color).
--depth 8 [inactive]
Number of bits per sample, typical values are 1 for "line-art" and 8
for multibit scans.
--halftoning None|Halftone A (Hard Tone)|Halftone B (Soft Tone)|Halftone C (Net Screen)|Dither A (4x4 Bayer)|Dither B (4x4 Spiral)|Dither C (4x4 Net Screen)|Dither D (8x4 Net Screen)|Text Enhanced Technology|Download pattern A|Download pattern B [Halftone A (Hard Tone)]
Selects the halftone.
--dropout None|Red|Green|Blue [None]
Selects the dropout.
--brightness -4..3 [0]
Selects the brightness.
--sharpness -2..2 [0]
--gamma-correction Default|User defined|High density printing|Low density printing|High contrast printing [Default]
Selects the gamma correction value from a list of pre-defined devices
or the user defined table, which can be downloaded to the scanner
--color-correction No Correction|User defined|Impact-dot printers|Thermal printers|Ink-jet printers|CRT monitors [CRT monitors]
Sets the color correction table for the selected output device.
--resolution 50|60|72|75|80|90|100|120|133|144|150|160|175|180|200|216|240|266|300|320|350|360|400|480|600|720|800|900|1200|1600|1800|2400dpi [50]
Sets the resolution of the scanned image.
--threshold 0..255 [128]
Select minimum-brightness to get a white point
Advanced:
--mirror[=(yes|no)] [no]
Mirror the image.
--speed[=(yes|no)] [no]
Determines the speed at which the scan proceeds.
--auto-area-segmentation[=(yes|no)] [yes]
--short-resolution[=(yes|no)] [no]
Display short resolution list
--zoom 50..200 [inactive]
Defines the zoom factor the scanner will use
--red-gamma-table 0..255,... [inactive]
Gamma-correction table for the red band.
--green-gamma-table 0..255,... [inactive]
Gamma-correction table for the green band.
--blue-gamma-table 0..255,... [inactive]
Gamma-correction table for the blue band.
--wait-for-button[=(yes|no)] [no]
After sending the scan command, wait until the button on the scanner
is pressed to actually start the scan process.
Color correction coefficients:
--cct-1 -127..127 [inactive]
Controls green level
--cct-2 -127..127 [inactive]
Adds to red based on green level
--cct-3 -127..127 [inactive]
Adds to blue based on green level
--cct-4 -127..127 [inactive]
Adds to green based on red level
--cct-5 -127..127 [inactive]
Controls red level
--cct-6 -127..127 [inactive]
Adds to blue based on red level
--cct-7 -127..127 [inactive]
Adds to green based on blue level
--cct-8 -127..127 [inactive]
Adds to red based on blue level
--cct-9 -127..127 [inactive]
Controls blue level
Preview:
--preview[=(yes|no)] [no]
Request a preview-quality scan.
--preview-speed[=(yes|no)] [no]
Geometry:
-l 0..215.9mm [0]
Top-left x position of scan area.
-t 0..297.18mm [0]
Top-left y position of scan area.
-x 0..215.9mm [215.9]
Width of scan-area.
-y 0..297.18mm [297.18]
Height of scan-area.
--quick-format CD|A5 portrait|A5 landscape|Letter|A4|Max [Max]
Optional equipment:
--source Flatbed [inactive]
Selects the scan source (such as a document-feeder).
--auto-eject[=(yes|no)] [inactive]
Eject document after scanning
--film-type Positive Film|Negative Film [inactive]
--focus-position Focus on glass|Focus 2.5mm above glass [inactive]
Sets the focus position to either the glass or 2.5mm above the glass
--bay 1 | 2 | 3 | 4 | 5 | 6 [inactive]
Select bay to scan
--eject [inactive]
Eject the sheet in the ADF
--adf_mode Simplex|Duplex [inactive]
Selects the ADF mode (simplex/duplex)
Type ``scanimage --help -d DEVICE'' to get list of all options for DEVICE.
List of available devices:
net:esche:epson:libusb:001:006
gscan2pdf-1.2.3/scanners/niash 0000644 0001750 0001750 00000005201 12053230657 014634 0 ustar jeff jeff Usage: scanimage [OPTION]...
Start image acquisition on a scanner device and write PNM image data to standard output.
-d, --device-name=DEVICE use a given scanner device (e.g. hp:/dev/scanner)
--format=pnm|tiff file format of output file
-i, --icc-profile=PROFILE include this ICC profile into TIFF file
-L, --list-devices show available scanner devices
-f, --formatted-device-list=FORMAT similar to -L, but the FORMAT of the output
can be specified: %d (device name), %v (vendor),
%m (model), %t (type), and %i (index number)
-b, --batch[=FORMAT] working in batch mode, FORMAT is `out%d.pnm' or
`out%d.tif' by default depending on --format
--batch-start=# page number to start naming files with
--batch-count=# how many pages to scan in batch mode
--batch-increment=# increase number in filename by an amount of #
--batch-double increment page number by two for 2sided originals
being scanned in a single sided scanner
--batch-prompt ask for pressing a key before scanning a page
--accept-md5-only only accept authorization requests using md5
-p, --progress print progress messages
-n, --dont-scan only set options, don't actually scan
-T, --test test backend thoroughly
-h, --help display this help message and exit
-v, --verbose give even more status messages
-B, --buffer-size change default input buffersize
-V, --version print version information
Options specific to device `niash:libusb:003:002':
Geometry:
-l 0..220mm (in steps of 1) [0]
Top-left x position of scan area.
-t 0..297mm (in steps of 1) [0]
Top-left y position of scan area.
-x 0..220mm (in steps of 1) [210]
Width of scan-area.
-y 0..297mm (in steps of 1) [290]
Height of scan-area.
--resolution 75|150|300|600dpi [150]
Sets the resolution of the scanned image.
Image:
--gamma-table 0..255,... (in steps of 1)
Gamma-correction table. In color mode this option equally affects the
red, green, and blue channels simultaneously (i.e., it is an intensity
gamma table).
Scan Mode:
--mode Color|Gray|Lineart [Color]
Selects the scan mode (e.g., lineart, monochrome, or color).
Enhancement:
--threshold 0..100% (in steps of 1) [inactive]
Select minimum-brightness to get a white point
Type ``scanimage --help -d DEVICE'' to get list of all options for DEVICE.
List of available devices:
niash:libusb:003:002
gscan2pdf-1.2.3/scanners/psc1315 0000644 0001750 0001750 00000007425 12053230657 014643 0 ustar jeff jeff Usage: scanimage [OPTION]...
Start image acquisition on a scanner device and write PNM image data to standard output.
-d, --device-name=DEVICE use a given scanner device (e.g. hp:/dev/scanner)
--format=pnm|tiff file format of output file
-i, --icc-profile=PROFILE include this ICC profile into TIFF file
-L, --list-devices show available scanner devices
-f, --formatted-device-list=FORMAT similar to -L, but the FORMAT of the output
can be specified: %d (device name), %v (vendor),
%m (model), %t (type), and %i (index number)
-b, --batch[=FORMAT] working in batch mode, FORMAT is `out%d.pnm' or
`out%d.tif' by default depending on --format
--batch-start=# page number to start naming files with
--batch-count=# how many pages to scan in batch mode
--batch-increment=# increase number in filename by an amount of #
--batch-double increment page number by two for 2sided originals
being scanned in a single sided scanner
--batch-prompt ask for pressing a key before scanning a page
--accept-md5-only only accept authorization requests using md5
-p, --progress print progress messages
-n, --dont-scan only set options, don't actually scan
-T, --test test backend thoroughly
-h, --help display this help message and exit
-v, --verbose give even more status messages
-B, --buffer-size change default input buffersize
-V, --version print version information
Options specific to device
`hpaio:/usb/psc_1310_series_?serial=MY41J1D14PO2':
Scan mode:
--mode Lineart|Grayscale|Color [Color]
Selects the scan mode (e.g., lineart, monochrome, or color).
--resolution 75..600dpi [75]
Sets the resolution of the scanned image.
Advanced:
--contrast 0..100 [inactive]
Controls the contrast of the acquired image.
--compression None|JPEG [JPEG]
Selects the scanner compression method for faster scans, possibly at
the expense of image quality.
--jpeg-compression-factor 0..100 [10]
Sets the scanner JPEG compression factor. Larger numbers mean better
compression, and smaller numbers mean better image quality.
--batch-scan[=(yes|no)] [no]
Guarantees that a "no documents" condition will be returned after the
last scanned page, to prevent endless flatbed scans after a batch scan.
For some models, option changes in the middle of a batch scan don't
take effect until after the last page.
--source Flatbed [Flatbed]
Selects the desired scan source for models with both flatbed and
automatic document feeder (ADF) capabilities. The "Auto" setting means
that the ADF will be used if it's loaded, and the flatbed (if present)
will be used otherwise.
--duplex[=(yes|no)] [inactive]
Enables scanning on both sides of the page for models with
duplex-capable document feeders. For pages printed in "book"-style
duplex mode, one side will be scanned upside-down. This feature is
experimental.
Geometry:
--length-measurement Unknown|Approximate|Padded [Padded]
Selects how the scanned image length is measured and reported, which
is impossible to know in advance for scrollfed scans.
-l 0..215.9mm [0]
Top-left x position of scan area.
-t 0..296.926mm [0]
Top-left y position of scan area.
-x 0..215.9mm [215.9]
Width of scan-area.
-y 0..296.926mm [296.926]
Height of scan-area.
Type ``scanimage --help -d DEVICE'' to get list of all options for DEVICE.
List of available devices:
hpaio:/usb/psc_1310_series_?serial=MY41J1D14PO2
gscan2pdf-1.2.3/scanners/hp_scanjet5470c 0000644 0001750 0001750 00000004743 12053230657 016345 0 ustar jeff jeff Usage: scanimage [OPTION]...
Start image acquisition on a scanner device and write PNM image data to standard output.
-d, --device-name=DEVICE use a given scanner device (e.g. hp:/dev/scanner)
--format=pnm|tiff file format of output file
-i, --icc-profile=PROFILE include this ICC profile into TIFF file
-L, --list-devices show available scanner devices
-f, --formatted-device-list=FORMAT similar to -L, but the FORMAT of the output
can be specified: %d (device name), %v (vendor),
%m (model), %t (type), and %i (index number)
-b, --batch[=FORMAT] working in batch mode, FORMAT is `out%d.pnm' or
`out%d.tif' by default depending on --format
--batch-start=# page number to start naming files with
--batch-count=# how many pages to scan in batch mode
--batch-increment=# increase number in filename by an amount of #
--batch-double increment page number by two for 2sided originals
being scanned in a single sided scanner
--batch-prompt ask for pressing a key before scanning a page
--accept-md5-only only accept authorization requests using md5
-p, --progress print progress messages
-n, --dont-scan only set options, don't actually scan
-T, --test test backend thoroughly
-h, --help display this help message and exit
-v, --verbose give even more status messages
-B, --buffer-size change default input buffersize
-V, --version print version information
Options specific to device `hp5400:libusb:002:002':
Geometry:
-l 0..220mm (in steps of 1) [5]
Top-left x position of scan area.
-t 0..300mm (in steps of 1) [52]
Top-left y position of scan area.
-x 0..215mm (in steps of 1) [220]
Width of scan-area.
-y 0..248mm (in steps of 1) [300]
Height of scan-area.
--resolution 75|150|300|600|1200dpi [75]
Sets the resolution of the scanned image.
Image:
--red-gamma-table 0..65535,... (in steps of 1)
Gamma-correction table for the red band.
--green-gamma-table 0..65535,... (in steps of 1)
Gamma-correction table for the green band.
--blue-gamma-table 0..65535,... (in steps of 1)
Gamma-correction table for the blue band.
Type ``scanimage --help -d DEVICE'' to get list of all options for DEVICE.
List of available devices:
hp:libusb:001:002
gscan2pdf-1.2.3/scanners/officejet_5500.gray 0000644 0001750 0001750 00000006214 12053230657 017107 0 ustar jeff jeff Usage: scanimage [OPTION]...
Start image acquisition on a scanner device and write PNM image data to
standard output.
-d, --device-name=DEVICE use a given scanner device (e.g. hp:/dev/scanner)
--format=pnm|tiff file format of output file
-i, --icc-profile=PROFILE include this ICC profile into TIFF file
-L, --list-devices show available scanner devices
-f, --formatted-device-list=FORMAT similar to -L, but the FORMAT of the output
can be specified: %d (device name), %v (vendor),
%m (model), %t (type), and %i (index number)
-b, --batch[=FORMAT] working in batch mode, FORMAT is `out%d.pnm' or
`out%d.tif' by default depending on --format
--batch-start=# page number to start naming files with
--batch-count=# how many pages to scan in batch mode
--batch-increment=# increase number in filename by an amount of #
--batch-double increment page number by two for 2sided originals
being scanned in a single sided scanner
--batch-prompt ask for pressing a key before scanning a page
--accept-md5-only only accept authorization requests using md5
-p, --progress print progress messages
-n, --dont-scan only set options, don't actually scan
-T, --test test backend thoroughly
-h, --help display this help message and exit
-v, --verbose give even more status messages
-B, --buffer-size change default input buffersize
-V, --version print version information
Options specific to device `hpaio:/usb/officejet_5500_series?serial=MY42QF209H96':
Scan mode:
--mode Lineart|Gray|Color [Gray]
Selects the scan mode (e.g., lineart, monochrome, or color).
--resolution 75..600dpi [75]
Sets the resolution of the scanned image.
Advanced:
--contrast 0..100 [inactive]
Controls the contrast of the acquired image.
--compression None|JPEG [JPEG]
Selects the scanner compression method for faster scans, possibly at
the expense of image quality.
--jpeg-quality 0..100 [10]
Sets the scanner JPEG compression factor. Larger numbers mean better
compression, and smaller numbers mean better image quality.
--batch-scan[=(yes|no)] [no]
Enables continuous scanning with automatic document feeder (ADF).
--source Auto|Flatbed|ADF [Auto]
Selects the scan source (such as a document-feeder).
Geometry:
--length-measurement Unknown|Approximate|Padded [Padded]
Selects how the scanned image length is measured and reported, which
is impossible to know in advance for scrollfed scans.
-l 0..215.9mm [0]
Top-left x position of scan area.
-t 0..381mm [0]
Top-left y position of scan area.
-x 0..215.9mm [215.9]
Width of scan-area.
-y 0..381mm [381]
Height of scan-area.
Type ``scanimage --help -d DEVICE'' to get list of all options for DEVICE.
List of available devices:
v4l:/dev/video2 v4l:/dev/video1 v4l:/dev/video0
hpaio:/usb/officejet_5500_series?serial=MY42QF209H96
gscan2pdf-1.2.3/scanners/Brother_MFC-8860DN 0000644 0001750 0001750 00000005342 12053230657 016457 0 ustar jeff jeff Usage: scanimage [OPTION]...
Start image acquisition on a scanner device and write PNM image data to standard output.
-d, --device-name=DEVICE use a given scanner device (e.g. hp:/dev/scanner)
--format=pnm|tiff file format of output file
-i, --icc-profile=PROFILE include this ICC profile into TIFF file
-L, --list-devices show available scanner devices
-f, --formatted-device-list=FORMAT similar to -L, but the FORMAT of the output
can be specified: %d (device name), %v (vendor),
%m (model), %t (type), and %i (index number)
-b, --batch[=FORMAT] working in batch mode, FORMAT is `out%d.pnm' or
`out%d.tif' by default depending on --format
--batch-start=# page number to start naming files with
--batch-count=# how many pages to scan in batch mode
--batch-increment=# increase number in filename by an amount of #
--batch-double increment page number by two for 2sided originals
being scanned in a single sided scanner
--batch-prompt ask for pressing a key before scanning a page
--accept-md5-only only accept authorization requests using md5
-p, --progress print progress messages
-n, --dont-scan only set options, don't actually scan
-T, --test test backend thoroughly
-h, --help display this help message and exit
-v, --verbose give even more status messages
-B, --buffer-size change default input buffersize
-V, --version print version information
Options specific to device `brother2:net1;dev0':
Mode:
--mode Black & White|Gray[Error Diffusion]|True Gray|24bit Color|24bit Color[Fast] [24bit Color]
Select the scan mode
--resolution 100|150|200|300|400|600|1200|2400|4800|9600dpi [200]
Sets the resolution of the scanned image.
--source FlatBed|Automatic Document Feeder|Automatic Document Feeder(Duplex) [Automatic Document Feeder]
Selects the scan source (such as a document-feeder).
--brightness -50..50% (in steps of 1) [inactive]
Controls the brightness of the acquired image.
--contrast -50..50% (in steps of 1) [inactive]
Controls the contrast of the acquired image.
Geometry:
-l 0..215.9mm (in steps of 0.0999908) [0]
Top-left x position of scan area.
-t 0..355.6mm (in steps of 0.0999908) [0]
Top-left y position of scan area.
-x 0..215.9mm (in steps of 0.0999908) [215.88]
Width of scan-area.
-y 0..355.6mm (in steps of 0.0999908) [355.567]
Height of scan-area.
Type ``scanimage --help -d DEVICE'' to get list of all options for DEVICE.
List of available devices:
brother2:net1;dev0
gscan2pdf-1.2.3/scanners/snapscanS510.Lineart 0000644 0001750 0001750 00000010552 12053230657 017313 0 ustar jeff jeff Usage: scanimage [OPTION]...
Start image acquisition on a scanner device and write PNM image data to
standard output.
Parameters are separated by a blank from single-character options (e.g.
-d epson) and by a "=" from multi-character options (e.g. --device-name=epson).
-d, --device-name=DEVICE use a given scanner device (e.g. hp:/dev/scanner)
--format=pnm|tiff file format of output file
-i, --icc-profile=PROFILE include this ICC profile into TIFF file
-L, --list-devices show available scanner devices
-f, --formatted-device-list=FORMAT similar to -L, but the FORMAT of the output
can be specified: %d (device name), %v (vendor),
%m (model), %t (type), and %i (index number)
-b, --batch[=FORMAT] working in batch mode, FORMAT is `out%d.pnm' or
`out%d.tif' by default depending on --format
--batch-start=# page number to start naming files with
--batch-count=# how many pages to scan in batch mode
--batch-increment=# increase number in filename by an amount of #
--batch-double increment page number by two for 2sided originals
being scanned in a single sided scanner
--batch-prompt ask for pressing a key before scanning a page
--accept-md5-only only accept authorization requests using md5
-p, --progress print progress messages
-n, --dont-scan only set options, don't actually scan
-T, --test test backend thoroughly
-h, --help display this help message and exit
-v, --verbose give even more status messages
-B, --buffer-size change default input buffersize
-V, --version print version information
Options specific to device `fujitsu:libusb:007:032':
Scan Mode:
--source ADF Front|ADF Back|ADF Duplex [ADF Front]
Selects the scan source (such as a document-feeder).
--mode Lineart|Halftone|Gray|Color [Lineart]
Selects the scan mode (e.g., lineart, monochrome, or color).
--resolution 50..600dpi (in steps of 1) [600]
Sets the horizontal resolution of the scanned image.
--y-resolution 50..600dpi (in steps of 1) [600]
Sets the vertical resolution of the scanned image.
Geometry:
-l 0..215.872mm (in steps of 0.0211639) [0]
Top-left x position of scan area.
-t 0..279.364mm (in steps of 0.0211639) [0]
Top-left y position of scan area.
-x 0..215.872mm (in steps of 0.0211639) [215.872]
Width of scan-area.
-y 0..279.364mm (in steps of 0.0211639) [279.364]
Height of scan-area.
--pagewidth 0..221.121mm (in steps of 0.0211639) [215.872]
Must be set properly to align scanning window
--pageheight 0..863.489mm (in steps of 0.0211639) [279.364]
Must be set properly to eject pages
Enhancement:
--brightness -127..127 (in steps of 1) [0]
Controls the brightness of the acquired image.
--contrast -127..127 (in steps of 1) [0]
Controls the contrast of the acquired image.
--threshold 0..255 (in steps of 1) [0]
Select minimum-brightness to get a white point
--rif[=(yes|no)] [no]
Reverse image format
Advanced:
--compression None|JPEG [None]
Enable compressed data. May crash your front-end program
--compression-arg 0..7 (in steps of 1) [0]
Level of JPEG compression. 1 is small file, 7 is large file. 0
(default) is same as 4
--dfdetect Default|None|Thickness|Length|Both [Default]
Enable double feed sensors
--dfdiff Default|10mm|15mm|20mm [Default]
Difference in page length to trigger double feed sensor
--dropoutcolor Default|Red|Green|Blue [Default]
One-pass scanners use only one color during gray or binary scanning,
useful for colored paper or ink
--overscan Default|Off|On [Default]
Collect a few mm of background on top side of scan, before paper
enters ADF, and increase maximum scan area beyond paper size, to allow
collection on remaining sides. May conflict with bgcolor option
--sleeptimer 0..60 (in steps of 1) [0]
Time in minutes until the internal power supply switches to sleep mode
Sensors and Buttons:
Type ``scanimage --help -d DEVICE'' to get list of all options for DEVICE.
List of available devices:
v4l:/dev/video0 fujitsu:libusb:007:032
gscan2pdf-1.2.3/scanners/epson_3490 0000644 0001750 0001750 00000013270 12053230657 015342 0 ustar jeff jeff Usage: scanimage [OPTION]...
Start image acquisition on a scanner device and write PNM image data to
standard output.
-d, --device-name=DEVICE use a given scanner device (e.g. hp:/dev/scanner)
--format=pnm|tiff file format of output file
-i, --icc-profile=PROFILE include this ICC profile into TIFF file
-L, --list-devices show available scanner devices
-f, --formatted-device-list=FORMAT similar to -L, but the FORMAT of the output
can be specified: %d (device name), %v (vendor),
%m (model), %t (type), and %i (index number)
-b, --batch[=FORMAT] working in batch mode, FORMAT is `out%d.pnm' or
`out%d.tif' by default depending on --format
--batch-start=# page number to start naming files with
--batch-count=# how many pages to scan in batch mode
--batch-increment=# increase number in filename by an amount of #
--batch-double increment page number by two for 2sided originals
being scanned in a single sided scanner
--batch-prompt ask for pressing a key before scanning a page
--accept-md5-only only accept authorization requests using md5
-p, --progress print progress messages
-n, --dont-scan only set options, don't actually scan
-T, --test test backend thoroughly
-h, --help display this help message and exit
-v, --verbose give even more status messages
-B, --buffer-size change default input buffersize
-V, --version print version information
Options specific to device `snapscan:libusb:005:007':
Scan Mode:
--resolution auto||50|150|200|240|266|300|350|360|400|600|720|800|1200|1600|3200dpi [300]
Sets the resolution of the scanned image.
--preview[=(auto|yes|no)] [no]
Request a preview-quality scan.
--mode auto|Color|Gray|Lineart [Color]
Selects the scan mode (e.g., lineart, monochrome, or color).
--preview-mode auto|Auto|Color|Gray|Lineart [Auto]
Select the mode for previews. Greyscale previews usually give the best
combination of speed and detail.
--high-quality[=(auto|yes|no)] [no]
Highest quality but lower speed
--source auto|Flatbed|Transparency Adapter [Flatbed]
Selects the scan source (such as a document-feeder).
Geometry:
-l auto|0..216mm [0]
Top-left x position of scan area.
-t auto|0..297mm [0]
Top-left y position of scan area.
-x auto|0..216mm [216]
Width of scan-area.
-y auto|0..297mm [297]
Height of scan-area.
--predef-window None|6x4 (inch)|8x10 (inch)|8.5x11 (inch) [None]
Provides standard scanning areas for photographs, printed pages and
the like.
Enhancement:
--depth 8|16bit [8]
Number of bits per sample, typical values are 1 for "line-art" and 8
for multibit scans.
--quality-cal[=(yes|no)] [yes]
Do a quality white-calibration
--halftoning[=(yes|no)] [inactive]
Selects whether the acquired image should be halftoned (dithered).
--halftone-pattern DispersedDot8x8|DispersedDot16x16 [inactive]
Defines the halftoning (dithering) pattern for scanning halftoned
images.
--custom-gamma[=(yes|no)] [no]
Determines whether a builtin or a custom gamma-table should be used.
--analog-gamma-bind[=(yes|no)] [no]
In RGB-mode use same values for each color
--analog-gamma 0..4 [inactive]
Analog gamma-correction
--analog-gamma-r 0..4 [1.79999]
Analog gamma-correction for red
--analog-gamma-g 0..4 [1.79999]
Analog gamma-correction for green
--analog-gamma-b 0..4 [1.79999]
Analog gamma-correction for blue
--gamma-table 0..65535,... (in steps of 1) [inactive]
Gamma-correction table. In color mode this option equally affects the
red, green, and blue channels simultaneously (i.e., it is an intensity
gamma table).
--red-gamma-table 0..65535,... (in steps of 1) [inactive]
Gamma-correction table for the red band.
--green-gamma-table 0..65535,... (in steps of 1) [inactive]
Gamma-correction table for the green band.
--blue-gamma-table 0..65535,... (in steps of 1) [inactive]
Gamma-correction table for the blue band.
--negative[=(auto|yes|no)] [inactive]
Swap black and white
--threshold 0..100% (in steps of 1) [inactive]
Select minimum-brightness to get a white point
--brightness -400..400% (in steps of 1) [0]
Controls the brightness of the acquired image.
--contrast -100..400% (in steps of 1) [0]
Controls the contrast of the acquired image.
Advanced:
--rgb-lpr auto|1..50 (in steps of 1) [4]
Number of scan lines to request in a SCSI read. Changing this
parameter allows you to tune the speed at which data is read from the
scanner during scans. If this is set too low, the scanner will have to
stop periodically in the middle of a scan; if it's set too high,
X-based frontends may stop responding to X events and your system could
bog down.
--gs-lpr auto|1..50 (in steps of 1) [inactive]
Number of scan lines to request in a SCSI read. Changing this
parameter allows you to tune the speed at which data is read from the
scanner during scans. If this is set too low, the scanner will have to
stop periodically in the middle of a scan; if it's set too high,
X-based frontends may stop responding to X events and your system could
bog down.
Type ``scanimage --help -d DEVICE'' to get list of all options for DEVICE.
List of available devices:
snapscan:libusb:005:007
gscan2pdf-1.2.3/scanners/Brother_DCP-7025 0000644 0001750 0001750 00000005310 12053230657 016221 0 ustar jeff jeff Usage: scanimage [OPTION]...
Start image acquisition on a scanner device and write PNM image data to standard output.
-d, --device-name=DEVICE use a given scanner device (e.g. hp:/dev/scanner)
--format=pnm|tiff file format of output file
-i, --icc-profile=PROFILE include this ICC profile into TIFF file
-L, --list-devices show available scanner devices
-f, --formatted-device-list=FORMAT similar to -L, but the FORMAT of the output
can be specified: %d (device name), %v (vendor),
%m (model), %t (type), and %i (index number)
-b, --batch[=FORMAT] working in batch mode, FORMAT is `out%d.pnm' or
`out%d.tif' by default depending on --format
--batch-start=# page number to start naming files with
--batch-count=# how many pages to scan in batch mode
--batch-increment=# increase number in filename by an amount of #
--batch-double increment page number by two for 2sided originals
being scanned in a single sided scanner
--batch-prompt ask for pressing a key before scanning a page
--accept-md5-only only accept authorization requests using md5
-p, --progress print progress messages
-n, --dont-scan only set options, don't actually scan
-T, --test test backend thoroughly
-h, --help display this help message and exit
-v, --verbose give even more status messages
-B, --buffer-size change default input buffersize
-V, --version print version information
Options specific to device `brother2:bus5;dev1':
Mode:
--mode Black & White|Gray[Error Diffusion]|True Gray|24bit Color|24bit Color[Fast] [Black & White]
Select the scan mode
--resolution 100|150|200|300|400|600|1200|2400|4800|9600dpi [200]
Sets the resolution of the scanned image.
--source FlatBed|Automatic Document Feeder [Automatic Document Feeder]
Selects the scan source (such as a document-feeder).
--brightness -50..50% (in steps of 1) [0]
Controls the brightness of the acquired image.
--contrast -50..50% (in steps of 1) [inactive]
Controls the contrast of the acquired image.
Geometry:
-l 0..210mm (in steps of 0.0999908) [0]
Top-left x position of scan area.
-t 0..297mm (in steps of 0.0999908) [0]
Top-left y position of scan area.
-x 0..210mm (in steps of 0.0999908) [209.981]
Width of scan-area.
-y 0..297mm (in steps of 0.0999908) [296.973]
Height of scan-area.
Type ``scanimage --help -d DEVICE'' to get list of all options for DEVICE.
List of available devices:
brother2:bus5;dev1
gscan2pdf-1.2.3/scanners/canonFB630u 0000644 0001750 0001750 00000004554 12053230657 015470 0 ustar jeff jeff Usage: scanimage [OPTION]...
Start image acquisition on a scanner device and write PNM image data to
standard output.
-d, --device-name=DEVICE use a given scanner device (e.g. hp:/dev/scanner)
--format=pnm|tiff file format of output file
-i, --icc-profile=PROFILE include this ICC profile into TIFF file
-L, --list-devices show available scanner devices
-f, --formatted-device-list=FORMAT similar to -L, but the FORMAT of the output
can be specified: %d (device name), %v (vendor),
%m (model), %t (type), and %i (index number)
-b, --batch[=FORMAT] working in batch mode, FORMAT is `out%d.pnm' or
`out%d.tif' by default depending on --format
--batch-start=# page number to start naming files with
--batch-count=# how many pages to scan in batch mode
--batch-increment=# increase number in filename by an amount of #
--batch-double increment page number by two for 2sided originals
being scanned in a single sided scanner
--batch-prompt ask for pressing a key before scanning a page
--accept-md5-only only accept authorization requests using md5
-p, --progress print progress messages
-n, --dont-scan only set options, don't actually scan
-T, --test test backend thoroughly
-h, --help display this help message and exit
-v, --verbose give even more status messages
-B, --buffer-size change default input buffersize
-V, --version print version information
Options specific to device `canon630u:libusb:002:005':
--resolution auto||75|150|300|600dpi [75]
Sets the resolution of the scanned image.
--cal[=(yes|no)] [no]
Force scanner calibration before scan
--gain 0..64 (in steps of 1) [1]
Increase or decrease the analog gain of the CCD array
--gamma [1.59999]
Selects the gamma corrected transfer curve
-l 0..215.9mm [0]
Top-left x position of scan area.
-t 0..296.333mm [0]
Top-left y position of scan area.
-x 0..215.9mm [215.9]
Width of scan-area.
-y 0..296.333mm [296.3]
Height of scan-area.
Type ``scanimage --help -d DEVICE'' to get list of all options for DEVICE.
List of available devices:
canon_pp:parport0
gscan2pdf-1.2.3/scanners/canonLiDE25 0000644 0001750 0001750 00000011347 12053230657 015505 0 ustar jeff jeff Usage: scanimage [OPTION]...
Start image acquisition on a scanner device and write PNM image data to
standard output.
-d, --device-name=DEVICE use a given scanner device (e.g. hp:/dev/scanner)
--format=pnm|tiff file format of output file
-i, --icc-profile=PROFILE include this ICC profile into TIFF file
-L, --list-devices show available scanner devices
-f, --formatted-device-list=FORMAT similar to -L, but the FORMAT of the output
can be specified: %d (device name), %v (vendor),
%m (model), %t (type), and %i (index number)
-b, --batch[=FORMAT] working in batch mode, FORMAT is `out%d.pnm' or
`out%d.tif' by default depending on --format
--batch-start=# page number to start naming files with
--batch-count=# how many pages to scan in batch mode
--batch-increment=# increase number in filename by an amount of #
--batch-double increment page number by two for 2sided originals
being scanned in a single sided scanner
--batch-prompt ask for pressing a key before scanning a page
--accept-md5-only only accept authorization requests using md5
-p, --progress print progress messages
-n, --dont-scan only set options, don't actually scan
-T, --test test backend thoroughly
-h, --help display this help message and exit
-v, --verbose give even more status messages
-B, --buffer-size change default input buffersize
-V, --version print version information
Options specific to device `plustek:libusb:001:002':
Scan Mode:
--mode Lineart|Gray|Color [Color]
Selects the scan mode (e.g., lineart, monochrome, or color).
--depth 8|16 [8]
Number of bits per sample, typical values are 1 for "line-art" and 8
for multibit scans.
--source Normal|Transparency|Negative [inactive]
Selects the scan source (such as a document-feeder).
--resolution 50..2400dpi [50]
Sets the resolution of the scanned image.
--preview[=(yes|no)] [no]
Request a preview-quality scan.
Geometry:
-l 0..215mm [0]
Top-left x position of scan area.
-t 0..297mm [0]
Top-left y position of scan area.
-x 0..215mm [103]
Width of scan-area.
-y 0..297mm [76.21]
Height of scan-area.
Enhancement:
--brightness -100..100% (in steps of 1) [0]
Controls the brightness of the acquired image.
--contrast -100..100% (in steps of 1) [0]
Controls the contrast of the acquired image.
--custom-gamma[=(yes|no)] [no]
Determines whether a builtin or a custom gamma-table should be used.
--gamma-table 0..255,... [inactive]
Gamma-correction table. In color mode this option equally affects the
red, green, and blue channels simultaneously (i.e., it is an intensity
gamma table).
--red-gamma-table 0..255,... [inactive]
Gamma-correction table for the red band.
--green-gamma-table 0..255,... [inactive]
Gamma-correction table for the green band.
--blue-gamma-table 0..255,... [inactive]
Gamma-correction table for the blue band.
Device-Settings:
--lamp-switch[=(yes|no)] [no]
Manually switching the lamp(s).
--lampoff-time 0..999 (in steps of 1) [300]
Lampoff-time in seconds.
--lamp-off-at-exit[=(yes|no)] [yes]
Turn off lamp when program exits
--warmup-time -1..999 (in steps of 1) [inactive]
Warmup-time in seconds.
--calibration-cache[=(yes|no)] [no]
Enables or disables calibration data cache.
--speedup-switch[=(yes|no)] [inactive]
Enables or disables speeding up sensor movement.
--calibrate [inactive]
Performs calibration
Analog frontend:
--red-gain -1..63 (in steps of 1) [-1]
Red gain value of the AFE
--green-gain -1..63 (in steps of 1) [-1]
Green gain value of the AFE
--blue-gain -1..63 (in steps of 1) [-1]
Blue gain value of the AFE
--red-offset -1..63 (in steps of 1) [-1]
Red offset value of the AFE
--green-offset -1..63 (in steps of 1) [-1]
Green offset value of the AFE
--blue-offset -1..63 (in steps of 1) [-1]
Blue offset value of the AFE
--redlamp-off -1..16363 (in steps of 1) [-1]
Defines red lamp off parameter
--greenlamp-off -1..16363 (in steps of 1) [-1]
Defines green lamp off parameter
--bluelamp-off -1..16363 (in steps of 1) [-1]
Defines blue lamp off parameter
Buttons:
Type ``scanimage --help -d DEVICE'' to get list of all options for DEVICE.
List of available devices:
plustek:libusb:001:002
This device is a Canon LiDE25 USB flatbed scanner gscan2pdf-1.2.3/scanners/officejet_5500.Lineart 0000644 0001750 0001750 00000007470 12053230657 017550 0 ustar jeff jeff Usage: scanimage [OPTION]...
Start image acquisition on a scanner device and write PNM image data to standard output.
-d, --device-name=DEVICE use a given scanner device (e.g. hp:/dev/scanner)
--format=pnm|tiff file format of output file
-i, --icc-profile=PROFILE include this ICC profile into TIFF file
-L, --list-devices show available scanner devices
-f, --formatted-device-list=FORMAT similar to -L, but the FORMAT of the output
can be specified: %d (device name), %v (vendor),
%m (model), %t (type), and %i (index number)
-b, --batch[=FORMAT] working in batch mode, FORMAT is `out%d.pnm' or
`out%d.tif' by default depending on --format
--batch-start=# page number to start naming files with
--batch-count=# how many pages to scan in batch mode
--batch-increment=# increase number in filename by an amount of #
--batch-double increment page number by two for 2sided originals
being scanned in a single sided scanner
--batch-prompt ask for pressing a key before scanning a page
--accept-md5-only only accept authorization requests using md5
-p, --progress print progress messages
-n, --dont-scan only set options, don't actually scan
-T, --test test backend thoroughly
-h, --help display this help message and exit
-v, --verbose give even more status messages
-B, --buffer-size change default input buffersize
-V, --version print version information
Options specific to device `hpaio:/usb/officejet_5500_series?serial=MY42QF209H96':
Scan mode:
--mode Lineart|Grayscale|Color [Color]
Selects the scan mode (e.g., lineart, monochrome, or color).
--resolution 75..600dpi [75]
Sets the resolution of the scanned image.
Advanced:
--contrast 0..100 [inactive]
Controls the contrast of the acquired image.
--compression None [None]
Selects the scanner compression method for faster scans, possibly at
the expense of image quality.
--jpeg-compression-factor 0..100 [10]
Sets the scanner JPEG compression factor. Larger numbers mean better
compression, and smaller numbers mean better image quality.
--batch-scan[=(yes|no)] [no]
Guarantees that a "no documents" condition will be returned after the
last scanned page, to prevent endless flatbed scans after a batch scan.
For some models, option changes in the middle of a batch scan don't
take effect until after the last page.
--source Auto|Flatbed|ADF [Auto]
Selects the desired scan source for models with both flatbed and
automatic document feeder (ADF) capabilities. The "Auto" setting means
that the ADF will be used if it's loaded, and the flatbed (if present)
will be used otherwise.
--duplex[=(yes|no)] [inactive]
Enables scanning on both sides of the page for models with
duplex-capable document feeders. For pages printed in "book"-style
duplex mode, one side will be scanned upside-down. This feature is
experimental.
Geometry:
--length-measurement Unknown|Approximate|Padded [Padded]
Selects how the scanned image length is measured and reported, which
is impossible to know in advance for scrollfed scans.
-l 0..215.9mm [0]
Top-left x position of scan area.
-t 0..381mm [0]
Top-left y position of scan area.
-x 0..215.9mm [215.9]
Width of scan-area.
-y 0..381mm [381]
Height of scan-area.
Type ``scanimage --help -d DEVICE'' to get list of all options for DEVICE.
List of available devices:
v4l:/dev/video1 v4l:/dev/video0
hpaio:/usb/officejet_5500_series?serial=MY42QF209H96
gscan2pdf-1.2.3/scanners/snapscanS510.Color 0000644 0001750 0001750 00000010135 12053230657 016770 0 ustar jeff jeff Usage: scanimage [OPTION]...
Start image acquisition on a scanner device and write PNM image data to
standard output.
Parameters are separated by a blank from single-character options (e.g.
-d epson) and by a "=" from multi-character options (e.g. --device-name=epson).
-d, --device-name=DEVICE use a given scanner device (e.g. hp:/dev/scanner)
--format=pnm|tiff file format of output file
-i, --icc-profile=PROFILE include this ICC profile into TIFF file
-L, --list-devices show available scanner devices
-f, --formatted-device-list=FORMAT similar to -L, but the FORMAT of the output
can be specified: %d (device name), %v (vendor),
%m (model), %t (type), and %i (index number)
-b, --batch[=FORMAT] working in batch mode, FORMAT is `out%d.pnm' or
`out%d.tif' by default depending on --format
--batch-start=# page number to start naming files with
--batch-count=# how many pages to scan in batch mode
--batch-increment=# increase number in filename by an amount of #
--batch-double increment page number by two for 2sided originals
being scanned in a single sided scanner
--batch-prompt ask for pressing a key before scanning a page
--accept-md5-only only accept authorization requests using md5
-p, --progress print progress messages
-n, --dont-scan only set options, don't actually scan
-T, --test test backend thoroughly
-h, --help display this help message and exit
-v, --verbose give even more status messages
-B, --buffer-size change default input buffersize
-V, --version print version information
Options specific to device `fujitsu:libusb:007:032':
Scan Mode:
--source ADF Front|ADF Back|ADF Duplex [ADF Front]
Selects the scan source (such as a document-feeder).
--mode Lineart|Halftone|Gray|Color [Color]
Selects the scan mode (e.g., lineart, monochrome, or color).
--resolution 50..600dpi (in steps of 1) [600]
Sets the horizontal resolution of the scanned image.
--y-resolution 50..600dpi (in steps of 1) [600]
Sets the vertical resolution of the scanned image.
Geometry:
-l 0..215.872mm (in steps of 0.0211639) [0]
Top-left x position of scan area.
-t 0..279.364mm (in steps of 0.0211639) [0]
Top-left y position of scan area.
-x 0..215.872mm (in steps of 0.0211639) [215.872]
Width of scan-area.
-y 0..279.364mm (in steps of 0.0211639) [279.364]
Height of scan-area.
--pagewidth 0..221.121mm (in steps of 0.0211639) [215.872]
Must be set properly to align scanning window
--pageheight 0..863.489mm (in steps of 0.0211639) [279.364]
Must be set properly to eject pages
Enhancement:
--brightness -127..127 (in steps of 1) [0]
Controls the brightness of the acquired image.
--contrast -127..127 (in steps of 1) [0]
Controls the contrast of the acquired image.
--rif[=(yes|no)] [no]
Reverse image format
Advanced:
--compression None|JPEG [None]
Enable compressed data. May crash your front-end program
--compression-arg 0..7 (in steps of 1) [0]
Level of JPEG compression. 1 is small file, 7 is large file. 0
(default) is same as 4
--dfdetect Default|None|Thickness|Length|Both [Default]
Enable double feed sensors
--dfdiff Default|10mm|15mm|20mm [Default]
Difference in page length to trigger double feed sensor
--overscan Default|Off|On [Default]
Collect a few mm of background on top side of scan, before paper
enters ADF, and increase maximum scan area beyond paper size, to allow
collection on remaining sides. May conflict with bgcolor option
--sleeptimer 0..60 (in steps of 1) [0]
Time in minutes until the internal power supply switches to sleep mode
Sensors and Buttons:
Type ``scanimage --help -d DEVICE'' to get list of all options for DEVICE.
List of available devices:
v4l:/dev/video0 fujitsu:libusb:007:032
gscan2pdf-1.2.3/scanners/xp450 0000644 0001750 0001750 00000007366 12053230657 014430 0 ustar jeff jeff Usage: scanimage [OPTION]...
Start image acquisition on a scanner device and write PNM image data to
standard output.
-d, --device-name=DEVICE use a given scanner device (e.g. hp:/dev/scanner)
--format=pnm|tiff file format of output file
-i, --icc-profile=PROFILE include this ICC profile into TIFF file
-L, --list-devices show available scanner devices
-f, --formatted-device-list=FORMAT similar to -L, but the FORMAT of the output
can be specified: %d (device name), %v (vendor),
%m (model), %t (type), and %i (index number)
-b, --batch[=FORMAT] working in batch mode, FORMAT is `out%d.pnm' or
`out%d.tif' by default depending on --format
--batch-start=# page number to start naming files with
--batch-count=# how many pages to scan in batch mode
--batch-increment=# increase number in filename by an amount of #
--batch-double increment page number by two for 2sided originals
being scanned in a single sided scanner
--batch-prompt ask for pressing a key before scanning a page
--accept-md5-only only accept authorization requests using md5
-p, --progress print progress messages
-n, --dont-scan only set options, don't actually scan
-T, --test test backend thoroughly
-h, --help display this help message and exit
-v, --verbose give even more status messages
-B, --buffer-size change default input buffersize
-V, --version print version information
Options specific to device `avision:libusb:002:007':
Scan mode:
--mode Lineart|Dithered|Gray|16bit Gray|Color|16bit Color [Color]
Selects the scan mode (e.g., lineart, monochrome, or color).
--resolution 50..600dpi (in steps of 5) [150]
Sets the resolution of the scanned image.
--speed 0..4 (in steps of 1) [inactive]
Determines the speed at which the scan proceeds.
--preview[=(yes|no)] [no]
Request a preview-quality scan.
--source ADF [ADF]
Selects the scan source (such as a document-feeder).
Geometry:
-l 0..216mm [0]
Top-left x position of scan area.
-t 0..297mm [0]
Top-left y position of scan area.
-x 0..216mm [216]
Width of scan-area.
-y 0..297mm [297]
Height of scan-area.
Enhancement:
--brightness -100..100% (in steps of 1) [0]
Controls the brightness of the acquired image.
--contrast -100..100% (in steps of 1) [0]
Controls the contrast of the acquired image.
--quality-scan[=(yes|no)] [yes]
Turn on quality scanning (slower but better).
--quality-cal[=(yes|no)] [yes]
Do a quality white-calibration
--gamma-table 0..255,...
Gamma-correction table. In color mode this option equally affects the
red, green, and blue channels simultaneously (i.e., it is an intensity
gamma table).
--red-gamma-table 0..255,... [inactive]
Gamma-correction table for the red band.
--green-gamma-table 0..255,... [inactive]
Gamma-correction table for the green band.
--blue-gamma-table 0..255,... [inactive]
Gamma-correction table for the blue band.
--frame 0..0 [inactive]
Selects the number of the frame to scan
--power-save-time [0]
Allows control of the scanner's power save timer, dimming or turning
off the light.
--nvram-values [Vendor: VISIONER
Model: Strobe XP 450
Firmware: 1.05]
Allows access obtaining the scanner's NVRAM values as pretty printed
text.
Type ``scanimage --help -d DEVICE'' to get list of all options for DEVICE.
List of available devices:
avision:libusb:002:007
gscan2pdf-1.2.3/scanners/snapscan 0000644 0001750 0001750 00000013232 12053230657 015343 0 ustar jeff jeff Usage: scanimage [OPTION]...
Start image acquisition on a scanner device and write PNM image data to
standard output.
-d, --device-name=DEVICE use a given scanner device (e.g. hp:/dev/scanner)
--format=pnm|tiff file format of output file
-i, --icc-profile=PROFILE include this ICC profile into TIFF file
-L, --list-devices show available scanner devices
-f, --formatted-device-list=FORMAT similar to -L, but the FORMAT of the output
can be specified: %d (device name), %v (vendor),
%m (model), %t (type), and %i (index number)
-b, --batch[=FORMAT] working in batch mode, FORMAT is `out%d.pnm' or
`out%d.tif' by default depending on --format
--batch-start=# page number to start naming files with
--batch-count=# how many pages to scan in batch mode
--batch-increment=# increase number in filename by an amount of #
--batch-double increment page number by two for 2sided originals
being scanned in a single sided scanner
--batch-prompt ask for pressing a key before scanning a page
--accept-md5-only only accept authorization requests using md5
-p, --progress print progress messages
-n, --dont-scan only set options, don't actually scan
-T, --test test backend thoroughly
-h, --help display this help message and exit
-v, --verbose give even more status messages
-B, --buffer-size change default input buffersize
-V, --version print version information
Options specific to device `snapscan:/dev/uscanner0':
Scan Mode:
--resolution auto||50|75|100|150|200|300|450|600dpi [300]
Sets the resolution of the scanned image.
--preview[=(auto|yes|no)] [no]
Request a preview-quality scan.
--mode auto|Color|Halftone|Gray|Lineart [Color]
Selects the scan mode (e.g., lineart, monochrome, or color).
--preview-mode auto|Auto|Color|Halftone|Gray|Lineart [Auto]
Select the mode for previews. Greyscale previews usually give the best
combination of speed and detail.
--high-quality[=(auto|yes|no)] [no]
Highest quality but lower speed
--source auto|Flatbed [inactive]
Selects the scan source (such as a document-feeder).
Geometry:
-l auto|0..216mm [0]
Top-left x position of scan area.
-t auto|0..297mm [0]
Top-left y position of scan area.
-x auto|0..216mm [216]
Width of scan-area.
-y auto|0..297mm [297]
Height of scan-area.
--predef-window None|6x4 (inch)|8x10 (inch)|8.5x11 (inch) [None]
Provides standard scanning areas for photographs, printed pages and
the like.
Enhancement:
--depth 8bit [inactive]
Number of bits per sample, typical values are 1 for "line-art" and 8
for multibit scans.
--quality-cal[=(yes|no)] [yes]
Do a quality white-calibration
--halftoning[=(yes|no)] [inactive]
Selects whether the acquired image should be halftoned (dithered).
--halftone-pattern DispersedDot8x8|DispersedDot16x16 [inactive]
Defines the halftoning (dithering) pattern for scanning halftoned
images.
--custom-gamma[=(yes|no)] [no]
Determines whether a builtin or a custom gamma-table should be used.
--analog-gamma-bind[=(yes|no)] [no]
In RGB-mode use same values for each color
--analog-gamma 0..4 [inactive]
Analog gamma-correction
--analog-gamma-r 0..4 [1.79999]
Analog gamma-correction for red
--analog-gamma-g 0..4 [1.79999]
Analog gamma-correction for green
--analog-gamma-b 0..4 [1.79999]
Analog gamma-correction for blue
--gamma-table 0..65535,... (in steps of 1) [inactive]
Gamma-correction table. In color mode this option equally affects the
red, green, and blue channels simultaneously (i.e., it is an intensity
gamma table).
--red-gamma-table 0..65535,... (in steps of 1) [inactive]
Gamma-correction table for the red band.
--green-gamma-table 0..65535,... (in steps of 1) [inactive]
Gamma-correction table for the green band.
--blue-gamma-table 0..65535,... (in steps of 1) [inactive]
Gamma-correction table for the blue band.
--negative[=(auto|yes|no)] [inactive]
Swap black and white
--threshold 0..100% (in steps of 1) [inactive]
Select minimum-brightness to get a white point
--brightness -400..400% (in steps of 1) [0]
Controls the brightness of the acquired image.
--contrast -100..400% (in steps of 1) [0]
Controls the contrast of the acquired image.
Advanced:
--rgb-lpr auto|1..50 (in steps of 1) [4]
Number of scan lines to request in a SCSI read. Changing this
parameter allows you to tune the speed at which data is read from the
scanner during scans. If this is set too low, the scanner will have to
stop periodically in the middle of a scan; if it's set too high,
X-based frontends may stop responding to X events and your system could
bog down.
--gs-lpr auto|1..50 (in steps of 1) [inactive]
Number of scan lines to request in a SCSI read. Changing this
parameter allows you to tune the speed at which data is read from the
scanner during scans. If this is set too low, the scanner will have to
stop periodically in the middle of a scan; if it's set too high,
X-based frontends may stop responding to X events and your system could
bog down.
Type ``scanimage --help -d DEVICE'' to get list of all options for DEVICE.
List of available devices:
snapscan:/dev/uscanner0
gscan2pdf-1.2.3/scanners/canoscan_FB_630P 0000644 0001750 0001750 00000004662 12237446454 016420 0 ustar jeff jeff Usage: scanimage [OPTION]...
Start image acquisition on a scanner device and write PNM image data to
standard output.
-d, --device-name=DEVICE use a given scanner device (e.g. hp:/dev/scanner)
--format=pnm|tiff file format of output file
-i, --icc-profile=PROFILE include this ICC profile into TIFF file
-L, --list-devices show available scanner devices
-f, --formatted-device-list=FORMAT similar to -L, but the FORMAT of the output
can be specified: %d (device name), %v (vendor),
%m (model), %t (type), and %i (index number)
-b, --batch[=FORMAT] working in batch mode, FORMAT is `out%d.pnm' or
`out%d.tif' by default depending on --format
--batch-start=# page number to start naming files with
--batch-count=# how many pages to scan in batch mode
--batch-increment=# increase number in filename by an amount of #
--batch-double increment page number by two for 2sided originals
being scanned in a single sided scanner
--batch-prompt ask for pressing a key before scanning a page
--accept-md5-only only accept authorization requests using md5
-p, --progress print progress messages
-n, --dont-scan only set options, don't actually scan
-T, --test test backend thoroughly
-h, --help display this help message and exit
-v, --verbose give even more status messages
-B, --buffer-size change default input buffersize
-V, --version print version information
Options specific to device `canon_pp:parport0':
--resolution 75|150|300|600dpi [75]
Sets the resolution of the scanned image.
--mode Gray|Color [Gray]
Selects the scan mode (e.g., lineart, monochrome, or color).
--depth 8|12 [8]
Number of bits per sample, typical values are 1 for "line-art" and 8
for multibit scans.
-l 0..215mm (in steps of 1869504867) [0]
Top-left x position of scan area.
-t 0..296mm (in steps of 1852795252) [0]
Top-left y position of scan area.
-x 3..216mm (in steps of 16) [100]
Width of scan-area.
-y 1..297mm [100]
Height of scan-area.
--quality-cal []
Do a quality white-calibration
Type ``scanimage --help -d DEVICE'' to get list of all options for DEVICE.
List of available devices:
canon_pp:parport0
gscan2pdf-1.2.3/scanners/psc1200 0000644 0001750 0001750 00000007423 12053230657 014632 0 ustar jeff jeff Usage: scanimage [OPTION]...
Start image acquisition on a scanner device and write PNM image data to
standard output.
-d, --device-name=DEVICE use a given scanner device (e.g. hp:/dev/scanner)
--format=pnm|tiff file format of output file
-i, --icc-profile=PROFILE include this ICC profile into TIFF file
-L, --list-devices show available scanner devices
-f, --formatted-device-list=FORMAT similar to -L, but the FORMAT of the output
can be specified: %d (device name), %v (vendor),
%m (model), %t (type), and %i (index number)
-b, --batch[=FORMAT] working in batch mode, FORMAT is `out%d.pnm' or
`out%d.tif' by default depending on --format
--batch-start=# page number to start naming files with
--batch-count=# how many pages to scan in batch mode
--batch-increment=# increase number in filename by an amount of #
--batch-double increment page number by two for 2sided originals
being scanned in a single sided scanner
--batch-prompt ask for pressing a key before scanning a page
--accept-md5-only only accept authorization requests using md5
-p, --progress print progress messages
-n, --dont-scan only set options, don't actually scan
-T, --test test backend thoroughly
-h, --help display this help message and exit
-v, --verbose give even more status messages
-B, --buffer-size change default input buffersize
-V, --version print version information
Options specific to device `hpaio:/usb/psc_1200_series?serial=UA468GB0RRT0':
Scan mode:
--mode Lineart|Grayscale|Color [Color]
Selects the scan mode (e.g., lineart, monochrome, or color).
--resolution 75..600dpi [75]
Sets the resolution of the scanned image.
Advanced:
--contrast 0..100 [inactive]
Controls the contrast of the acquired image.
--compression None|JPEG [JPEG]
Selects the scanner compression method for faster scans, possibly at
the expense of image quality.
--jpeg-compression-factor 0..100 [10]
Sets the scanner JPEG compression factor. Larger numbers mean better
compression, and smaller numbers mean better image quality.
--batch-scan[=(yes|no)] [no]
Guarantees that a "no documents" condition will be returned after the
last scanned page, to prevent endless flatbed scans after a batch scan.
For some models, option changes in the middle of a batch scan don't
take effect until after the last page.
--source Flatbed [Flatbed]
Selects the desired scan source for models with both flatbed and
automatic document feeder (ADF) capabilities. The "Auto" setting means
that the ADF will be used if it's loaded, and the flatbed (if present)
will be used otherwise.
--duplex[=(yes|no)] [inactive]
Enables scanning on both sides of the page for models with
duplex-capable document feeders. For pages printed in "book"-style
duplex mode, one side will be scanned upside-down. This feature is
experimental.
Geometry:
--length-measurement Unknown|Approximate|Padded [Padded]
Selects how the scanned image length is measured and reported, which
is impossible to know in advance for scrollfed scans.
-l 0..215.9mm [0]
Top-left x position of scan area.
-t 0..296.926mm [0]
Top-left y position of scan area.
-x 0..215.9mm [215.9]
Width of scan-area.
-y 0..296.926mm [296.926]
Height of scan-area.
Type ``scanimage --help -d DEVICE'' to get list of all options for DEVICE.
List of available devices:
hpaio:/usb/psc_1200_series?serial=UA468GB0RRT0
gscan2pdf-1.2.3/scanners/Brother_MFC_5100c 0000644 0001750 0001750 00000005447 12053230657 016450 0 ustar jeff jeff Usage: scanimage [OPTION]...
Start image acquisition on a scanner device and write PNM image data to standard output.
-d, --device-name=DEVICE use a given scanner device (e.g. hp:/dev/scanner)
--format=pnm|tiff file format of output file
-i, --icc-profile=PROFILE include this ICC profile into TIFF file
-L, --list-devices show available scanner devices
-f, --formatted-device-list=FORMAT similar to -L, but the FORMAT of the output
can be specified: %d (device name), %v (vendor),
%m (model), %t (type), and %i (index number)
-b, --batch[=FORMAT] working in batch mode, FORMAT is `out%d.pnm' or
`out%d.tif' by default depending on --format
--batch-start=# page number to start naming files with
--batch-count=# how many pages to scan in batch mode
--batch-increment=# increase number in filename by an amount of #
--batch-double increment page number by two for 2sided originals
being scanned in a single sided scanner
--batch-prompt ask for pressing a key before scanning a page
--accept-md5-only only accept authorization requests using md5
-p, --progress print progress messages
-n, --dont-scan only set options, don't actually scan
-T, --test test backend thoroughly
-h, --help display this help message and exit
-v, --verbose give even more status messages
-B, --buffer-size change default input buffersize
-V, --version print version information
scanimage: rounded value of br-x from 208 to 207.981
scanimage: rounded value of br-y from 297 to 296.973
Options specific to device `brother:bus1;dev2':
Mode:
--mode Black & White|Gray[Error Diffusion]|True Gray|24bit Color [24bit Color]
Select the scan mode
--resolution 100|150|200|300|400|600|1200|2400|4800|9600dpi [200]
Sets the resolution of the scanned image.
--source FlatBed|Automatic Document Feeder [Automatic Document Feeder]
Selects the scan source (such as a document-feeder).
--brightness -50..50% (in steps of 1) [inactive]
Controls the brightness of the acquired image.
--contrast -50..50% (in steps of 1) [inactive]
Controls the contrast of the acquired image.
Geometry:
-l 0..208mm (in steps of 0.0999908) [0]
Top-left x position of scan area.
-t 0..355.6mm (in steps of 0.0999908) [0]
Top-left y position of scan area.
-x 0..208mm (in steps of 0.0999908) [207.981]
Width of scan-area.
-y 0..355.6mm (in steps of 0.0999908) [296.973]
Height of scan-area.
Type ``scanimage --help -d DEVICE'' to get list of all options for DEVICE.
List of available devices:
brother:bus1;dev2
gscan2pdf-1.2.3/scanners/snapscanS510 0000644 0001750 0001750 00000010135 12053230657 015713 0 ustar jeff jeff Usage: scanimage [OPTION]...
Start image acquisition on a scanner device and write PNM image data to
standard output.
Parameters are separated by a blank from single-character options (e.g.
-d epson) and by a "=" from multi-character options (e.g. --device-name=epson).
-d, --device-name=DEVICE use a given scanner device (e.g. hp:/dev/scanner)
--format=pnm|tiff file format of output file
-i, --icc-profile=PROFILE include this ICC profile into TIFF file
-L, --list-devices show available scanner devices
-f, --formatted-device-list=FORMAT similar to -L, but the FORMAT of the output
can be specified: %d (device name), %v (vendor),
%m (model), %t (type), and %i (index number)
-b, --batch[=FORMAT] working in batch mode, FORMAT is `out%d.pnm' or
`out%d.tif' by default depending on --format
--batch-start=# page number to start naming files with
--batch-count=# how many pages to scan in batch mode
--batch-increment=# increase number in filename by an amount of #
--batch-double increment page number by two for 2sided originals
being scanned in a single sided scanner
--batch-prompt ask for pressing a key before scanning a page
--accept-md5-only only accept authorization requests using md5
-p, --progress print progress messages
-n, --dont-scan only set options, don't actually scan
-T, --test test backend thoroughly
-h, --help display this help message and exit
-v, --verbose give even more status messages
-B, --buffer-size change default input buffersize
-V, --version print version information
Options specific to device `fujitsu:libusb:007:032':
Scan Mode:
--source ADF Front|ADF Back|ADF Duplex [ADF Front]
Selects the scan source (such as a document-feeder).
--mode Lineart|Halftone|Gray|Color [Color]
Selects the scan mode (e.g., lineart, monochrome, or color).
--resolution 50..600dpi (in steps of 1) [600]
Sets the horizontal resolution of the scanned image.
--y-resolution 50..600dpi (in steps of 1) [600]
Sets the vertical resolution of the scanned image.
Geometry:
-l 0..215.872mm (in steps of 0.0211639) [0]
Top-left x position of scan area.
-t 0..279.364mm (in steps of 0.0211639) [0]
Top-left y position of scan area.
-x 0..215.872mm (in steps of 0.0211639) [215.872]
Width of scan-area.
-y 0..279.364mm (in steps of 0.0211639) [279.364]
Height of scan-area.
--pagewidth 0..221.121mm (in steps of 0.0211639) [215.872]
Must be set properly to align scanning window
--pageheight 0..863.489mm (in steps of 0.0211639) [279.364]
Must be set properly to eject pages
Enhancement:
--brightness -127..127 (in steps of 1) [0]
Controls the brightness of the acquired image.
--contrast -127..127 (in steps of 1) [0]
Controls the contrast of the acquired image.
--rif[=(yes|no)] [no]
Reverse image format
Advanced:
--compression None|JPEG [None]
Enable compressed data. May crash your front-end program
--compression-arg 0..7 (in steps of 1) [0]
Level of JPEG compression. 1 is small file, 7 is large file. 0
(default) is same as 4
--dfdetect Default|None|Thickness|Length|Both [Default]
Enable double feed sensors
--dfdiff Default|10mm|15mm|20mm [Default]
Difference in page length to trigger double feed sensor
--overscan Default|Off|On [Default]
Collect a few mm of background on top side of scan, before paper
enters ADF, and increase maximum scan area beyond paper size, to allow
collection on remaining sides. May conflict with bgcolor option
--sleeptimer 0..60 (in steps of 1) [0]
Time in minutes until the internal power supply switches to sleep mode
Sensors and Buttons:
Type ``scanimage --help -d DEVICE'' to get list of all options for DEVICE.
List of available devices:
v4l:/dev/video0 fujitsu:libusb:007:032
gscan2pdf-1.2.3/scanners/epson_3490.Lineart 0000644 0001750 0001750 00000013300 12053230657 016731 0 ustar jeff jeff Usage: scanimage [OPTION]...
Start image acquisition on a scanner device and write PNM image data to
standard output.
-d, --device-name=DEVICE use a given scanner device (e.g. hp:/dev/scanner)
--format=pnm|tiff file format of output file
-i, --icc-profile=PROFILE include this ICC profile into TIFF file
-L, --list-devices show available scanner devices
-f, --formatted-device-list=FORMAT similar to -L, but the FORMAT of the output
can be specified: %d (device name), %v (vendor),
%m (model), %t (type), and %i (index number)
-b, --batch[=FORMAT] working in batch mode, FORMAT is `out%d.pnm' or
`out%d.tif' by default depending on --format
--batch-start=# page number to start naming files with
--batch-count=# how many pages to scan in batch mode
--batch-increment=# increase number in filename by an amount of #
--batch-double increment page number by two for 2sided originals
being scanned in a single sided scanner
--batch-prompt ask for pressing a key before scanning a page
--accept-md5-only only accept authorization requests using md5
-p, --progress print progress messages
-n, --dont-scan only set options, don't actually scan
-T, --test test backend thoroughly
-h, --help display this help message and exit
-v, --verbose give even more status messages
-B, --buffer-size change default input buffersize
-V, --version print version information
Options specific to device `snapscan:libusb:005:007':
Scan Mode:
--resolution auto||50|150|200|240|266|300|350|360|400|600|720|800|1200|1600|3200dpi [300]
Sets the resolution of the scanned image.
--preview[=(auto|yes|no)] [no]
Request a preview-quality scan.
--mode auto|Color|Gray|Lineart [Color]
Selects the scan mode (e.g., lineart, monochrome, or color).
--preview-mode auto|Auto|Color|Gray|Lineart [Auto]
Select the mode for previews. Greyscale previews usually give the best
combination of speed and detail.
--high-quality[=(auto|yes|no)] [no]
Highest quality but lower speed
--source auto|Flatbed|Transparency Adapter [Flatbed]
Selects the scan source (such as a document-feeder).
Geometry:
-l auto|0..216mm [0]
Top-left x position of scan area.
-t auto|0..297mm [0]
Top-left y position of scan area.
-x auto|0..216mm [216]
Width of scan-area.
-y auto|0..297mm [297]
Height of scan-area.
--predef-window None|6x4 (inch)|8x10 (inch)|8.5x11 (inch) [None]
Provides standard scanning areas for photographs, printed pages and
the like.
Enhancement:
--depth 8|16bit [8]
Number of bits per sample, typical values are 1 for "line-art" and 8
for multibit scans.
--quality-cal[=(yes|no)] [yes]
Do a quality white-calibration
--halftoning[=(yes|no)] [inactive]
Selects whether the acquired image should be halftoned (dithered).
--halftone-pattern DispersedDot8x8|DispersedDot16x16 [inactive]
Defines the halftoning (dithering) pattern for scanning halftoned
images.
--custom-gamma[=(yes|no)] [no]
Determines whether a builtin or a custom gamma-table should be used.
--analog-gamma-bind[=(yes|no)] [no]
In RGB-mode use same values for each color
--analog-gamma 0..4 [inactive]
Analog gamma-correction
--analog-gamma-r 0..4 [1.79999]
Analog gamma-correction for red
--analog-gamma-g 0..4 [1.79999]
Analog gamma-correction for green
--analog-gamma-b 0..4 [1.79999]
Analog gamma-correction for blue
--gamma-table 0..65535,... (in steps of 1) [inactive]
Gamma-correction table. In color mode this option equally affects the
red, green, and blue channels simultaneously (i.e., it is an intensity
gamma table).
--red-gamma-table 0..65535,... (in steps of 1) [inactive]
Gamma-correction table for the red band.
--green-gamma-table 0..65535,... (in steps of 1) [inactive]
Gamma-correction table for the green band.
--blue-gamma-table 0..65535,... (in steps of 1) [inactive]
Gamma-correction table for the blue band.
--negative[=(auto|yes|no)] [inactive]
Swap black and white
--threshold 0..100% (in steps of 1) [50]
Select minimum-brightness to get a white point
--brightness -400..400% (in steps of 1) [inactive]
Controls the brightness of the acquired image.
--contrast -100..400% (in steps of 1) [inactive]
Controls the contrast of the acquired image.
Advanced:
--rgb-lpr auto|1..50 (in steps of 1) [4]
Number of scan lines to request in a SCSI read. Changing this
parameter allows you to tune the speed at which data is read from the
scanner during scans. If this is set too low, the scanner will have to
stop periodically in the middle of a scan; if it's set too high,
X-based frontends may stop responding to X events and your system could
bog down.
--gs-lpr auto|1..50 (in steps of 1) [inactive]
Number of scan lines to request in a SCSI read. Changing this
parameter allows you to tune the speed at which data is read from the
scanner during scans. If this is set too low, the scanner will have to
stop periodically in the middle of a scan; if it's set too high,
X-based frontends may stop responding to X events and your system could
bog down.
Type ``scanimage --help -d DEVICE'' to get list of all options for DEVICE.
List of available devices:
snapscan:libusb:005:007
gscan2pdf-1.2.3/scanners/hp_scanjet6390c.scanadf 0000644 0001750 0001750 00000007172 12053230657 017744 0 ustar jeff jeff Usage: scanadf [OPTION]...
Start image acquisition on a scanner device and write image data to
output files.
[ -d | --device-name ] use a given scanner device.
[ -h | --help ] display this help message and exit.
[ -L | --list-devices ] show available scanner devices.
[ -v | --verbose ] give even more status messages.
[ -V | --version ] print version information.
[ -N | --no-overwrite ] don't overwrite existing files.
[ -o | --output-file ] name of file to write image data
(%d replacement in output file name).
[ -S | --scan-script ] name of script to run after every scan.
[ --script-wait ] wait for scripts to finish before exit
[ -s | --start-count ] page count of first scanned image.
[ -e | --end-count ] last page number to scan.
[ -r | --raw ] write raw image data to file.
Options specific to device `hp:libusb:001:003':
Scan Mode:
--preview[=(yes|no)] [no]
Request a preview-quality scan.
--mode Lineart|Halftone|Grayscale|Color [Lineart]
Selects the scan mode (e.g., lineart, monochrome, or color).
--resolution 12..3200dpi (in steps of 1) [300]
Sets the resolution of the scanned image.
Enhancement:
--brightness -127..127 (in steps of 1) [0]
Controls the brightness of the acquired image.
--contrast -127..127 (in steps of 1) [0]
Controls the contrast of the acquired image.
--auto-threshold[=(yes|no)] [no]
Enable automatic determination of threshold for line-art scans.
Advanced Options:
--custom-gamma[=(yes|no)] [no]
Determines whether a builtin or a custom gamma-table should be used.
--gamma-table 0..255,... (in steps of 1.52588e-05) [inactive]
Gamma-correction table. In color mode this option equally affects the
red, green, and blue channels simultaneously (i.e., it is an intensity
gamma table).
--matrix-type Auto|NTSC Gray|Red|Green|Blue [Auto]
Set the scanners color matrix.
--matrix-rgb -3.99219..3.99219,... (in steps of 1.52588e-05) [inactive]
Custom color matrix.
--halftone-pattern Coarse|Fine|Bayer|Vertical|Horizontal|Custom [inactive]
Defines the halftoning (dithering) pattern for scanning halftoned
images.
--speed Auto|Slow|Normal|Fast|Extra Fast [Auto]
Determines the speed at which the scan proceeds.
--depth 1 [inactive]
Number of bits per sample, typical values are 1 for "line-art" and 8
for multibit scans.
--output-8bit[=(yes|no)] [inactive]
Use bit depth greater eight internally, but output only eight bits.
--source Normal|ADF|XPA [Normal]
Selects the scan source (such as a document-feeder).
--button-wait[=(yes|no)] [no]
Wait to scan for front-panel button push.
--lamp-off
Shut off scanner lamp.
--change-document
Change Document.
Geometry:
-l 0..215.788mm (in steps of 1.52588e-05) [0]
Top-left x position of scan area.
-t 0..296.888mm (in steps of 1.52588e-05) [0]
Top-left y position of scan area.
-x 0..215.788mm (in steps of 1.52588e-05) [215.788]
Width of scan-area.
-y 0..296.888mm (in steps of 1.52588e-05) [296.888]
Height of scan-area.
--mirror-horizontal Off|On [Off]
Mirror image horizontally.
--mirror-vertical Off|On [Off]
Mirror image vertically.
Type ``scanadf --help -d DEVICE'' to get list of all options for DEVICE.
List of available devices:
hp:libusb:001:003
gscan2pdf-1.2.3/scanners/hpangua 0000644 0001750 0001750 00000010220 12053230657 015152 0 ustar jeff jeff Usage: scanimage [OPTION]...
Start image acquisition on a scanner device and write PNM image data to standard output.
-d, --device-name=DEVICE use a given scanner device (e.g. hp:/dev/scanner)
--format=pnm|tiff file format of output file
-i, --icc-profile=PROFILE include this ICC profile into TIFF file
-L, --list-devices show available scanner devices
-f, --formatted-device-list=FORMAT similar to -L, but the FORMAT of the output
can be specified: %d (device name), %v (vendor),
%m (model), %t (type), and %i (index number)
-b, --batch[=FORMAT] working in batch mode, FORMAT is `out%d.pnm' or
`out%d.tif' by default depending on --format
--batch-start=# page number to start naming files with
--batch-count=# how many pages to scan in batch mode
--batch-increment=# increase number in filename by an amount of #
--batch-double increment page number by two for 2sided originals
being scanned in a single sided scanner
--batch-prompt ask for pressing a key before scanning a page
--accept-md5-only only accept authorization requests using md5
-n, --dont-scan only set options, don't actually scan
-T, --test test backend thoroughly
-h, --help display this help message and exit
-v, --verbose give even more status messages
-V, --version print version information
Options specific to device `net:angua:hp:/dev/scanner':
Scan Mode:
--preview[=(yes|no)] [no]
Request a preview-quality scan.
--mode Lineart|Halftone|Grayscale|Color [Lineart]
Selects the scan mode (e.g., lineart, monochrome, or color).
--resolution 12..3200dpi (in steps of 1) [300]
Sets the resolution of the scanned image.
Enhancement:
--brightness -127..127 (in steps of 1) [0]
Controls the brightness of the acquired image.
--contrast -127..127 (in steps of 1) [0]
Controls the contrast of the acquired image.
--auto-threshold[=(yes|no)] [no]
Enable automatic determination of threshold for line-art scans.
Advanced Options:
--custom-gamma[=(yes|no)] [no]
Determines whether a builtin or a custom gamma-table should be used.
--gamma-table 0..255,... (in steps of 1.52588e-05) [inactive]
Gamma-correction table. In color mode this option equally affects the
red, green, and blue channels simultaneously (i.e., it is an intensity
gamma table).
--matrix-type Auto|NTSC Gray|Red|Green|Blue [Auto]
Set the scanners color matrix.
--matrix-rgb -3.99219..3.99219,... (in steps of 1.52588e-05) [inactive]
Custom color matrix.
--halftone-pattern Coarse|Fine|Bayer|Vertical|Horizontal|Custom [inactive]
Defines the halftoning (dithering) pattern for scanning halftoned
images.
--speed Auto|Slow|Normal|Fast|Extra Fast [Auto]
Determines the speed at which the scan proceeds.
--depth 1 [inactive]
Number of bits per sample, typical values are 1 for "line-art" and 8
for multibit scans.
--output-8bit[=(yes|no)] [inactive]
Use bit depth greater eight internally, but output only eight bits.
--source Normal|ADF|XPA [Normal]
Selects the scan source (such as a document-feeder).
--button-wait[=(yes|no)] [no]
Wait to scan for front-panel button push.
--lamp-off []
Shut off scanner lamp.
--change-document []
Change Document.
Geometry:
-l 0..215.788mm (in steps of 1.52588e-05) [0]
Top-left x position of scan area.
-t 0..296.888mm (in steps of 1.52588e-05) [0]
Top-left y position of scan area.
-x 0..215.788mm (in steps of 1.52588e-05) [215.788]
Width of scan-area.
-y 0..296.888mm (in steps of 1.52588e-05) [296.888]
Height of scan-area.
--mirror-horizontal Off|On [Off]
Mirror image horizontally.
--mirror-vertical Off|On [Off]
Mirror image vertically.
Type ``scanimage --help -d DEVICE'' to get list of all options for DEVICE.
List of available devices:
net:angua:hp:/dev/scanner
gscan2pdf-1.2.3/scanners/FujitsuS510 0000644 0001750 0001750 00000010551 12053230657 015540 0 ustar jeff jeff Usage: scanimage [OPTION]...
Start image acquisition on a scanner device and write PNM image data to
standard output.
Parameters are separated by a blank from single-character options (e.g.
-d epson) and by a "=" from multi-character options (e.g. --device-name=epson).
-d, --device-name=DEVICE use a given scanner device (e.g. hp:/dev/scanner)
--format=pnm|tiff file format of output file
-i, --icc-profile=PROFILE include this ICC profile into TIFF file
-L, --list-devices show available scanner devices
-f, --formatted-device-list=FORMAT similar to -L, but the FORMAT of the output
can be specified: %d (device name), %v (vendor),
%m (model), %t (type), and %i (index number)
-b, --batch[=FORMAT] working in batch mode, FORMAT is `out%d.pnm' or
`out%d.tif' by default depending on --format
--batch-start=# page number to start naming files with
--batch-count=# how many pages to scan in batch mode
--batch-increment=# increase number in filename by an amount of #
--batch-double increment page number by two for 2sided originals
being scanned in a single sided scanner
--batch-prompt ask for pressing a key before scanning a page
--accept-md5-only only accept authorization requests using md5
-p, --progress print progress messages
-n, --dont-scan only set options, don't actually scan
-T, --test test backend thoroughly
-h, --help display this help message and exit
-v, --verbose give even more status messages
-B, --buffer-size change default input buffersize
-V, --version print version information
Options specific to device `fujitsu:libusb:007:032':
Scan Mode:
--source ADF Front|ADF Back|ADF Duplex [ADF Front]
Selects the scan source (such as a document-feeder).
--mode Lineart|Halftone|Gray|Color [Lineart]
Selects the scan mode (e.g., lineart, monochrome, or color).
--resolution 50..600dpi (in steps of 1) [600]
Sets the horizontal resolution of the scanned image.
--y-resolution 50..600dpi (in steps of 1) [600]
Sets the vertical resolution of the scanned image.
Geometry:
-l 0..215.872mm (in steps of 0.0211639) [0]
Top-left x position of scan area.
-t 0..279.364mm (in steps of 0.0211639) [0]
Top-left y position of scan area.
-x 0..215.872mm (in steps of 0.0211639) [215.872]
Width of scan-area.
-y 0..279.364mm (in steps of 0.0211639) [279.364]
Height of scan-area.
--pagewidth 0..221.121mm (in steps of 0.0211639) [215.872]
Must be set properly to align scanning window
--pageheight 0..863.489mm (in steps of 0.0211639) [279.364]
Must be set properly to eject pages
Enhancement:
--brightness -127..127 (in steps of 1) [0]
Controls the brightness of the acquired image.
--contrast -127..127 (in steps of 1) [0]
Controls the contrast of the acquired image.
--threshold 0..255 (in steps of 1) [0]
Select minimum-brightness to get a white point
--rif[=(yes|no)] [no]
Reverse image format
Advanced:
--compression None|JPEG [None]
Enable compressed data. May crash your front-end program
--compression-arg 0..7 (in steps of 1) [0]
Level of JPEG compression. 1 is small file, 7 is large file. 0
(default) is same as 4
--dfdetect Default|None|Thickness|Length|Both [Default]
Enable double feed sensors
--dfdiff Default|10mm|15mm|20mm [Default]
Difference in page length to trigger double feed sensor
--dropoutcolor Default|Red|Green|Blue [Default]
One-pass scanners use only one color during gray or binary scanning,
useful for colored paper or ink
--overscan Default|Off|On [Default]
Collect a few mm of background on top side of scan, before paper
enters ADF, and increase maximum scan area beyond paper size, to allow
collection on remaining sides. May conflict with bgcolor option
--sleeptimer 0..60 (in steps of 1) [0]
Time in minutes until the internal power supply switches to sleep mode
Sensors and Buttons:
Type ``scanimage --help -d DEVICE'' to get list of all options for DEVICE.
List of available devices:
v4l:/dev/video0 fujitsu:libusb:007:032
gscan2pdf-1.2.3/scanners/hp_6200 0000644 0001750 0001750 00000007447 12053230657 014626 0 ustar jeff jeff Usage: scanimage [OPTION]...
Start image acquisition on a scanner device and write PNM image data to
standard output.
-d, --device-name=DEVICE use a given scanner device (e.g. hp:/dev/scanner)
--format=pnm|tiff file format of output file
-i, --icc-profile=PROFILE include this ICC profile into TIFF file
-L, --list-devices show available scanner devices
-f, --formatted-device-list=FORMAT similar to -L, but the FORMAT of the output
can be specified: %d (device name), %v (vendor),
%m (model), %t (type), and %i (index number)
-b, --batch[=FORMAT] working in batch mode, FORMAT is `out%d.pnm' or
`out%d.tif' by default depending on --format
--batch-start=# page number to start naming files with
--batch-count=# how many pages to scan in batch mode
--batch-increment=# increase number in filename by an amount of #
--batch-double increment page number by two for 2sided originals
being scanned in a single sided scanner
--batch-prompt ask for pressing a key before scanning a page
--accept-md5-only only accept authorization requests using md5
-p, --progress print progress messages
-n, --dont-scan only set options, don't actually scan
-T, --test test backend thoroughly
-h, --help display this help message and exit
-v, --verbose give even more status messages
-B, --buffer-size change default input buffersize
-V, --version print version information
Options specific to device `hpaio:/usb/Officejet_6200_series?serial=CN4AKCE1ZY0453':
Scan mode:
--mode Lineart|Grayscale|Color [Color]
Selects the scan mode (e.g., lineart, monochrome, or color).
--resolution 75..600dpi [75]
Sets the resolution of the scanned image.
Advanced:
--contrast 0..100 [inactive]
Controls the contrast of the acquired image.
--compression None|JPEG [JPEG]
Selects the scanner compression method for faster scans, possibly at
the expense of image quality.
--jpeg-compression-factor 0..100 [10]
Sets the scanner JPEG compression factor. Larger numbers mean better
compression, and smaller numbers mean better image quality.
--batch-scan[=(yes|no)] [no]
Guarantees that a "no documents" condition will be returned after the
last scanned page, to prevent endless flatbed scans after a batch scan.
For some models, option changes in the middle of a batch scan don't
take effect until after the last page.
--source Auto|Flatbed|ADF [Auto]
Selects the desired scan source for models with both flatbed and
automatic document feeder (ADF) capabilities. The "Auto" setting means
that the ADF will be used if it's loaded, and the flatbed (if present)
will be used otherwise.
--duplex[=(yes|no)] [no]
Enables scanning on both sides of the page for models with
duplex-capable document feeders. For pages printed in "book"-style
duplex mode, one side will be scanned upside-down. This feature is
experimental.
Geometry:
--length-measurement Unknown|Approximate|Padded [Padded]
Selects how the scanned image length is measured and reported, which
is impossible to know in advance for scrollfed scans.
-l 0..215.9mm [0]
Top-left x position of scan area.
-t 0..381mm [0]
Top-left y position of scan area.
-x 0..215.9mm [215.9]
Width of scan-area.
-y 0..381mm [381]
Height of scan-area.
Type ``scanimage --help -d DEVICE'' to get list of all options for DEVICE.
List of available devices:
hpaio:/usb/Officejet_6200_series?serial=CN4AKCE1ZY0453 v4l:/dev/video0
gscan2pdf-1.2.3/scanners/hp3900 0000644 0001750 0001750 00000004421 12053230657 014460 0 ustar jeff jeff Usage: scanadf [OPTION]...
Start image acquisition on a scanner device and write image data to
output files.
[ -d | --device-name ] use a given scanner device.
[ -h | --help ] display this help message and exit.
[ -L | --list-devices ] show available scanner devices.
[ -v | --verbose ] give even more status messages.
[ -V | --version ] print version information.
[ -N | --no-overwrite ] don't overwrite existing files.
[ -o | --output-file ] name of file to write image data
(%d replacement in output file name).
[ -S | --scan-script ] name of script to run after every scan.
[ --script-wait ] wait for scripts to finish before exit
[ -s | --start-count ] page count of first scanned image.
[ -e | --end-count ] last page number to scan.
[ -r | --raw ] write raw image data to file.
Options specific to device `hp3900:libusb:005:002':
-l 0..220mm (in steps of 1) [220]
Top-left x position of scan area.
-t 0..300mm (in steps of 1) [300]
Top-left y position of scan area.
-x 0..220mm (in steps of 1) [220]
Width of scan-area.
-y 0..300mm (in steps of 1) [300]
Height of scan-area.
--resolution 75|100|150|200|300|600|1200|2400dpi [75]
Sets the resolution of the scanned image.
--red-gamma-table 0..65535,... [0]
Gamma-correction table for the red band.
--green-gamma-table 0..65535,... [0]
Gamma-correction table for the green band.
--blue-gamma-table 0..65535,... [0]
Gamma-correction table for the blue band.
--source Flatbed|Slide|Negative [Flatbed]
Selects the scan source (such as a document-feeder).
--mode Color|Gray|Lineart [Gray]
Selects the scan mode (e.g., lineart, monochrome, or color).
--depth 8|16bit [8]
Number of bits per sample, typical values are 1 for "line-art" and 8
for multibit scans.
--threshold 0..255 [inactive]
Select minimum-brightness to get a white point
Type ``scanadf --help -d DEVICE'' to get list of all options for DEVICE.
List of available devices:
v4l:/dev/video0 hp3900:libusb:005:002
gscan2pdf-1.2.3/scanners/Epson_GT-2500 0000644 0001750 0001750 00000013532 12053230657 015602 0 ustar jeff jeff Usage: scanimage [OPTION]...
Start image acquisition on a scanner device and write PNM image data to
standard output.
Parameters are separated by a blank from single-character options (e.g.
-d epson) and by a "=" from multi-character options (e.g. --device-name=epson).
-d, --device-name=DEVICE use a given scanner device (e.g. hp:/dev/scanner)
--format=pnm|tiff file format of output file
-i, --icc-profile=PROFILE include this ICC profile into TIFF file
-L, --list-devices show available scanner devices
-f, --formatted-device-list=FORMAT similar to -L, but the FORMAT of the output
can be specified: %d (device name), %v (vendor),
%m (model), %t (type), and %i (index number)
-b, --batch[=FORMAT] working in batch mode, FORMAT is `out%d.pnm' or
`out%d.tif' by default depending on --format
--batch-start=# page number to start naming files with
--batch-count=# how many pages to scan in batch mode
--batch-increment=# increase number in filename by an amount of #
--batch-double increment page number by two for 2sided originals
being scanned in a single sided scanner
--batch-prompt ask for pressing a key before scanning a page
--accept-md5-only only accept authorization requests using md5
-p, --progress print progress messages
-n, --dont-scan only set options, don't actually scan
-T, --test test backend thoroughly
-h, --help display this help message and exit
-v, --verbose give even more status messages
-B, --buffer-size change default input buffersize
-V, --version print version information
Options specific to device `epkowa:libusb:006:011':
Scan Mode:
--mode Binary|Gray|Color [Binary]
Selects the scan mode (e.g., lineart,monochrome, or color).
--depth 8|16 [inactive]
Number of bits per sample, typical values are 1 for "line-art" and 8
for multibit scans.
--halftoning None|Halftone A (Hard Tone)|Halftone B (Soft Tone)|Halftone C (Net Screen)|Dither A (4x4 Bayer)|Dither B (4x4 Spiral)|Dither C (4x4 Net Screen)|Dither D (8x4 Net Screen)|Text Enhanced Technology|Download pattern A|Download pattern B [None]
Selects the halftone.
--dropout None|Red|Green|Blue [None]
Selects the dropout.
--brightness -4..3 [0]
Selects the brightness.
--sharpness -2..2 [0]
--gamma-correction Default|User defined (Gamma=1.0)|User defined (Gamma=1.8)|High density printing|Low density printing|High contrast printing [Default]
Selects the gamma correction value from a list of pre-defined devices
or the user defined table, which can be downloaded to the scanner
--color-correction No Correction|User defined|Impact-dot printers|Thermal printers|Ink-jet printers|CRT monitors [CRT monitors]
Sets the color correction table for the selected output device.
--resolution 50..2400dpi [300]
Sets the resolution of the scanned image.
--threshold 0..255 [128]
Select minimum-brightness to get a white point
Advanced:
--mirror[=(yes|no)] [no]
Mirror the image.
--speed[=(yes|no)] [no]
Determines the speed at which the scan proceeds.
--auto-area-segmentation[=(yes|no)] [no]
--short-resolution[=(yes|no)] [no]
Display short resolution list
--zoom 50..200 [100]
Defines the zoom factor the scanner will use
--red-gamma-table 0..255,... [inactive]
Gamma-correction table for the red band.
--green-gamma-table 0..255,... [inactive]
Gamma-correction table for the green band.
--blue-gamma-table 0..255,... [inactive]
Gamma-correction table for the blue band.
--wait-for-button[=(yes|no)] [no]
After sending the scan command, wait until the button on the scanner
is pressed to actually start the scan process.
--monitor-button[=(yes|no)] [no]
Indicates whether a button on the scanner has been pressed (read-only
option).
Color correction coefficients:
--cct-1 -2..2 [inactive]
Controls red level
--cct-2 -2..2 [inactive]
Adds to red based on green level
--cct-3 -2..2 [inactive]
Adds to red based on blue level
--cct-4 -2..2 [inactive]
Adds to green based on red level
--cct-5 -2..2 [inactive]
Controls green level
--cct-6 -2..2 [inactive]
Adds to green based on blue level
--cct-7 -2..2 [inactive]
Adds to blue based on red level
--cct-8 -2..2 [inactive]
Adds to blue based on green level
--cct-9 -2..2 [inactive]
Control blue level
Preview:
--preview[=(yes|no)] [no]
Request a preview-quality scan.
--preview-speed[=(yes|no)] [no]
Geometry:
-l 0..215.9mm [0]
Top-left x position of scan area.
-t 0..297.18mm [0]
Top-left y position of scan area.
-x 0..215.9mm [215.9]
Width of scan-area.
-y 0..297.18mm [297.18]
Height of scan-area.
--quick-format CD|A5 portrait|A5 landscape|Letter|A4|Max [Max]
Optional equipment:
--source Flatbed|Automatic Document Feeder [Flatbed]
Selects the scan source (such as a document-feeder).
--auto-eject[=(yes|no)] [yes]
Eject document after scanning
--film-type Positive Film|Negative Film [inactive]
--focus-position Focus on glass|Focus 2.5mm above glass [inactive]
Sets the focus position to either the glass or 2.5mm above the glass
--bay 1 | 2 | 3 | 4 | 5 | 6 [inactive]
Select bay to scan
--eject []
Eject the sheet in the ADF
--adf_mode Simplex|Duplex [Simplex]
Selects the ADF mode (simplex/duplex)
Type ``scanimage --help -d DEVICE'' to get list of all options for DEVICE.
List of available devices:
epkowa:libusb:006:011
gscan2pdf-1.2.3/COPYING 0000644 0001750 0001750 00000002022 12053230657 013024 0 ustar jeff jeff Copyright (C) 2006 -- 2011 Jeffrey Ratcliffe
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 3 as published by
the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
The scanner icon was taken from
http://quantum-bits.org/wp-content/uploads/2007/05/epson-perfection-1260.tar.gz
and is equally GPL.
The PDF icon was taken from
http://upload.wikimedia.org/wikipedia/commons/b/b6/Gnome-mime-application-pdf.svg
and is LGPL.
I created the gscan2pdf icon by combining the above two icons.
gscan2pdf-1.2.3/pdf.svg 0000644 0001750 0001750 00000103545 12053230657 013277 0 ustar jeff jeff
gscan2pdf-1.2.3/LICENCE 0000644 0001750 0001750 00000104513 12053230657 012766 0 ustar jeff jeff GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc.
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
Copyright (C)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
Copyright (C)
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
.
gscan2pdf-1.2.3/t/ 0000755 0001750 0001750 00000000000 12271546566 012253 5 ustar jeff jeff gscan2pdf-1.2.3/t/165_import_with_spaces.t 0000644 0001750 0001750 00000001342 12270574026 016725 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 1;
BEGIN {
use Gscan2pdf::Document;
use Gtk2 -init; # Could just call init separately
}
#########################
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Document->setup($logger);
# Create test image
system('convert rose: test.pnm; c44 test.pnm te\ st.djvu');
my $slist = Gscan2pdf::Document->new;
$slist->get_file_info(
path => 'te st.djvu',
finished_callback => sub {
my ($info) = @_;
is( $info->{format}, 'DJVU', 'DjVu with spaces recognised correctly' );
Gtk2->main_quit;
}
);
Gtk2->main;
#########################
unlink 'test.pnm', 'te st.djvu';
Gscan2pdf::Document->quit();
gscan2pdf-1.2.3/t/90_MANIFEST.t 0000644 0001750 0001750 00000000545 12053230657 014147 0 ustar jeff jeff use strict;
use warnings;
use Test::More;
my $git;
if ( -d '.git'
and
eval { $git = `git ls-tree --name-status -r HEAD | egrep -v '^\.(git|be)'` } )
{
plan( tests => 1 );
}
else {
my $msg = 'Need the git repository to compare the MANIFEST.';
plan( skip_all => $msg );
}
my $manifest = `cat MANIFEST`;
ok( $git eq $manifest, 'MANIFEST up to date' );
gscan2pdf-1.2.3/t/14_save_image.t 0000644 0001750 0001750 00000002071 12053230657 015031 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 2;
BEGIN {
use_ok('Gscan2pdf::Document');
use Gtk2 -init; # Could just call init separately
}
#########################
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Document->setup($logger);
# Create test image
system('convert rose: test.pnm');
my $slist = Gscan2pdf::Document->new;
# dir for temporary files
my $dir = File::Temp->newdir;
$slist->set_dir($dir);
$slist->get_file_info(
path => 'test.pnm',
finished_callback => sub {
my ($info) = @_;
$slist->import_file(
info => $info,
first => 1,
last => 1,
finished_callback => sub {
$slist->save_image(
path => 'test.jpg',
list_of_pages => [ $slist->{data}[0][2] ],
finished_callback => sub { Gtk2->main_quit }
);
}
);
}
);
Gtk2->main;
is( system('identify test.jpg'), 0, 'valid JPG created' );
#########################
unlink 'test.pnm', 'test.jpg';
Gscan2pdf::Document->quit();
gscan2pdf-1.2.3/t/02_Scanner_Options_canonLiDE25.t 0000644 0001750 0001750 00000037317 12271200642 020061 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 3;
use Sane 0.05; # For enums
BEGIN { use_ok('Gscan2pdf::Scanner::Options') }
#########################
my $filename = 'scanners/canonLiDE25';
my $output = do { local ( @ARGV, $/ ) = $filename; <> };
my $options = Gscan2pdf::Scanner::Options->new_from_data($output);
my @that = (
{
'index' => 0,
},
{
index => 1,
title => 'Scan Mode',
type => SANE_TYPE_GROUP,
'cap' => 0,
'max_values' => 0,
'name' => '',
'unit' => SANE_UNIT_NONE,
'desc' => '',
type => SANE_TYPE_GROUP,
'constraint_type' => SANE_CONSTRAINT_NONE
},
{
name => 'mode',
title => 'Mode',
index => 2,
'desc' => 'Selects the scan mode (e.g., lineart, monochrome, or color).',
'val' => 'Color',
'constraint' => [ 'Lineart', 'Gray', 'Color' ],
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_STRING_LIST,
type => SANE_TYPE_STRING,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'depth',
title => 'Depth',
index => 3,
'desc' =>
'Number of bits per sample, typical values are 1 for "line-art" and 8 for multibit scans.',
'val' => '8',
'constraint' => [ '8', '16' ],
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_WORD_LIST,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'source',
title => 'Source',
index => 4,
'desc' => 'Selects the scan source (such as a document-feeder).',
'constraint' => [ 'Normal', 'Transparency', 'Negative' ],
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_STRING_LIST,
type => SANE_TYPE_STRING,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
'max_values' => 1,
},
{
name => 'resolution',
title => 'Resolution',
index => 5,
'desc' => 'Sets the resolution of the scanned image.',
'val' => '50',
constraint => {
'min' => 50,
'max' => 2400,
},
'unit' => SANE_UNIT_DPI,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'preview',
title => 'Preview',
index => 6,
'desc' => 'Request a preview-quality scan.',
'val' => SANE_FALSE,
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_NONE,
type => SANE_TYPE_BOOL,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
index => 7,
title => 'Geometry',
'cap' => 0,
'max_values' => 0,
'name' => '',
'unit' => SANE_UNIT_NONE,
'desc' => '',
type => SANE_TYPE_GROUP,
'constraint_type' => SANE_CONSTRAINT_NONE
},
{
name => 'l',
title => 'Top-left x',
index => 8,
'desc' => 'Top-left x position of scan area.',
'val' => 0,
constraint => {
'min' => 0,
'max' => 215,
},
constraint_type => SANE_CONSTRAINT_RANGE,
'unit' => SANE_UNIT_MM,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 't',
title => 'Top-left y',
index => 9,
'desc' => 'Top-left y position of scan area.',
'val' => 0,
constraint => {
'min' => 0,
'max' => 297,
},
constraint_type => SANE_CONSTRAINT_RANGE,
'unit' => SANE_UNIT_MM,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'x',
title => 'Width',
index => 10,
'desc' => 'Width of scan-area.',
'val' => 103,
constraint => {
'min' => 0,
'max' => 215,
},
constraint_type => SANE_CONSTRAINT_RANGE,
'unit' => SANE_UNIT_MM,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'y',
title => 'Height',
index => 11,
'desc' => 'Height of scan-area.',
'val' => 76.21,
constraint => {
'min' => 0,
'max' => 297,
},
constraint_type => SANE_CONSTRAINT_RANGE,
'unit' => SANE_UNIT_MM,
type => SANE_TYPE_FIXED,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
index => 12,
title => 'Enhancement',
'cap' => 0,
'max_values' => 0,
'name' => '',
'unit' => SANE_UNIT_NONE,
'desc' => '',
type => SANE_TYPE_GROUP,
'constraint_type' => SANE_CONSTRAINT_NONE
},
{
name => 'brightness',
title => 'Brightness',
index => 13,
'desc' => 'Controls the brightness of the acquired image.',
'val' => '0',
constraint => {
'min' => -100,
'max' => 100,
'quant' => 1,
},
'unit' => SANE_UNIT_PERCENT,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'contrast',
title => 'Contrast',
index => 14,
'desc' => 'Controls the contrast of the acquired image.',
'val' => '0',
constraint => {
'min' => -100,
'max' => 100,
'quant' => 1,
},
'unit' => SANE_UNIT_PERCENT,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'custom-gamma',
title => 'Custom gamma',
index => 15,
'desc' =>
'Determines whether a builtin or a custom gamma-table should be used.',
'val' => SANE_FALSE,
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_NONE,
type => SANE_TYPE_BOOL,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'gamma-table',
title => 'Gamma table',
index => 16,
'desc' =>
'Gamma-correction table. In color mode this option equally affects the red, green, and blue channels simultaneously (i.e., it is an intensity gamma table).',
constraint => {
'min' => 0,
'max' => 255,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
'max_values' => 255,
},
{
name => 'red-gamma-table',
title => 'Red gamma table',
index => 17,
'desc' => 'Gamma-correction table for the red band.',
constraint => {
'min' => 0,
'max' => 255,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
'max_values' => 255,
},
{
name => 'green-gamma-table',
title => 'Green gamma table',
index => 18,
'desc' => 'Gamma-correction table for the green band.',
constraint => {
'min' => 0,
'max' => 255,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
'max_values' => 255,
},
{
name => 'blue-gamma-table',
title => 'Blue gamma table',
index => 19,
'desc' => 'Gamma-correction table for the blue band.',
constraint => {
'min' => 0,
'max' => 255,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
'max_values' => 255,
},
{
index => 20,
title => 'Device-Settings',
'cap' => 0,
'max_values' => 0,
'name' => '',
'unit' => SANE_UNIT_NONE,
'desc' => '',
type => SANE_TYPE_GROUP,
'constraint_type' => SANE_CONSTRAINT_NONE
},
{
name => 'lamp-switch',
title => 'Lamp switch',
index => 21,
'desc' => 'Manually switching the lamp(s).',
'val' => SANE_FALSE,
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_NONE,
type => SANE_TYPE_BOOL,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'lampoff-time',
title => 'Lampoff time',
index => 22,
'desc' => 'Lampoff-time in seconds.',
'val' => '300',
constraint => {
'min' => 0,
'max' => 999,
'quant' => 1,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'lamp-off-at-exit',
title => 'Lamp off at exit',
index => 23,
'desc' => 'Turn off lamp when program exits',
'val' => SANE_TRUE,
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_NONE,
type => SANE_TYPE_BOOL,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'warmup-time',
title => 'Warmup time',
index => 24,
'desc' => 'Warmup-time in seconds.',
constraint => {
'min' => -1,
'max' => 999,
'quant' => 1,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
'max_values' => 1,
},
{
name => 'calibration-cache',
title => 'Calibration cache',
index => 25,
'desc' => 'Enables or disables calibration data cache.',
'val' => SANE_FALSE,
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_NONE,
type => SANE_TYPE_BOOL,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'speedup-switch',
title => 'Speedup switch',
index => 26,
'desc' => 'Enables or disables speeding up sensor movement.',
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_NONE,
type => SANE_TYPE_BOOL,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
'max_values' => 1,
},
{
name => 'calibrate',
title => 'Calibrate',
index => 27,
'desc' => 'Performs calibration',
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_NONE,
type => SANE_TYPE_BUTTON,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
'max_values' => 0,
},
{
index => 28,
title => 'Analog frontend',
'cap' => 0,
'max_values' => 0,
'name' => '',
'unit' => SANE_UNIT_NONE,
'desc' => '',
type => SANE_TYPE_GROUP,
'constraint_type' => SANE_CONSTRAINT_NONE
},
{
name => 'red-gain',
title => 'Red gain',
index => 29,
'desc' => 'Red gain value of the AFE',
'val' => '-1',
constraint => {
'min' => -1,
'max' => 63,
'quant' => 1,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'green-gain',
title => 'Green gain',
index => 30,
'desc' => 'Green gain value of the AFE',
'val' => '-1',
constraint => {
'min' => -1,
'max' => 63,
'quant' => 1,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'blue-gain',
title => 'Blue gain',
index => 31,
'desc' => 'Blue gain value of the AFE',
'val' => '-1',
constraint => {
'min' => -1,
'max' => 63,
'quant' => 1,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'red-offset',
title => 'Red offset',
index => 32,
'desc' => 'Red offset value of the AFE',
'val' => '-1',
constraint => {
'min' => -1,
'max' => 63,
'quant' => 1,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'green-offset',
title => 'Green offset',
index => 33,
'desc' => 'Green offset value of the AFE',
'val' => '-1',
constraint => {
'min' => -1,
'max' => 63,
'quant' => 1,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'blue-offset',
title => 'Blue offset',
index => 34,
'desc' => 'Blue offset value of the AFE',
'val' => '-1',
constraint => {
'min' => -1,
'max' => 63,
'quant' => 1,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'redlamp-off',
title => 'Redlamp off',
index => 35,
'desc' => 'Defines red lamp off parameter',
'val' => '-1',
constraint => {
'min' => -1,
'max' => 16363,
'quant' => 1,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'greenlamp-off',
title => 'Greenlamp off',
index => 36,
'desc' => 'Defines green lamp off parameter',
'val' => '-1',
constraint => {
'min' => -1,
'max' => 16363,
'quant' => 1,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'bluelamp-off',
title => 'Bluelamp off',
index => 37,
'desc' => 'Defines blue lamp off parameter',
'val' => '-1',
constraint => {
'min' => -1,
'max' => 16363,
'quant' => 1,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
index => 38,
title => 'Buttons',
'cap' => 0,
'max_values' => 0,
'name' => '',
'unit' => SANE_UNIT_NONE,
'desc' => '',
type => SANE_TYPE_GROUP,
'constraint_type' => SANE_CONSTRAINT_NONE
},
);
is_deeply( $options->{array}, \@that, 'canonLiDE25' );
is( Gscan2pdf::Scanner::Options->device,
'plustek:libusb:001:002', 'device name' );
gscan2pdf-1.2.3/t/44_cancel_rotate.t 0000644 0001750 0001750 00000002617 12270574026 015547 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 2;
BEGIN {
use Gscan2pdf::Document;
use Gtk2 -init; # Could just call init separately
}
#########################
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Document->setup($logger);
# Create test image
system('convert rose: test.jpg');
my $slist = Gscan2pdf::Document->new;
# dir for temporary files
my $dir = File::Temp->newdir;
$slist->set_dir($dir);
$slist->get_file_info(
path => 'test.jpg',
finished_callback => sub {
my ($info) = @_;
$slist->import_file(
info => $info,
first => 1,
last => 1,
finished_callback => sub {
my $pid = $slist->rotate(
angle => 90,
page => $slist->{data}[0][2],
cancelled_callback => sub {
is(
-s 'test.jpg',
-s "$slist->{data}[0][2]{filename}",
'image not rotated'
);
$slist->save_image(
path => 'test2.jpg',
list_of_pages => [ $slist->{data}[0][2] ],
finished_callback => sub { Gtk2->main_quit }
);
}
);
$slist->cancel($pid);
}
);
}
);
Gtk2->main;
is( system('identify test2.jpg'),
0, 'can create a valid JPG after cancelling previous process' );
#########################
unlink 'test.jpg', 'test2.jpg';
Gscan2pdf::Document->quit();
gscan2pdf-1.2.3/t/123_save_djvu_with_hocr.t 0000644 0001750 0001750 00000003313 12270574026 017050 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 1;
BEGIN {
use Gscan2pdf::Document;
use Gtk2 -init; # Could just call init separately
}
#########################
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Document->setup($logger);
# Create test image
system('convert rose: test.pnm');
my $slist = Gscan2pdf::Document->new;
# dir for temporary files
my $dir = File::Temp->newdir;
$slist->set_dir($dir);
$slist->get_file_info(
path => 'test.pnm',
finished_callback => sub {
my ($info) = @_;
$slist->import_file(
info => $info,
first => 1,
last => 1,
finished_callback => sub {
$slist->{data}[0][2]{hocr} = <OCR Output
The quick brown fox
EOS
$slist->save_djvu(
path => 'test.djvu',
list_of_pages => [ $slist->{data}[0][2] ],
finished_callback => sub { Gtk2->main_quit }
);
}
);
}
);
Gtk2->main;
like( `djvutxt test.djvu`, qr/The quick brown fox/, 'DjVu with expected text' );
#########################
unlink 'test.pnm', 'test.djvu';
Gscan2pdf::Document->quit();
gscan2pdf-1.2.3/t/170_import_multipage_TIFF.t 0000644 0001750 0001750 00000001515 12237446416 017215 0 ustar jeff jeff use warnings;
use strict;
use File::Temp;
use Test::More tests => 1;
BEGIN {
use Gscan2pdf::Document;
use Gtk2 -init; # Could just call init separately
}
#########################
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Document->setup($logger);
# Create test image
system('convert rose: test.tif');
system('tiffcp test.tif test.tif test2.tif');
my $slist = Gscan2pdf::Document->new;
# dir for temporary files
my $dir = File::Temp->newdir;
$slist->set_dir($dir);
$slist->get_file_info(
path => 'test2.tif',
finished_callback => sub {
my ($info) = @_;
is( $info->{pages}, 2, 'found 2 pages' );
Gtk2->main_quit;
}
);
Gtk2->main;
#########################
unlink 'test.tif', 'test2.tif', <$dir/*>;
rmdir $dir;
Gscan2pdf::Document->quit();
gscan2pdf-1.2.3/t/132_cancel_save_tiff.t 0000644 0001750 0001750 00000002470 12270574026 016272 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 1;
BEGIN {
use Gscan2pdf::Document;
use Gtk2 -init; # Could just call init separately
}
#########################
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Document->setup($logger);
# Create test image
system('convert rose: test.pnm');
my $slist = Gscan2pdf::Document->new;
# dir for temporary files
my $dir = File::Temp->newdir;
$slist->set_dir($dir);
$slist->get_file_info(
path => 'test.pnm',
finished_callback => sub {
my ($info) = @_;
$slist->import_file(
info => $info,
first => 1,
last => 1,
finished_callback => sub {
my $pid = $slist->save_tiff(
path => 'test.tif',
list_of_pages => [ $slist->{data}[0][2] ],
cancelled_callback => sub {
$slist->save_image(
path => 'test.jpg',
list_of_pages => [ $slist->{data}[0][2] ],
finished_callback => sub { Gtk2->main_quit }
);
}
);
$slist->cancel($pid);
}
);
}
);
Gtk2->main;
is( system('identify test.jpg'),
0, 'can create a valid JPG after cancelling save TIFF process' );
#########################
unlink 'test.pnm', 'test.tif', 'test.jpg';
Gscan2pdf::Document->quit();
gscan2pdf-1.2.3/t/05_Dialog.t 0000644 0001750 0001750 00000004301 12053230657 014126 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 17;
use Glib qw(TRUE FALSE); # To get TRUE and FALSE
use Gtk2 -init;
use Scalar::Util;
BEGIN {
use_ok('Gscan2pdf::Dialog');
}
#########################
my $window = Gtk2::Window->new;
ok(
my $dialog =
Gscan2pdf::Dialog->new( title => 'title', 'transient-for' => $window ),
'Created dialog'
);
isa_ok( $dialog, 'Gscan2pdf::Dialog' );
is( $dialog->get('title'), 'title', 'title' );
is( $dialog->get('transient-for'), $window, 'transient-for' );
ok( $dialog->get('hide-on-delete') == FALSE, 'default destroy' );
is( $dialog->get('border-width'), 0, 'default border width' );
ok( my $vbox = $dialog->get('vbox'), 'Get vbox' );
isa_ok( $vbox, 'Gtk2::VBox' );
is(
$vbox->get('border-width'),
$dialog->get('border-width'),
'border width applied to vbox'
);
my $border_width = 6;
$dialog->set( 'border-width', $border_width );
is( $dialog->get('border-width'), $border_width, 'set border width' );
is( $vbox->get('border-width'),
$border_width, 'new border width applied to vbox' );
$dialog = Gscan2pdf::Dialog->new;
$dialog->signal_emit( 'delete_event', undef );
Scalar::Util::weaken($dialog);
is( $dialog, undef, 'destroyed on delete_event' );
$dialog = Gscan2pdf::Dialog->new( 'hide-on-delete' => TRUE );
$dialog->signal_emit( 'delete_event', undef );
Scalar::Util::weaken($dialog);
isnt( $dialog, undef, 'hidden on delete_event' );
$dialog = Gscan2pdf::Dialog->new;
my $event = Gtk2::Gdk::Event->new('key-press');
$event->keyval( $Gtk2::Gdk::Keysyms{Escape} );
$dialog->signal_emit( 'key_press_event', $event );
Scalar::Util::weaken($dialog);
is( $dialog, undef, 'destroyed on escape' );
$dialog = Gscan2pdf::Dialog->new( 'hide-on-delete' => TRUE );
$dialog->signal_emit( 'key_press_event', $event );
Scalar::Util::weaken($dialog);
isnt( $dialog, undef, 'hidden on escape' );
$dialog = Gscan2pdf::Dialog->new;
$dialog->signal_connect_after(
key_press_event => sub {
my ( $widget, $event ) = @_;
is(
$event->keyval,
$Gtk2::Gdk::Keysyms{Delete},
'other key press events still propagate'
);
}
);
$event = Gtk2::Gdk::Event->new('key-press');
$event->keyval( $Gtk2::Gdk::Keysyms{Delete} );
$dialog->signal_emit( 'key_press_event', $event );
__END__
gscan2pdf-1.2.3/t/22_analyse_blank.t 0000644 0001750 0001750 00000002316 12053230657 015535 0 ustar jeff jeff use warnings;
use strict;
use File::Basename; # Split filename into dir, file, ext
use Test::More tests => 3;
BEGIN {
use_ok('Gscan2pdf::Document');
use Gtk2 -init; # Could just call init separately
}
#########################
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Document->setup($logger);
# Create test image
system('convert xc:white white.pnm');
my $slist = Gscan2pdf::Document->new;
# dir for temporary files
my $dir = File::Temp->newdir;
$slist->set_dir($dir);
$slist->get_file_info(
path => 'white.pnm',
finished_callback => sub {
my ($info) = @_;
$slist->import_file(
info => $info,
first => 1,
last => 1,
finished_callback => sub {
$slist->analyse(
page => $slist->{data}[0][2],
finished_callback => sub {
is( $slist->{data}[0][2]{std_dev}, 0, 'Found blank page' );
is( dirname("$slist->{data}[0][2]{filename}"),
"$dir", 'using session directory' );
Gtk2->main_quit;
}
);
}
);
}
);
Gtk2->main;
#########################
unlink 'white.pnm', <$dir/*>;
rmdir $dir;
Gscan2pdf::Document->quit();
gscan2pdf-1.2.3/t/07_Dialog_Renumber.t 0000644 0001750 0001750 00000004105 12053230657 015771 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 14;
use Glib qw(TRUE FALSE); # To get TRUE and FALSE
use Gtk2 -init;
BEGIN {
use_ok('Gscan2pdf::Dialog::Renumber');
}
#########################
Glib::set_application_name('gscan2pdf');
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Document->setup($logger);
my $window = Gtk2::Window->new;
my $slist = Gscan2pdf::Document->new;
ok(
my $dialog = Gscan2pdf::Dialog::Renumber->new(
document => $slist,
'transient-for' => $window
),
'Created dialog'
);
isa_ok( $dialog, 'Gscan2pdf::Dialog::Renumber' );
is( $dialog->get('start'), 1, 'default start for empty document' );
is( $dialog->get('increment'), 1, 'default step for empty document' );
#########################
$slist = Gscan2pdf::Document->new;
@{ $slist->{data} } = ( [ 1, undef, undef ], [ 2, undef, undef ] );
$slist->select(1);
my @selected = $slist->get_selected_indices;
is_deeply( \@selected, [1], 'selected' );
$dialog->set( 'range', 'selected' );
$dialog->set( 'document', $slist );
is( $dialog->get('start'), 2, 'start for document with start clash' );
is( $dialog->get('increment'), 1, 'step for document with start clash' );
#########################
@{ $slist->{data} } = (
[ 1, undef, undef ],
[ 3, undef, undef ],
[ 5, undef, undef ],
[ 7, undef, undef ]
);
$slist->select( 2, 3 );
@selected = $slist->get_selected_indices;
is_deeply( \@selected, [ 2, 3 ], 'selected' );
$dialog->set( 'range', 'selected' );
is( $dialog->get('start'), 4, 'start for document with start and step clash' );
is( $dialog->get('increment'),
1, 'step for document with start and step clash' );
#########################
$dialog->set( 'increment', 0 );
is( $dialog->get('start'), 4, 'start for document with negative step' );
is( $dialog->get('increment'), -2, 'step for document with negative step' );
$dialog->signal_connect(
'before-renumber' => sub {
ok( 1, 'before-renumber signal fired on renumber' );
}
);
$dialog->renumber;
#########################
Gscan2pdf::Document->quit();
__END__
gscan2pdf-1.2.3/t/02_Scanner_Options_Brother_MFC_5100c.t 0000644 0001750 0001750 00000012121 12271200642 021002 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 3;
use Sane 0.05; # For enums
BEGIN { use_ok('Gscan2pdf::Scanner::Options') }
#########################
my $filename = 'scanners/Brother_MFC_5100c';
my $output = do { local ( @ARGV, $/ ) = $filename; <> };
my $options = Gscan2pdf::Scanner::Options->new_from_data($output);
my @that = (
{
'index' => 0,
},
{
title => 'Mode',
'index' => 1,
type => SANE_TYPE_GROUP,
'cap' => 0,
'max_values' => 0,
'name' => '',
'unit' => SANE_UNIT_NONE,
'desc' => '',
type => SANE_TYPE_GROUP,
'constraint_type' => SANE_CONSTRAINT_NONE
},
{
name => 'mode',
title => 'Mode',
index => 2,
'desc' => 'Select the scan mode',
'val' => '24bit Color',
'constraint' =>
[ 'Black & White', 'Gray[Error Diffusion]', 'True Gray', '24bit Color', ],
constraint_type => SANE_CONSTRAINT_STRING_LIST,
'unit' => SANE_UNIT_NONE,
type => SANE_TYPE_STRING,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'resolution',
title => 'Resolution',
index => 3,
'desc' => 'Sets the resolution of the scanned image.',
'val' => '200',
'constraint' => [
'100', '150', '200', '300', '400', '600', '1200', '2400', '4800', '9600'
],
'unit' => SANE_UNIT_DPI,
constraint_type => SANE_CONSTRAINT_WORD_LIST,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'source',
title => 'Source',
index => 4,
'desc' => 'Selects the scan source (such as a document-feeder).',
'val' => 'Automatic Document Feeder',
'constraint' => [ 'FlatBed', 'Automatic Document Feeder' ],
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_STRING_LIST,
type => SANE_TYPE_STRING,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'brightness',
title => 'Brightness',
index => 5,
'desc' => 'Controls the brightness of the acquired image.',
constraint => {
'min' => -50,
'max' => 50,
'quant' => 1,
},
'unit' => SANE_UNIT_PERCENT,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
'max_values' => 1,
},
{
name => 'contrast',
title => 'Contrast',
index => 6,
'desc' => 'Controls the contrast of the acquired image.',
constraint => {
'min' => -50,
'max' => 50,
'quant' => 1,
},
'unit' => SANE_UNIT_PERCENT,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
'max_values' => 1,
},
{
index => 7,
title => 'Geometry',
'cap' => 0,
'max_values' => 0,
'name' => '',
'unit' => SANE_UNIT_NONE,
'desc' => '',
type => SANE_TYPE_GROUP,
'constraint_type' => SANE_CONSTRAINT_NONE
},
{
name => 'l',
title => 'Top-left x',
index => 8,
'desc' => 'Top-left x position of scan area.',
'val' => 0,
constraint => {
'min' => 0,
'max' => 208,
'quant' => 0.0999908,
},
constraint_type => SANE_CONSTRAINT_RANGE,
'unit' => SANE_UNIT_MM,
type => SANE_TYPE_FIXED,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 't',
title => 'Top-left y',
index => 9,
'desc' => 'Top-left y position of scan area.',
'val' => 0,
constraint => {
'min' => 0,
'max' => 355.6,
'quant' => 0.0999908,
},
constraint_type => SANE_CONSTRAINT_RANGE,
'unit' => SANE_UNIT_MM,
type => SANE_TYPE_FIXED,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'x',
title => 'Width',
index => 10,
'desc' => 'Width of scan-area.',
'val' => 207.981,
constraint => {
'min' => 0,
'max' => 208,
'quant' => 0.0999908,
},
constraint_type => SANE_CONSTRAINT_RANGE,
'unit' => SANE_UNIT_MM,
type => SANE_TYPE_FIXED,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'y',
title => 'Height',
index => 11,
'desc' => 'Height of scan-area.',
'val' => 296.973,
constraint => {
'min' => 0,
'max' => 355.6,
'quant' => 0.0999908,
},
constraint_type => SANE_CONSTRAINT_RANGE,
'unit' => SANE_UNIT_MM,
type => SANE_TYPE_FIXED,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
}
);
is_deeply( $options->{array}, \@that, 'Brother_MFC_5100c' );
is( Gscan2pdf::Scanner::Options->device, 'brother:bus1;dev2', 'device name' );
gscan2pdf-1.2.3/t/30_tesseract_in_thread.t 0000644 0001750 0001750 00000003266 12105002475 016741 0 ustar jeff jeff use warnings;
use strict;
use File::Basename; # Split filename into dir, file, ext
use Test::More tests => 6;
BEGIN {
use Gscan2pdf::Document;
use_ok('Gscan2pdf::Tesseract');
use Gtk2 -init; # Could just call init separately
}
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Document->setup($logger);
SKIP: {
skip 'Tesseract not installed', 5 unless Gscan2pdf::Tesseract->setup($logger);
# Create test image
system(
'convert +matte -depth 1 -colorspace Gray -pointsize 12 -density 300 label:"The quick brown fox" test.png'
);
my $slist = Gscan2pdf::Document->new;
# dir for temporary files
my $dir = File::Temp->newdir;
$slist->set_dir($dir);
$slist->get_file_info(
path => 'test.png',
finished_callback => sub {
my ($info) = @_;
$slist->import_file(
info => $info,
first => 1,
last => 1,
finished_callback => sub {
$slist->tesseract(
page => $slist->{data}[0][2],
language => 'eng',
finished_callback => sub {
like( $slist->{data}[0][2]{hocr}, qr/The/, 'Tesseract returned "The"' );
like( $slist->{data}[0][2]{hocr},
qr/quick/, 'Tesseract returned "quick"' );
like( $slist->{data}[0][2]{hocr},
qr/brown/, 'Tesseract returned "brown"' );
like( $slist->{data}[0][2]{hocr}, qr/fox/, 'Tesseract returned "fox"' );
is( dirname("$slist->{data}[0][2]{filename}"),
"$dir", 'using session directory' );
Gtk2->main_quit;
}
);
}
);
}
);
Gtk2->main;
unlink 'test.png', <$dir/*>;
rmdir $dir;
}
Gscan2pdf::Document->quit();
gscan2pdf-1.2.3/t/119_save_pdf_with_non-utf8.t 0000644 0001750 0001750 00000002243 12053230657 017400 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 1;
BEGIN {
use Gscan2pdf::Document;
use Gtk2 -init; # Could just call init separately
use PDF::API2;
}
#########################
Glib::set_application_name('gscan2pdf');
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Document->setup($logger);
# Create test image
system('convert rose: test.pnm');
my $slist = Gscan2pdf::Document->new;
# dir for temporary files
my $dir = File::Temp->newdir;
$slist->set_dir($dir);
$slist->get_file_info(
path => 'test.pnm',
finished_callback => sub {
my ($info) = @_;
$slist->import_file(
info => $info,
first => 1,
last => 1,
finished_callback => sub {
$slist->{data}[0][2]{hocr} = Gscan2pdf::Document::slurp('t/non-utf8.html');
$slist->save_pdf(
path => 'test.pdf',
list_of_pages => [ $slist->{data}[0][2] ],
finished_callback => sub { Gtk2->main_quit }
);
}
);
}
);
Gtk2->main;
ok( 1, 'PDF with expected text' );
#########################
unlink 'test.pnm', 'test.pdf';
Gscan2pdf::Document->quit();
gscan2pdf-1.2.3/t/131_save_tiff.t 0000644 0001750 0001750 00000002071 12053230657 014757 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 2;
BEGIN {
use_ok('Gscan2pdf::Document');
use Gtk2 -init; # Could just call init separately
}
#########################
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Document->setup($logger);
# Create test image
system('convert rose: test.pnm');
my $slist = Gscan2pdf::Document->new;
# dir for temporary files
my $dir = File::Temp->newdir;
$slist->set_dir($dir);
$slist->get_file_info(
path => 'test.pnm',
finished_callback => sub {
my ($info) = @_;
$slist->import_file(
info => $info,
first => 1,
last => 1,
finished_callback => sub {
$slist->save_tiff(
path => 'test.tif',
list_of_pages => [ $slist->{data}[0][2] ],
finished_callback => sub { Gtk2->main_quit }
);
}
);
}
);
Gtk2->main;
is( system('identify test.tif'), 0, 'valid TIFF created' );
#########################
unlink 'test.pnm', 'test.tif';
Gscan2pdf::Document->quit();
gscan2pdf-1.2.3/t/373_user_defined.t 0000644 0001750 0001750 00000003713 12237446416 015467 0 ustar jeff jeff use warnings;
use strict;
use File::Basename; # Split filename into dir, file, ext
use Test::More tests => 5;
BEGIN {
use Gscan2pdf::Document;
use Gtk2 -init; # Could just call init separately
}
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
Gscan2pdf::Document->setup(Log::Log4perl::get_logger);
my %paper_sizes = (
A4 => {
x => 210,
y => 297,
l => 0,
t => 0,
},
'US Letter' => {
x => 216,
y => 279,
l => 0,
t => 0,
},
'US Legal' => {
x => 216,
y => 356,
l => 0,
t => 0,
},
);
# Create test image
system('convert -size 210x297 xc:white white.pnm');
my $slist = Gscan2pdf::Document->new;
# dir for temporary files
my $dir = File::Temp->newdir;
$slist->set_dir($dir);
$slist->set_paper_sizes( \%paper_sizes );
$slist->get_file_info(
path => 'white.pnm',
finished_callback => sub {
my ($info) = @_;
$slist->import_file(
info => $info,
first => 1,
last => 1,
finished_callback => sub {
is( int( abs( $slist->{data}[0][2]{resolution} - 25.4 ) ),
0, 'Resolution of imported image' );
$slist->user_defined(
page => $slist->{data}[0][2],
command => 'convert %i tmp.pbm;mv tmp.pbm %i',
finished_callback => sub {
is( int( abs( $slist->{data}[0][2]{resolution} - 25.4 ) ),
0, 'Resolution of converted image' );
my ( $dir, $base, $suffix ) =
fileparse( "$slist->{data}[0][2]{filename}", qr/\.[^.]*/ );
is( $dir, "$dir", 'using session directory' );
is( $suffix, ".pbm", 'still has an extension' );
$slist->save_pdf(
path => 'test.pdf',
list_of_pages => [ $slist->{data}[0][2] ],
finished_callback => sub { Gtk2->main_quit }
);
}
);
}
);
}
);
Gtk2->main;
like( `pdfinfo test.pdf`, qr/A4/, 'PDF is A4' );
#########################
unlink 'white.pnm', 'test.pdf', <$dir/*>;
rmdir $dir;
Gscan2pdf::Document->quit();
gscan2pdf-1.2.3/t/161_import_TIFF.t 0000644 0001750 0001750 00000002301 12053230657 015132 0 ustar jeff jeff use warnings;
use strict;
use File::Basename; # Split filename into dir, file, ext
use Test::More tests => 3;
BEGIN {
use_ok('Gscan2pdf::Document');
use Gtk2 -init; # Could just call init separately
}
#########################
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Document->setup($logger);
# Create test image
system('convert rose: test.tif');
my $old = `identify -format '%m %G %g %z-bit %r' test.tif`;
my $slist = Gscan2pdf::Document->new;
# dir for temporary files
my $dir = File::Temp->newdir;
$slist->set_dir($dir);
$slist->get_file_info(
path => 'test.tif',
finished_callback => sub {
my ($info) = @_;
$slist->import_file(
info => $info,
first => 1,
last => 1,
finished_callback => sub {
is( `identify -format '%m %G %g %z-bit %r' $slist->{data}[0][2]{filename}`,
$old, 'TIFF imported correctly' );
is( dirname("$slist->{data}[0][2]{filename}"),
"$dir", 'using session directory' );
Gtk2->main_quit;
}
);
}
);
Gtk2->main;
#########################
unlink 'test.tif', <$dir/*>;
rmdir $dir;
Gscan2pdf::Document->quit();
gscan2pdf-1.2.3/t/21_rotate.t 0000644 0001750 0001750 00000002401 12053230657 014222 0 ustar jeff jeff use warnings;
use strict;
use File::Basename; # Split filename into dir, file, ext
use Test::More tests => 3;
BEGIN {
use_ok('Gscan2pdf::Document');
use Gtk2 -init; # Could just call init separately
}
#########################
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Document->setup($logger);
# Create test image
system('convert rose: test.jpg');
my $slist = Gscan2pdf::Document->new;
# dir for temporary files
my $dir = File::Temp->newdir;
$slist->set_dir($dir);
$slist->get_file_info(
path => 'test.jpg',
finished_callback => sub {
my ($info) = @_;
$slist->import_file(
info => $info,
first => 1,
last => 1,
finished_callback => sub {
$slist->rotate(
angle => 90,
page => $slist->{data}[0][2],
finished_callback => sub {
is( system("identify $slist->{data}[0][2]{filename}"),
0, 'valid JPG created' );
is( dirname("$slist->{data}[0][2]{filename}"),
"$dir", 'using session directory' );
Gtk2->main_quit;
}
);
}
);
}
);
Gtk2->main;
#########################
unlink 'test.jpg', <$dir/*>;
rmdir $dir;
Gscan2pdf::Document->quit();
gscan2pdf-1.2.3/t/01_scan_sane.t 0000644 0001750 0001750 00000001512 12270574026 014660 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 2;
BEGIN {
use_ok('Gscan2pdf::Frontend::Sane');
use Gtk2;
}
#########################
Glib::set_application_name('gscan2pdf');
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Frontend::Sane->setup($logger);
Gscan2pdf::Frontend::Sane->open_device(
device_name => 'test',
finished_callback => sub {
Gscan2pdf::Frontend::Sane->scan_pages(
dir => '.',
format => 'out%d.pnm',
start => 1,
step => 1,
npages => 1,
finished_callback => sub {
is( -s 'out1.pnm', 30807, 'PNM created with expected size' );
Gtk2->main_quit;
}
);
}
);
Gtk2->main;
#########################
unlink 'out1.pnm';
Gscan2pdf::Frontend::Sane->quit();
gscan2pdf-1.2.3/t/28_to_png.t 0000644 0001750 0001750 00000002343 12053230657 014226 0 ustar jeff jeff use warnings;
use strict;
use File::Basename; # Split filename into dir, file, ext
use Test::More tests => 3;
BEGIN {
use_ok('Gscan2pdf::Document');
use Gtk2 -init; # Could just call init separately
}
#########################
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Document->setup($logger);
# Create test image
system('convert rose: test.pnm');
my $slist = Gscan2pdf::Document->new;
# dir for temporary files
my $dir = File::Temp->newdir;
$slist->set_dir($dir);
$slist->get_file_info(
path => 'test.pnm',
finished_callback => sub {
my ($info) = @_;
$slist->import_file(
info => $info,
first => 1,
last => 1,
finished_callback => sub {
$slist->to_png(
page => $slist->{data}[0][2],
finished_callback => sub {
is( system("identify $slist->{data}[0][2]{filename}"),
0, 'valid PNG created' );
is( dirname("$slist->{data}[0][2]{filename}"),
"$dir", 'using session directory' );
Gtk2->main_quit;
}
);
}
);
}
);
Gtk2->main;
#########################
unlink 'test.pnm', <$dir/*>;
rmdir $dir;
Gscan2pdf::Document->quit();
gscan2pdf-1.2.3/t/27_crop.t 0000644 0001750 0001750 00000002556 12053230657 013710 0 ustar jeff jeff use warnings;
use strict;
use File::Basename; # Split filename into dir, file, ext
use Test::More tests => 3;
BEGIN {
use_ok('Gscan2pdf::Document');
use Gtk2 -init; # Could just call init separately
}
#########################
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Document->setup($logger);
# Create test image
system('convert rose: test.gif');
my $slist = Gscan2pdf::Document->new;
# dir for temporary files
my $dir = File::Temp->newdir;
$slist->set_dir($dir);
$slist->get_file_info(
path => 'test.gif',
finished_callback => sub {
my ($info) = @_;
$slist->import_file(
info => $info,
first => 1,
last => 1,
finished_callback => sub {
$slist->crop(
page => $slist->{data}[0][2],
x => 10,
y => 10,
w => 10,
h => 10,
finished_callback => sub {
is( `identify -format '%g' $slist->{data}[0][2]{filename}`,
"10x10+0+0\n", 'GIF cropped correctly' );
is( dirname("$slist->{data}[0][2]{filename}"),
"$dir", 'using session directory' );
Gtk2->main_quit;
}
);
}
);
}
);
Gtk2->main;
#########################
unlink 'test.gif', <$dir/*>;
rmdir $dir;
Gscan2pdf::Document->quit();
gscan2pdf-1.2.3/t/49_cancel_to_png.t 0000644 0001750 0001750 00000002703 12270574026 015540 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 2;
BEGIN {
use Gscan2pdf::Document;
use Gtk2 -init; # Could just call init separately
}
#########################
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Document->setup($logger);
# Create test image
system('convert rose: test.pnm');
my $slist = Gscan2pdf::Document->new;
# dir for temporary files
my $dir = File::Temp->newdir;
$slist->set_dir($dir);
$slist->get_file_info(
path => 'test.pnm',
finished_callback => sub {
my ($info) = @_;
$slist->import_file(
info => $info,
first => 1,
last => 1,
finished_callback => sub {
my $md5sum = `md5sum $slist->{data}[0][2]{filename} | cut -c -32`;
my $pid = $slist->to_png(
page => $slist->{data}[0][2],
cancelled_callback => sub {
is(
$md5sum,
`md5sum $slist->{data}[0][2]{filename} | cut -c -32`,
'image not modified'
);
$slist->save_image(
path => 'test.jpg',
list_of_pages => [ $slist->{data}[0][2] ],
finished_callback => sub { Gtk2->main_quit }
);
}
);
$slist->cancel($pid);
}
);
}
);
Gtk2->main;
is( system('identify test.jpg'),
0, 'can create a valid JPG after cancelling previous process' );
#########################
unlink 'test.pnm', 'test.jpg';
Gscan2pdf::Document->quit();
gscan2pdf-1.2.3/t/24_threshold.t 0000644 0001750 0001750 00000002404 12053230657 014726 0 ustar jeff jeff use warnings;
use strict;
use File::Basename; # Split filename into dir, file, ext
use Test::More tests => 3;
BEGIN {
use_ok('Gscan2pdf::Document');
use Gtk2 -init; # Could just call init separately
}
#########################
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Document->setup($logger);
# Create test image
system('convert rose: test.jpg');
my $slist = Gscan2pdf::Document->new;
# dir for temporary files
my $dir = File::Temp->newdir;
$slist->set_dir($dir);
$slist->get_file_info(
path => 'test.jpg',
finished_callback => sub {
my ($info) = @_;
$slist->import_file(
info => $info,
first => 1,
last => 1,
finished_callback => sub {
$slist->threshold(
threshold => 80,
page => $slist->{data}[0][2],
finished_callback => sub {
is( system("identify $slist->{data}[0][2]{filename}"),
0, 'valid PNG created' );
is( dirname("$slist->{data}[0][2]{filename}"),
"$dir", 'using session directory' );
Gtk2->main_quit;
}
);
}
);
}
);
Gtk2->main;
#########################
unlink 'test.jpg', <$dir/*>;
rmdir $dir;
Gscan2pdf::Document->quit();
gscan2pdf-1.2.3/t/08_Frontend_CLI.t 0000644 0001750 0001750 00000012017 12237446454 015213 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 29;
BEGIN {
use_ok('Gscan2pdf::Frontend::CLI');
}
#########################
Glib::set_application_name('gscan2pdf');
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Frontend::CLI->setup($logger);
#########################
my $output = <<'END';
'0','test:0','Noname','frontend-tester','virtual device'
'1','test:1','Noname','frontend-tester','virtual device'
END
is_deeply(
Gscan2pdf::Frontend::CLI->parse_device_list($output),
[
{
'name' => 'test:0',
'model' => 'frontend-tester',
'type' => 'virtual device',
'vendor' => 'Noname'
},
{
'name' => 'test:1',
'model' => 'frontend-tester',
'type' => 'virtual device',
'vendor' => 'Noname'
}
],
"basic parse_device_list functionality"
);
#########################
is_deeply( Gscan2pdf::Frontend::CLI->parse_device_list(''),
[], "parse_device_list no devices" );
#########################
my $loop = Glib::MainLoop->new;
Gscan2pdf::Frontend::CLI::_watch_cmd(
cmd => 'echo hello stdout',
started_callback => sub {
ok( 1, 'started watching only stdout' );
},
out_callback => sub {
my ($output) = @_;
is( $output, "hello stdout\n", 'stdout watching only stdout' );
},
finished_callback => sub {
my ( $output, $error ) = @_;
is( $output, "hello stdout\n", 'stdout finished watching only stdout' );
is( $error, undef, 'stderr finished watching only stdout' );
$loop->quit;
}
);
$loop->run;
#########################
$loop = Glib::MainLoop->new;
Gscan2pdf::Frontend::CLI::_watch_cmd(
cmd => 'echo hello stderr 1>&2',
started_callback => sub {
ok( 1, 'started watching only stderr' );
},
err_callback => sub {
my ($output) = @_;
is( $output, "hello stderr\n", 'stderr watching only stderr' );
},
finished_callback => sub {
my ( $output, $error ) = @_;
is( $output, undef, 'stdout finished watching only stderr' );
is( $error, "hello stderr\n", 'stderr finished watching only stderr' );
$loop->quit;
}
);
$loop->run;
#########################
$loop = Glib::MainLoop->new;
Gscan2pdf::Frontend::CLI::_watch_cmd(
cmd => 'echo hello stdout; echo hello stderr 1>&2',
started_callback => sub {
ok( 1, 'started watching stdout and stderr' );
},
out_callback => sub {
my ($output) = @_;
is( $output, "hello stdout\n", 'stdout watching stdout and stderr' );
},
err_callback => sub {
my ($output) = @_;
is( $output, "hello stderr\n", 'stderr watching stdout and stderr' );
},
finished_callback => sub {
my ( $output, $error ) = @_;
is( $output, "hello stdout\n", 'stdout finished watching stdout and stderr' );
is( $error, "hello stderr\n", 'stderr finished watching stdout and stderr' );
$loop->quit;
}
);
$loop->run;
#########################
$loop = Glib::MainLoop->new;
my $cmd = 'cat scanners/*';
Gscan2pdf::Frontend::CLI::_watch_cmd(
cmd => $cmd,
started_callback => sub {
ok( 1, 'started watching large amounts of stdout' );
},
finished_callback => sub {
my ( $output, $error ) = @_;
is( length($output) . "\n",
`$cmd | wc -c`, 'stdout finished watching large amounts of stdout' );
is( $error, undef, 'stderr finished watching large amounts of stdout' );
$loop->quit;
}
);
$loop->run;
#########################
$loop = Glib::MainLoop->new;
Gscan2pdf::Frontend::CLI->find_scan_options(
device => 'test',
finished_callback => sub {
my ($options) = @_;
is( $options->by_name('source')->{name}, 'source', 'by_name' );
is( $options->by_name('button')->{name}, 'button', 'by_name' );
is( $options->by_name('mode')->{val},
'Gray', 'find_scan_options default option' );
$loop->quit;
}
);
$loop->run;
#########################
$loop = Glib::MainLoop->new;
Gscan2pdf::Frontend::CLI->find_scan_options(
device => 'test',
options => [ { mode => 'Color' } ],
finished_callback => sub {
my ($options) = @_;
is( $options->by_name('mode')->{val},
'Color', 'find_scan_options with option' );
$loop->quit;
}
);
$loop->run;
#########################
$loop = Glib::MainLoop->new;
Gscan2pdf::Frontend::CLI->scan_pages(
frontend => 'scanimage',
device => 'test',
npages => 1,
started_callback => sub {
ok( 1, 'scanimage starts' );
},
new_page_callback => sub {
my ($n) = @_;
my $path = sprintf( "out%d.pnm", $n );
ok( -e $path, 'scanimage scans' );
unlink $path;
},
finished_callback => sub {
ok( 1, 'scanimage finishes' );
$loop->quit;
},
);
$loop->run;
#########################
$loop = Glib::MainLoop->new;
Gscan2pdf::Frontend::CLI->scan_pages(
frontend => 'scanadf',
device => 'test',
npages => 1,
started_callback => sub {
ok( 1, 'scanadf starts' );
},
new_page_callback => sub {
my ($n) = @_;
my $path = sprintf( "out%d.pnm", $n );
ok( -e $path, 'scanadf scans' );
unlink $path;
},
finished_callback => sub {
ok( 1, 'scanadf finishes' );
$loop->quit;
},
);
$loop->run;
#########################
__END__
gscan2pdf-1.2.3/t/80_scanimage-perl.t 0000644 0001750 0001750 00000001666 12053230657 015634 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 3;
#########################
ok( !system('perl bin/scanimage-perl --device=test --test > /dev/null 2>&1'),
'test' );
#########################
SKIP: {
skip 'scanimage v1.0.23 not installed', 2
unless ( `scanimage --version` eq
"scanimage (sane-backends) 1.0.23; backend version 1.0.23\n" );
my $output = `perl bin/scanimage-perl --device=test --help`;
$output =~ s/scanimage-perl/scanimage/g;
my $example = `scanimage --device=test --help`;
my @output = split( "\n", $output );
my @example = split( "\n", $example );
is_deeply( \@output, \@example, "basic help functionality" );
#########################
$output = `perl bin/scanimage-perl --device=test --all`;
$output =~ s/scanimage-perl/scanimage/g;
$example = `scanimage --device=test --all`;
@output = split( "\n", $output );
@example = split( "\n", $example );
is_deeply( \@output, \@example, "all options" );
}
gscan2pdf-1.2.3/t/152_save_utf8.t 0000644 0001750 0001750 00000002300 12270574026 014715 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 1;
BEGIN {
use Gscan2pdf::Document;
use Gtk2 -init; # Could just call init separately
}
#########################
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Document->setup($logger);
# Create test image
system('convert rose: test.pnm');
my $slist = Gscan2pdf::Document->new;
# dir for temporary files
my $dir = File::Temp->newdir;
$slist->set_dir($dir);
$slist->get_file_info(
path => 'test.pnm',
finished_callback => sub {
my ($info) = @_;
$slist->import_file(
info => $info,
first => 1,
last => 1,
finished_callback => sub {
$slist->{data}[0][2]{hocr} =
'пени способствовала сохранению';
$slist->save_text(
path => 'test.txt',
list_of_pages => [ $slist->{data}[0][2] ],
finished_callback => sub { Gtk2->main_quit }
);
}
);
}
);
Gtk2->main;
is( `cat test.txt`,
'пени способствовала сохранению',
'saved UTF8' );
#########################
unlink 'test.pnm', 'test.txt';
Gscan2pdf::Document->quit();
gscan2pdf-1.2.3/t/064_Dialog_Scan_CLI.t 0000644 0001750 0001750 00000004540 12237446454 015663 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 13;
use Glib qw(TRUE FALSE); # To get TRUE and FALSE
use Gtk2 -init; # Could just call init separately
BEGIN {
use_ok('Gscan2pdf::Dialog::Scan::CLI');
}
#########################
my $window = Gtk2::Window->new;
Glib::set_application_name('gscan2pdf');
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Frontend::CLI->setup($logger);
ok(
my $dialog = Gscan2pdf::Dialog::Scan::CLI->new(
title => 'title',
'transient-for' => $window,
'logger' => $logger,
'visible-scan-options' => { mode => 1 },
),
'Created dialog'
);
isa_ok( $dialog, 'Gscan2pdf::Dialog::Scan::CLI' );
is_deeply(
$dialog->get('visible-scan-options'),
{ mode => 1 },
'initial visible-scan-options'
);
my $signal;
$signal = $dialog->signal_connect(
'changed-option-visibility' => sub {
ok( 1, 'changed-option-visibility' );
is_deeply(
$dialog->get('visible-scan-options'),
{ mode => 0 },
'updated visible-scan-options'
);
$dialog->signal_handler_disconnect($signal);
$dialog->set( 'visible-scan-options', { mode => 1 } );
is_deeply(
$dialog->get('visible-scan-options'),
{ mode => 1 },
'reset visible-scan-options'
);
}
);
$dialog->set( 'visible-scan-options', { mode => 0 } );
$dialog->signal_connect(
'changed-device-list' => sub {
ok( 1, 'changed-device-list' );
is_deeply(
$dialog->get('device-list'),
[ { 'name' => 'test', 'model' => 'test', 'label' => 'test' } ],
'add model field if missing'
);
$signal = $dialog->signal_connect(
'changed-device' => sub {
my ( $widget, $name ) = @_;
is( $name, 'test', 'changed-device' );
$dialog->signal_handler_disconnect($signal);
}
);
$dialog->set( 'device', 'test' );
}
);
$dialog->set( 'device-list', [ { 'name' => 'test' } ] );
$signal = $dialog->signal_connect(
'reloaded-scan-options' => sub {
ok( 1, 'reloaded-scan-options' );
$dialog->signal_handler_disconnect($signal);
my $options = $dialog->get('available-scan-options');
my $option = $options->by_name('mode');
is( $option->{widget}->visible, TRUE, 'mode widget visible' );
$dialog->set( 'visible-scan-options', { mode => 0 } );
is( $option->{widget}->visible, '', 'mode widget hidden by title' );
Gtk2->main_quit;
}
);
Gtk2->main;
__END__
gscan2pdf-1.2.3/t/02_Scanner_Options_epson1.t 0000644 0001750 0001750 00000050177 12271200642 017322 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 3;
use Sane 0.05; # For enums
BEGIN { use_ok('Gscan2pdf::Scanner::Options') }
#########################
my $filename = 'scanners/epson1';
my $output = do { local ( @ARGV, $/ ) = $filename; <> };
my $options = Gscan2pdf::Scanner::Options->new_from_data($output);
my @that = (
{
'index' => 0,
},
{
index => 1,
title => 'Scan Mode',
'cap' => 0,
'max_values' => 0,
'name' => '',
'unit' => SANE_UNIT_NONE,
'desc' => '',
type => SANE_TYPE_GROUP,
'constraint_type' => SANE_CONSTRAINT_NONE
},
{
name => 'mode',
title => 'Mode',
index => 2,
'desc' => 'Selects the scan mode (e.g., lineart, monochrome, or color).',
'val' => 'Binary',
'constraint' => [ 'Binary', 'Gray', 'Color' ],
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_STRING_LIST,
type => SANE_TYPE_STRING,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'depth',
title => 'Depth',
index => 3,
'desc' =>
'Number of bits per sample, typical values are 1 for "line-art" and 8 for multibit scans.',
'constraint' => [ '8', '16' ],
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_WORD_LIST,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
'max_values' => 1,
},
{
name => 'halftoning',
title => 'Halftoning',
index => 4,
'desc' => 'Selects the halftone.',
'val' => 'Halftone A (Hard Tone)',
'constraint' => [
'None',
'Halftone A (Hard Tone)',
'Halftone B (Soft Tone)',
'Halftone C (Net Screen)',
'Dither A (4x4 Bayer)',
'Dither B (4x4 Spiral)',
'Dither C (4x4 Net Screen)',
'Dither D (8x4 Net Screen)',
'Text Enhanced Technology',
'Download pattern A',
'Download pattern B'
],
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_STRING_LIST,
type => SANE_TYPE_STRING,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'dropout',
title => 'Dropout',
index => 5,
'desc' => 'Selects the dropout.',
'val' => 'None',
'constraint' => [ 'None', 'Red', 'Green', 'Blue' ],
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_STRING_LIST,
type => SANE_TYPE_STRING,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'brightness',
title => 'Brightness',
index => 6,
'desc' => 'Selects the brightness.',
'val' => '0',
constraint => {
'min' => -4,
'max' => 3,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'sharpness',
title => 'Sharpness',
index => 7,
'desc' => '',
'val' => '0',
constraint => {
'min' => -2,
'max' => 2,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'gamma-correction',
title => 'Gamma correction',
index => 8,
'desc' =>
'Selects the gamma correction value from a list of pre-defined devices or the user defined table, which can be downloaded to the scanner',
'val' => 'Default',
'constraint' => [
'Default',
'User defined',
'High density printing',
'Low density printing',
'High contrast printing'
],
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_STRING_LIST,
type => SANE_TYPE_STRING,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'color-correction',
title => 'Color correction',
index => 9,
'desc' => 'Sets the color correction table for the selected output device.',
'val' => 'CRT monitors',
'constraint' => [
'No Correction',
'User defined',
'Impact-dot printers',
'Thermal printers',
'Ink-jet printers',
'CRT monitors'
],
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_STRING_LIST,
type => SANE_TYPE_STRING,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'resolution',
title => 'Resolution',
index => 10,
'desc' => 'Sets the resolution of the scanned image.',
'val' => '50',
'constraint' => [
'50', '60', '72', '75', '80', '90', '100', '120',
'133', '144', '150', '160', '175', '180', '200', '216',
'240', '266', '300', '320', '350', '360', '400', '480',
'600', '720', '800', '900', '1200', '1600', '1800', '2400',
'3200'
],
'unit' => SANE_UNIT_DPI,
constraint_type => SANE_CONSTRAINT_WORD_LIST,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'threshold',
title => 'Threshold',
index => 11,
'desc' => 'Select minimum-brightness to get a white point',
constraint => {
'min' => 0,
'max' => 255,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
'max_values' => 1,
},
{
index => 12,
title => 'Advanced',
'cap' => 0,
'max_values' => 0,
'name' => '',
'unit' => SANE_UNIT_NONE,
'desc' => '',
type => SANE_TYPE_GROUP,
'constraint_type' => SANE_CONSTRAINT_NONE
},
{
name => 'mirror',
title => 'Mirror',
index => 13,
'desc' => 'Mirror the image.',
'val' => SANE_FALSE,
'unit' => SANE_UNIT_NONE,
'type' => SANE_TYPE_BOOL,
'constraint_type' => SANE_CONSTRAINT_NONE,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'speed',
title => 'Speed',
index => 14,
'desc' => 'Determines the speed at which the scan proceeds.',
'val' => SANE_FALSE,
'unit' => SANE_UNIT_NONE,
'type' => SANE_TYPE_BOOL,
'constraint_type' => SANE_CONSTRAINT_NONE,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'auto-area-segmentation',
title => 'Auto area segmentation',
index => 15,
'desc' => '',
'val' => SANE_TRUE,
'unit' => SANE_UNIT_NONE,
'type' => SANE_TYPE_BOOL,
'constraint_type' => SANE_CONSTRAINT_NONE,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'short-resolution',
title => 'Short resolution',
index => 16,
'desc' => 'Display short resolution list',
'val' => SANE_FALSE,
'unit' => SANE_UNIT_NONE,
'type' => SANE_TYPE_BOOL,
'constraint_type' => SANE_CONSTRAINT_NONE,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'zoom',
title => 'Zoom',
index => 17,
'desc' => 'Defines the zoom factor the scanner will use',
constraint => {
'min' => 50,
'max' => 200,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
'max_values' => 1,
},
{
name => 'red-gamma-table',
title => 'Red gamma table',
index => 18,
'desc' => 'Gamma-correction table for the red band.',
constraint => {
'min' => 0,
'max' => 255,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
'max_values' => 255,
},
{
name => 'green-gamma-table',
title => 'Green gamma table',
index => 19,
'desc' => 'Gamma-correction table for the green band.',
constraint => {
'min' => 0,
'max' => 255,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
'max_values' => 255,
},
{
name => 'blue-gamma-table',
title => 'Blue gamma table',
index => 20,
'desc' => 'Gamma-correction table for the blue band.',
constraint => {
'min' => 0,
'max' => 255,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
'max_values' => 255,
},
{
name => 'wait-for-button',
title => 'Wait for button',
index => 21,
'desc' =>
'After sending the scan command, wait until the button on the scanner is pressed to actually start the scan process.',
'val' => SANE_FALSE,
'unit' => SANE_UNIT_NONE,
'type' => SANE_TYPE_BOOL,
'constraint_type' => SANE_CONSTRAINT_NONE,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
index => 22,
title => 'Color correction coefficients',
'cap' => 0,
'max_values' => 0,
'name' => '',
'unit' => SANE_UNIT_NONE,
'desc' => '',
type => SANE_TYPE_GROUP,
'constraint_type' => SANE_CONSTRAINT_NONE
},
{
name => 'cct-1',
title => 'CCT 1',
index => 23,
'desc' => 'Controls green level',
constraint => {
'min' => -127,
'max' => 127,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
'max_values' => 1,
},
{
name => 'cct-2',
title => 'CCT 2',
index => 24,
'desc' => 'Adds to red based on green level',
constraint => {
'min' => -127,
'max' => 127,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
'max_values' => 1,
},
{
name => 'cct-3',
title => 'CCT 3',
index => 25,
'desc' => 'Adds to blue based on green level',
constraint => {
'min' => -127,
'max' => 127,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
'max_values' => 1,
},
{
name => 'cct-4',
title => 'CCT 4',
index => 26,
'desc' => 'Adds to green based on red level',
constraint => {
'min' => -127,
'max' => 127,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
'max_values' => 1,
},
{
name => 'cct-5',
title => 'CCT 5',
index => 27,
'desc' => 'Controls red level',
constraint => {
'min' => -127,
'max' => 127,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
'max_values' => 1,
},
{
name => 'cct-6',
title => 'CCT 6',
index => 28,
'desc' => 'Adds to blue based on red level',
constraint => {
'min' => -127,
'max' => 127,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
'max_values' => 1,
},
{
name => 'cct-7',
title => 'CCT 7',
index => 29,
'desc' => 'Adds to green based on blue level',
constraint => {
'min' => -127,
'max' => 127,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
'max_values' => 1,
},
{
name => 'cct-8',
title => 'CCT 8',
index => 30,
'desc' => 'Adds to red based on blue level',
constraint => {
'min' => -127,
'max' => 127,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
'max_values' => 1,
},
{
name => 'cct-9',
title => 'CCT 9',
index => 31,
'desc' => 'Controls blue level',
constraint => {
'min' => -127,
'max' => 127,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
'max_values' => 1,
},
{
index => 32,
title => 'Preview',
'cap' => 0,
'max_values' => 0,
'name' => '',
'unit' => SANE_UNIT_NONE,
'desc' => '',
type => SANE_TYPE_GROUP,
'constraint_type' => SANE_CONSTRAINT_NONE
},
{
name => 'preview',
title => 'Preview',
index => 33,
'desc' => 'Request a preview-quality scan.',
'val' => SANE_FALSE,
'unit' => SANE_UNIT_NONE,
'type' => SANE_TYPE_BOOL,
'constraint_type' => SANE_CONSTRAINT_NONE,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'preview-speed',
title => 'Preview speed',
index => 34,
'desc' => '',
'val' => SANE_FALSE,
'unit' => SANE_UNIT_NONE,
'type' => SANE_TYPE_BOOL,
'constraint_type' => SANE_CONSTRAINT_NONE,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
index => 35,
title => 'Geometry',
'cap' => 0,
'max_values' => 0,
'name' => '',
'unit' => SANE_UNIT_NONE,
'desc' => '',
type => SANE_TYPE_GROUP,
'constraint_type' => SANE_CONSTRAINT_NONE
},
{
name => 'l',
title => 'Top-left x',
index => 36,
'desc' => 'Top-left x position of scan area.',
'val' => 0,
constraint => {
'min' => 0,
'max' => 215.9,
},
'unit' => SANE_UNIT_MM,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_FIXED,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 't',
title => 'Top-left y',
index => 37,
'desc' => 'Top-left y position of scan area.',
'val' => 0,
constraint => {
'min' => 0,
'max' => 297.18,
},
'unit' => SANE_UNIT_MM,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_FIXED,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'x',
title => 'Width',
index => 38,
'desc' => 'Width of scan-area.',
'val' => 215.9,
constraint => {
'min' => 0,
'max' => 215.9,
},
'unit' => SANE_UNIT_MM,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_FIXED,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'y',
title => 'Height',
index => 39,
'desc' => 'Height of scan-area.',
'val' => 297.18,
constraint => {
'min' => 0,
'max' => 297.18,
},
'unit' => SANE_UNIT_MM,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_FIXED,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'quick-format',
title => 'Quick format',
index => 40,
'desc' => '',
'val' => 'Max',
'constraint' =>
[ 'CD', 'A5 portrait', 'A5 landscape', 'Letter', 'A4', 'Max' ],
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_STRING_LIST,
type => SANE_TYPE_STRING,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
index => 41,
title => 'Optional equipment',
'cap' => 0,
'max_values' => 0,
'name' => '',
'unit' => SANE_UNIT_NONE,
'desc' => '',
type => SANE_TYPE_GROUP,
'constraint_type' => SANE_CONSTRAINT_NONE
},
{
name => 'source',
title => 'Source',
index => 42,
'desc' => 'Selects the scan source (such as a document-feeder).',
'val' => 'Flatbed',
'constraint' => [ 'Flatbed', 'Transparency Unit' ],
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_STRING_LIST,
type => SANE_TYPE_STRING,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'auto-eject',
title => 'Auto eject',
index => 43,
'desc' => 'Eject document after scanning',
'unit' => SANE_UNIT_NONE,
'type' => SANE_TYPE_BOOL,
'constraint_type' => SANE_CONSTRAINT_NONE,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
'max_values' => 1,
},
{
name => 'film-type',
title => 'Film type',
index => 44,
'desc' => '',
'constraint' => [ 'Positive Film', 'Negative Film' ],
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_STRING_LIST,
type => SANE_TYPE_STRING,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
'max_values' => 1,
},
{
name => 'focus-position',
title => 'Focus position',
index => 45,
'desc' =>
'Sets the focus position to either the glass or 2.5mm above the glass',
'val' => 'Focus on glass',
'constraint' => [ 'Focus on glass', 'Focus 2.5mm above glass' ],
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_STRING_LIST,
type => SANE_TYPE_STRING,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'bay',
title => 'Bay',
index => 46,
'desc' => 'Select bay to scan',
'constraint' => [ ' 1 ', ' 2 ', ' 3 ', ' 4 ', ' 5 ', ' 6 ' ],
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_WORD_LIST,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
'max_values' => 1,
},
{
name => 'eject',
title => 'Eject',
index => 47,
'desc' => 'Eject the sheet in the ADF',
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_NONE,
type => SANE_TYPE_BUTTON,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
'max_values' => 0,
},
{
name => 'adf_mode',
title => 'ADF mode',
index => 48,
'desc' => 'Selects the ADF mode (simplex/duplex)',
'constraint' => [ 'Simplex', 'Duplex' ],
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_STRING_LIST,
type => SANE_TYPE_STRING,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
'max_values' => 1,
},
);
is_deeply( $options->{array}, \@that, 'epson1' );
is( Gscan2pdf::Scanner::Options->device, 'epson:libusb:005:007',
'device name' );
gscan2pdf-1.2.3/t/116_save_pdf_with_metadata.t 0000644 0001750 0001750 00000002471 12053230657 017502 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 2;
BEGIN {
use_ok('Gscan2pdf::Document');
use Gtk2 -init; # Could just call init separately
use PDF::API2;
}
#########################
# Insert your test code below, the Test::More module is use()ed here so read
# its man page ( perldoc Test::More ) for help writing this test script.
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Document->setup($logger);
# Create test image
system('convert rose: test.pnm');
my $slist = Gscan2pdf::Document->new;
# dir for temporary files
my $dir = File::Temp->newdir;
$slist->set_dir($dir);
my $metadata = { Title => 'metadata title' };
$slist->get_file_info(
path => 'test.pnm',
finished_callback => sub {
my ($info) = @_;
$slist->import_file(
info => $info,
first => 1,
last => 1,
finished_callback => sub {
$slist->save_pdf(
path => 'test.pdf',
list_of_pages => [ $slist->{data}[0][2] ],
metadata => $metadata,
finished_callback => sub { Gtk2->main_quit }
);
}
);
}
);
Gtk2->main;
like( `pdfinfo test.pdf`, qr/metadata title/, 'metadata in PDF' );
#########################
unlink 'test.pnm', 'test.pdf';
Gscan2pdf::Document->quit();
gscan2pdf-1.2.3/t/063_Dialog_Scan_CLI.t 0000644 0001750 0001750 00000030567 12270574026 015664 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 48;
use Glib qw(TRUE FALSE); # To get TRUE and FALSE
use Gtk2 -init; # Could just call init separately
use Sane 0.05; # To get SANE_* enums
BEGIN {
use_ok('Gscan2pdf::Dialog::Scan::CLI');
}
#########################
my $window = Gtk2::Window->new;
Glib::set_application_name('gscan2pdf');
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Frontend::CLI->setup($logger);
ok(
my $dialog = Gscan2pdf::Dialog::Scan::CLI->new(
title => 'title',
'transient-for' => $window,
'logger' => $logger
),
'Created dialog'
);
isa_ok( $dialog, 'Gscan2pdf::Dialog::Scan::CLI' );
is( $dialog->get('device'), '', 'device' );
is( $dialog->get('device-list'), undef, 'device-list' );
is( $dialog->get('dir'), undef, 'dir' );
is( $dialog->get('num-pages'), 1, 'num-pages' );
is( $dialog->get('max-pages'), 0, 'max-pages' );
is( $dialog->get('page-number-start'), 1, 'page-number-start' );
is( $dialog->get('page-number-increment'), 1, 'page-number-increment' );
is( $dialog->get('side-to-scan'), 'facing', 'side-to-scan' );
is( $dialog->get('available-scan-options'), undef, 'available-scan-options' );
my $signal = $dialog->signal_connect(
'changed-device-list' => sub {
ok( 1, 'changed-device-list' );
is_deeply(
$dialog->get('device-list'),
[ { 'name' => 'test', 'model' => 'test', 'label' => 'test' } ],
'add model field if missing'
);
my $signal;
$signal = $dialog->signal_connect(
'changed-device' => sub {
my ( $widget, $name ) = @_;
is( $name, 'test', 'changed-device' );
$dialog->signal_handler_disconnect($signal);
}
);
$dialog->set( 'device', 'test' );
}
);
$dialog->set( 'device-list', [ { 'name' => 'test' } ] );
my $csignal;
$csignal = $dialog->signal_connect(
'changed-num-pages' => sub {
my ( $widget, $n, $signal ) = @_;
is( $n, 0, 'changed-num-pages' );
$dialog->signal_handler_disconnect($csignal);
}
);
$dialog->set( 'num-pages', 0 );
$dialog->signal_connect(
'changed-page-number-start' => sub {
my ( $widget, $n ) = @_;
is( $n, 2, 'changed-page-number-start' );
}
);
$dialog->set( 'page-number-start', 2 );
$signal = $dialog->signal_connect(
'changed-page-number-increment' => sub {
my ( $widget, $n ) = @_;
is( $n, 2, 'changed-page-number-increment' );
$dialog->signal_handler_disconnect($signal);
}
);
$dialog->set( 'page-number-increment', 2 );
$dialog->signal_connect(
'changed-side-to-scan' => sub {
my ( $widget, $side ) = @_;
is( $side, 'reverse', 'changed-side-to-scan' );
is( $dialog->get('page-number-increment'),
-2, 'reverse side gives increment -2' );
}
);
$dialog->set( 'side-to-scan', 'reverse' );
my $reloads = 0;
$dialog->signal_connect(
'reloaded-scan-options' => sub {
++$reloads;
}
);
$signal = $dialog->signal_connect(
'reloaded-scan-options' => sub {
is( $reloads, 1, 'reloaded-scan-options' );
$dialog->signal_handler_disconnect($signal);
# So that it can be used in hash
my $resolution = SANE_NAME_SCAN_RESOLUTION;
my $brx = SANE_NAME_SCAN_BR_X;
$signal = $dialog->signal_connect(
'added-profile' => sub {
my ( $widget, $name, $profile ) = @_;
is( $name, 'my profile', 'added-profile name' );
is_deeply(
$profile,
[ { $resolution => 52 }, { mode => 'Color' } ],
'added-profile profile'
);
$dialog->signal_handler_disconnect($signal);
}
);
$dialog->add_profile( 'my profile',
[ { $resolution => 52 }, { mode => 'Color' } ] );
######################################
$signal = $dialog->signal_connect(
'added-profile' => sub {
my ( $widget, $name, $profile ) = @_;
is( $name, 'old profile', 'added-profile old name' );
is_deeply(
$profile,
[ { mode => 'Gray' }, { $resolution => 51 } ],
'added-profile profile as hash'
);
$dialog->signal_handler_disconnect($signal);
}
);
$dialog->add_profile( 'old profile', { $resolution => 51, mode => 'Gray' } );
######################################
$dialog->signal_connect(
'removed-profile' => sub {
my ( $widget, $profile ) = @_;
is( $profile, 'old profile', 'removed-profile' );
}
);
$dialog->remove_profile('old profile');
######################################
# need a new main loop because of the timeout
my $loop = Glib::MainLoop->new;
my $flag = FALSE;
$signal = $dialog->signal_connect(
'changed-profile' => sub {
my ( $widget, $profile ) = @_;
is( $profile, 'my profile', 'changed-profile' );
is_deeply(
$dialog->get('current-scan-options'),
[ { $resolution => 52 }, { mode => 'Color' } ],
'current-scan-options with profile'
);
is( $reloads, 1, 'reloaded-scan-options not called' );
$dialog->signal_handler_disconnect($signal);
$flag = TRUE;
$loop->quit;
}
);
$dialog->set( 'profile', 'my profile' );
$loop->run unless ($flag);
######################################
$dialog->add_profile( 'my profile2',
[ { $resolution => 52 }, { mode => 'Color' } ] );
# need a new main loop because of the timeout
$loop = Glib::MainLoop->new;
$flag = FALSE;
$signal = $dialog->signal_connect(
'changed-profile' => sub {
my ( $widget, $profile ) = @_;
is( $profile, 'my profile2', 'set profile with identical options' );
$dialog->signal_handler_disconnect($signal);
$flag = TRUE;
$loop->quit;
}
);
$dialog->set( 'profile', 'my profile2' );
$loop->run unless ($flag);
######################################
# need a new main loop because of the timeout
$loop = Glib::MainLoop->new;
$flag = FALSE;
$signal = $dialog->signal_connect(
'changed-scan-option' => sub {
my ( $widget, $option, $value ) = @_;
is( $dialog->get('profile'),
undef, 'changing an option deselects the current profile' );
is_deeply(
$dialog->get('current-scan-options'),
[ { mode => 'Color' }, { $resolution => 51 } ],
'current-scan-options without profile'
);
$dialog->signal_handler_disconnect($signal);
$flag = TRUE;
$loop->quit;
}
);
my $options = $dialog->get('available-scan-options');
$dialog->set_option( $options->by_name($resolution), 51 );
$loop->run unless ($flag);
my @geometry_widgets = keys %{ $options->{box} };
cmp_ok(
$#geometry_widgets == 3,
'||',
$#geometry_widgets == 5,
'Only 4 or 6 options should be flagged as geometry'
);
######################################
# need a new main loop because of the timeout
$loop = Glib::MainLoop->new;
$flag = FALSE;
# Reset profile for next test
$signal = $dialog->signal_connect(
'changed-profile' => sub {
my ( $widget, $profile ) = @_;
is( $profile, 'my profile', 'reset profile' );
$dialog->signal_handler_disconnect($signal);
$flag = TRUE;
$loop->quit;
}
);
$dialog->set( 'profile', 'my profile' );
$loop->run unless ($flag);
######################################
# need a new main loop because of the timeout
$loop = Glib::MainLoop->new;
$flag = FALSE;
$signal = $dialog->signal_connect(
'changed-profile' => sub {
my ( $widget, $profile ) = @_;
is( $profile, undef,
'changing an option fires the changed-profile signal if a profile is set'
);
is_deeply(
$dialog->get('current-scan-options'),
[ { $resolution => 52 }, { mode => 'Gray' } ],
'current-scan-options without profile (again)'
);
my $reloaded_options = $dialog->get('available-scan-options');
is( $reloaded_options->by_name($resolution)->{val},
52, 'option value updated when reloaded' );
$dialog->signal_handler_disconnect($signal);
$flag = TRUE;
$loop->quit;
}
);
$options = $dialog->get('available-scan-options');
$dialog->set_option( $options->by_name('mode'), 'Gray' );
$loop->run unless ($flag);
######################################
$dialog->set( 'reload-triggers', qw(mode) );
# need a new main loop because of the timeout
$loop = Glib::MainLoop->new;
$flag = FALSE;
$dialog->signal_connect(
'reloaded-scan-options' => sub {
is_deeply(
$dialog->get('current-scan-options'),
[ { $resolution => 52 }, { mode => 'Color' } ],
'setting a option with a reload trigger to a non-default value stays set'
);
$flag = TRUE;
$loop->quit;
}
);
$options = $dialog->get('available-scan-options');
$dialog->set_option( $options->by_name('mode'), 'Color' );
$loop->run unless ($flag);
######################################
# need a new main loop because of the timeout
$loop = Glib::MainLoop->new;
$flag = FALSE;
$signal = $dialog->signal_connect(
'changed-scan-option' => sub {
my ( $widget, $option, $value ) = @_;
is_deeply(
$dialog->get('current-scan-options'),
[ { x => 11 } ],
'map option names'
);
$dialog->signal_handler_disconnect($signal);
$flag = TRUE;
$loop->quit;
}
);
$dialog->set( 'current-scan-options', [ { $brx => 11 } ] );
$loop->run unless ($flag);
######################################
$dialog->set(
'paper-formats',
{
new => {
l => 1,
y => 50,
x => 50,
t => 2,
}
}
);
$dialog->add_profile( 'cli geometry',
[ { 'Paper size' => 'new' }, { $resolution => 50 } ] );
# need a new main loop because of the timeout
$loop = Glib::MainLoop->new;
$flag = FALSE;
$signal = $dialog->signal_connect(
'changed-profile' => sub {
my ( $widget, $profile ) = @_;
my $options = $dialog->get('available-scan-options');
my $expected = [ { 'Paper size' => 'new' } ];
push @$expected, { scalar(SANE_NAME_PAGE_HEIGHT) => 52 }
if ( defined $options->by_name(SANE_NAME_PAGE_HEIGHT) );
push @$expected, { scalar(SANE_NAME_PAGE_WIDTH) => 51 }
if ( defined $options->by_name(SANE_NAME_PAGE_WIDTH) );
push @$expected, { y => 50 }, { l => 1 }, { t => 2 }, { x => 50 },
{ $resolution => 50 };
is_deeply( $dialog->get('current-scan-options'),
$expected, 'CLI geometry option names' );
$dialog->signal_handler_disconnect($signal);
$flag = TRUE;
$loop->quit;
}
);
$dialog->set( 'profile', 'cli geometry' );
$loop->run unless ($flag);
######################################
$dialog->signal_connect(
'changed-paper-formats' => sub {
my ( $widget, $formats ) = @_;
ok( 1, 'changed-paper-formats' );
}
);
$dialog->set(
'paper-formats',
{
new2 => {
l => 0,
y => 10,
x => 10,
t => 0,
}
}
);
$dialog->signal_connect(
'changed-paper' => sub {
my ( $widget, $paper ) = @_;
is( $paper, 'new2', 'changed-paper' );
my $options = $dialog->get('available-scan-options');
my $expected = [ { 'Paper size' => 'new' }, { $resolution => 50 } ];
push @$expected, { scalar(SANE_NAME_PAGE_HEIGHT) => 10 }
if ( defined $options->by_name(SANE_NAME_PAGE_HEIGHT) );
push @$expected, { scalar(SANE_NAME_PAGE_WIDTH) => 10 }
if ( defined $options->by_name(SANE_NAME_PAGE_WIDTH) );
push @$expected, { l => 0 }, { t => 0 }, { x => 10 }, { y => 10 };
is_deeply( $dialog->get('current-scan-options'),
$expected, 'CLI geometry option names after setting paper' );
}
);
$dialog->set( 'paper', 'new2' );
my $s_signal;
$s_signal = $dialog->signal_connect(
'started-process' => sub {
ok( 1, 'started-process' );
$dialog->signal_handler_disconnect($s_signal);
}
);
my $c_signal;
$c_signal = $dialog->signal_connect(
'changed-progress' => sub {
ok( 1, 'changed-progress' );
$dialog->signal_handler_disconnect($c_signal);
}
);
# FIXME: figure out how to emit this
# my $e_signal;
# $e_signal = $dialog->signal_connect(
# 'process-error' => sub {
# ok( 1, 'process-error' );
# $dialog->signal_handler_disconnect($e_signal);
# }
# );
$dialog->signal_connect(
'new-scan' => sub {
my ( $widget, $n ) = @_;
is( $n, 2, 'new_scan' );
$flag = TRUE;
Gtk2->main_quit;
}
);
$dialog->set( 'num-pages', 1 );
$dialog->set( 'page-number-increment', 1 );
$dialog->set_option( $options->by_name('enable-test-options'), TRUE );
$dialog->scan;
}
);
Gtk2->main;
is( $reloads, 2, 'Final number of calls reloaded-scan-options' );
is( $dialog->get('available-scan-options')->by_name('mode')->{val},
'Color', 'reloaded option still set to non-default value' );
__END__
gscan2pdf-1.2.3/t/162_import_ppm.t 0000644 0001750 0001750 00000002356 12053230657 015211 0 ustar jeff jeff use warnings;
use strict;
use File::Basename; # Split filename into dir, file, ext
use Test::More tests => 3;
BEGIN {
use_ok('Gscan2pdf::Document');
use Gtk2 -init; # Could just call init separately
}
#########################
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Document->setup($logger);
# Create test image
system('convert rose: test.ppm');
system('convert rose: test.png');
my $old = `identify -format '%m %G %g %z-bit %r' test.png`;
my $slist = Gscan2pdf::Document->new;
# dir for temporary files
my $dir = File::Temp->newdir;
$slist->set_dir($dir);
$slist->get_file_info(
path => 'test.ppm',
finished_callback => sub {
my ($info) = @_;
$slist->import_file(
info => $info,
first => 1,
last => 1,
finished_callback => sub {
is( `identify -format '%m %G %g %z-bit %r' $slist->{data}[0][2]{filename}`,
$old, 'PPM imported correctly' );
is( dirname("$slist->{data}[0][2]{filename}"),
"$dir", 'using session directory' );
Gtk2->main_quit;
}
);
}
);
Gtk2->main;
#########################
unlink 'test.ppm', 'test.png', <$dir/*>;
rmdir $dir;
Gscan2pdf::Document->quit();
gscan2pdf-1.2.3/t/066_Dialog_Scan_CLI.t 0000644 0001750 0001750 00000004512 12237446454 015664 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 5;
use Glib qw(TRUE FALSE); # To get TRUE and FALSE
use Gtk2 -init; # Could just call init separately
use Sane 0.05; # To get SANE_* enums
BEGIN {
use_ok('Gscan2pdf::Dialog::Scan::CLI');
}
#########################
my $window = Gtk2::Window->new;
Glib::set_application_name('gscan2pdf');
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Frontend::CLI->setup($logger);
ok(
my $dialog = Gscan2pdf::Dialog::Scan::CLI->new(
title => 'title',
'transient-for' => $window,
'logger' => $logger
),
'Created dialog'
);
isa_ok( $dialog, 'Gscan2pdf::Dialog::Scan::CLI' );
my $signal;
$signal = $dialog->signal_connect(
'reloaded-scan-options' => sub {
$dialog->signal_handler_disconnect($signal);
$dialog->set( 'current-scan-options', [ { 'invert-endianess' => 0 } ] );
$dialog->signal_connect(
'new-scan' => sub {
my ( $widget, $n ) = @_;
is( $n, 1, 'error-free scan despite illegal option' );
#########################
$dialog = Gscan2pdf::Dialog::Scan::CLI->new(
title => 'title',
'transient-for' => $window,
'logger' => $logger
);
$signal = $dialog->signal_connect(
'reloaded-scan-options' => sub {
$dialog->signal_handler_disconnect($signal);
$dialog->set( 'current-scan-options',
[ { mode => 'Gray' }, { 'invert-endianess' => 0 } ] );
$dialog->signal_connect(
'new-scan' => sub {
my ( $widget, $n ) = @_;
is( $n, 1,
'error-free scan despite illegal option following an ignored one' );
Gtk2->main_quit;
}
);
$dialog->signal_connect(
'process-error' => sub {
my ( $widget, $process, $msg ) = @_;
Gtk2->main_quit;
}
);
$dialog->set( 'num-pages', 1 );
$dialog->set( 'page-number-increment', 1 );
$dialog->scan;
}
);
$dialog->set( 'device-list', [ { 'name' => 'test' } ] );
$dialog->set( 'device', 'test' );
}
);
$dialog->set( 'num-pages', 1 );
$dialog->set( 'page-number-increment', 1 );
$dialog->scan;
}
);
$dialog->set( 'device-list', [ { 'name' => 'test' } ] );
$dialog->set( 'device', 'test' );
#########################
Gtk2->main;
__END__
gscan2pdf-1.2.3/t/151_save_text.t 0000644 0001750 0001750 00000002153 12270574026 015020 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 1;
BEGIN {
use Gscan2pdf::Document;
use Gtk2 -init; # Could just call init separately
}
#########################
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Document->setup($logger);
# Create test image
system('convert rose: test.pnm');
my $slist = Gscan2pdf::Document->new;
# dir for temporary files
my $dir = File::Temp->newdir;
$slist->set_dir($dir);
$slist->get_file_info(
path => 'test.pnm',
finished_callback => sub {
my ($info) = @_;
$slist->import_file(
info => $info,
first => 1,
last => 1,
finished_callback => sub {
$slist->{data}[0][2]{hocr} = 'The quick brown fox';
$slist->save_text(
path => 'test.txt',
list_of_pages => [ $slist->{data}[0][2] ],
finished_callback => sub { Gtk2->main_quit }
);
}
);
}
);
Gtk2->main;
is( `cat test.txt`, 'The quick brown fox', 'saved ASCII' );
#########################
unlink 'test.pnm', 'test.txt';
Gscan2pdf::Document->quit();
gscan2pdf-1.2.3/t/38_user_defined2.t 0000644 0001750 0001750 00000002237 12270574026 015463 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 1;
BEGIN {
use Gscan2pdf::Document;
use Gtk2 -init; # Could just call init separately
}
#########################
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
Gscan2pdf::Document->setup(Log::Log4perl::get_logger);
# Create test image
system('convert xc:white white.pnm');
my $slist = Gscan2pdf::Document->new;
# dir for temporary files
my $dir = File::Temp->newdir;
$slist->set_dir($dir);
$slist->get_file_info(
path => 'white.pnm',
finished_callback => sub {
my ($info) = @_;
$slist->import_file(
info => $info,
first => 1,
last => 1,
finished_callback => sub {
$slist->user_defined(
page => $slist->{data}[0][2],
command => 'convert %i -negate %i',
finished_callback => sub {
$slist->analyse(
page => $slist->{data}[0][2],
finished_callback => sub { Gtk2->main_quit }
);
}
);
}
);
}
);
Gtk2->main;
is( $slist->{data}[0][2]{mean}, 0, 'User-defined with %i' );
#########################
unlink 'white.pnm';
Gscan2pdf::Document->quit();
gscan2pdf-1.2.3/t/02_Scanner_Options_snapscan.t 0000644 0001750 0001750 00000037110 12271200642 017713 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 3;
use Sane 0.05; # For enums
BEGIN { use_ok('Gscan2pdf::Scanner::Options') }
#########################
my $filename = 'scanners/snapscan';
my $output = do { local ( @ARGV, $/ ) = $filename; <> };
my $options = Gscan2pdf::Scanner::Options->new_from_data($output);
my @that = (
{
'index' => 0,
},
{
index => 1,
title => 'Scan Mode',
'cap' => 0,
'max_values' => 0,
'name' => '',
'unit' => SANE_UNIT_NONE,
'desc' => '',
type => SANE_TYPE_GROUP,
'constraint_type' => SANE_CONSTRAINT_NONE
},
{
name => 'resolution',
title => 'Resolution',
index => 2,
'desc' => 'Sets the resolution of the scanned image.',
'val' => '300',
'constraint' => [ '50', '75', '100', '150', '200', '300', '450', '600' ],
'unit' => SANE_UNIT_DPI,
constraint_type => SANE_CONSTRAINT_WORD_LIST,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_AUTOMATIC,
'max_values' => 1,
},
{
name => 'preview',
title => 'Preview',
index => 3,
'desc' => 'Request a preview-quality scan.',
'val' => SANE_FALSE,
'unit' => SANE_UNIT_NONE,
'type' => SANE_TYPE_BOOL,
'constraint_type' => SANE_CONSTRAINT_NONE,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_AUTOMATIC,
'max_values' => 1,
},
{
name => 'mode',
title => 'Mode',
index => 4,
'desc' => 'Selects the scan mode (e.g., lineart, monochrome, or color).',
'val' => 'Color',
'constraint' => [ 'Color', 'Halftone', 'Gray', 'Lineart' ],
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_STRING_LIST,
type => SANE_TYPE_STRING,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_AUTOMATIC,
'max_values' => 1,
},
{
name => 'preview-mode',
title => 'Preview mode',
index => 5,
'desc' =>
'Select the mode for previews. Greyscale previews usually give the best combination of speed and detail.',
'val' => 'Auto',
'constraint' => [ 'Auto', 'Color', 'Halftone', 'Gray', 'Lineart' ],
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_STRING_LIST,
type => SANE_TYPE_STRING,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_AUTOMATIC,
'max_values' => 1,
},
{
name => 'high-quality',
title => 'High quality',
index => 6,
'desc' => 'Highest quality but lower speed',
'val' => SANE_FALSE,
'unit' => SANE_UNIT_NONE,
'type' => SANE_TYPE_BOOL,
'constraint_type' => SANE_CONSTRAINT_NONE,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_AUTOMATIC,
'max_values' => 1,
},
{
name => 'source',
title => 'Source',
index => 7,
'desc' => 'Selects the scan source (such as a document-feeder).',
'constraint' => ['Flatbed'],
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_STRING_LIST,
type => SANE_TYPE_STRING,
'cap' => SANE_CAP_SOFT_DETECT +
SANE_CAP_SOFT_SELECT +
SANE_CAP_INACTIVE +
SANE_CAP_AUTOMATIC,
'max_values' => 1,
},
{
index => 8,
title => 'Geometry',
'cap' => 0,
'max_values' => 0,
'name' => '',
'unit' => SANE_UNIT_NONE,
'desc' => '',
type => SANE_TYPE_GROUP,
'constraint_type' => SANE_CONSTRAINT_NONE
},
{
name => 'l',
title => 'Top-left x',
index => 9,
'desc' => 'Top-left x position of scan area.',
'val' => 0,
constraint => {
'min' => 0,
'max' => 216,
},
'unit' => SANE_UNIT_MM,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 't',
title => 'Top-left y',
index => 10,
'desc' => 'Top-left y position of scan area.',
'val' => 0,
constraint => {
'min' => 0,
'max' => 297,
},
'unit' => SANE_UNIT_MM,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'x',
title => 'Width',
index => 11,
'desc' => 'Width of scan-area.',
'val' => 216,
constraint => {
'min' => 0,
'max' => 216,
},
'unit' => SANE_UNIT_MM,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'y',
title => 'Height',
index => 12,
'desc' => 'Height of scan-area.',
'val' => 297,
constraint => {
'min' => 0,
'max' => 297,
},
'unit' => SANE_UNIT_MM,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'predef-window',
title => 'Predef window',
index => 13,
'desc' =>
'Provides standard scanning areas for photographs, printed pages and the like.',
'val' => 'None',
'constraint' => [ 'None', '6x4 (inch)', '8x10 (inch)', '8.5x11 (inch)' ],
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_STRING_LIST,
type => SANE_TYPE_STRING,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
index => 14,
title => 'Enhancement',
'cap' => 0,
'max_values' => 0,
'name' => '',
'unit' => SANE_UNIT_NONE,
'desc' => '',
type => SANE_TYPE_GROUP,
'constraint_type' => SANE_CONSTRAINT_NONE
},
{
name => 'depth',
title => 'Depth',
index => 15,
'desc' =>
'Number of bits per sample, typical values are 1 for "line-art" and 8 for multibit scans.',
'constraint' => ['8'],
'unit' => SANE_UNIT_BIT,
constraint_type => SANE_CONSTRAINT_WORD_LIST,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
'max_values' => 1,
},
{
name => 'quality-cal',
title => 'Quality cal',
index => 16,
'desc' => 'Do a quality white-calibration',
'val' => SANE_TRUE,
'unit' => SANE_UNIT_NONE,
'type' => SANE_TYPE_BOOL,
'constraint_type' => SANE_CONSTRAINT_NONE,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'halftoning',
title => 'Halftoning',
index => 17,
'desc' =>
'Selects whether the acquired image should be halftoned (dithered).',
'unit' => SANE_UNIT_NONE,
'type' => SANE_TYPE_BOOL,
'constraint_type' => SANE_CONSTRAINT_NONE,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
'max_values' => 1,
},
{
name => 'halftone-pattern',
title => 'Halftone pattern',
index => 18,
'desc' =>
'Defines the halftoning (dithering) pattern for scanning halftoned images.',
'constraint' => [ 'DispersedDot8x8', 'DispersedDot16x16' ],
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_STRING_LIST,
type => SANE_TYPE_STRING,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
'max_values' => 1,
},
{
name => 'custom-gamma',
title => 'Custom gamma',
index => 19,
'desc' =>
'Determines whether a builtin or a custom gamma-table should be used.',
'val' => SANE_FALSE,
'unit' => SANE_UNIT_NONE,
'type' => SANE_TYPE_BOOL,
'constraint_type' => SANE_CONSTRAINT_NONE,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'analog-gamma-bind',
title => 'Analog gamma bind',
index => 20,
'desc' => 'In RGB-mode use same values for each color',
'val' => SANE_FALSE,
'unit' => SANE_UNIT_NONE,
'type' => SANE_TYPE_BOOL,
'constraint_type' => SANE_CONSTRAINT_NONE,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'analog-gamma',
title => 'Analog gamma',
index => 21,
'desc' => 'Analog gamma-correction',
constraint => {
'min' => 0,
'max' => 4,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
'max_values' => 1,
},
{
name => 'analog-gamma-r',
title => 'Analog gamma r',
index => 22,
'desc' => 'Analog gamma-correction for red',
'val' => '1.79999',
constraint => {
'min' => 0,
'max' => 4,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_FIXED,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'analog-gamma-g',
title => 'Analog gamma g',
index => 23,
'desc' => 'Analog gamma-correction for green',
'val' => '1.79999',
constraint => {
'min' => 0,
'max' => 4,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_FIXED,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'analog-gamma-b',
title => 'Analog gamma b',
index => 24,
'desc' => 'Analog gamma-correction for blue',
'val' => '1.79999',
constraint => {
'min' => 0,
'max' => 4,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_FIXED,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'gamma-table',
title => 'Gamma table',
index => 25,
'desc' =>
'Gamma-correction table. In color mode this option equally affects the red, green, and blue channels simultaneously (i.e., it is an intensity gamma table).',
constraint => {
'min' => 0,
'max' => 65535,
'quant' => 1,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
'max_values' => 255,
},
{
name => 'red-gamma-table',
title => 'Red gamma table',
index => 26,
'desc' => 'Gamma-correction table for the red band.',
constraint => {
'min' => 0,
'max' => 65535,
'quant' => 1,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
'max_values' => 255,
},
{
name => 'green-gamma-table',
title => 'Green gamma table',
index => 27,
'desc' => 'Gamma-correction table for the green band.',
constraint => {
'min' => 0,
'max' => 65535,
'quant' => 1,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
'max_values' => 255,
},
{
name => 'blue-gamma-table',
title => 'Blue gamma table',
index => 28,
'desc' => 'Gamma-correction table for the blue band.',
constraint => {
'min' => 0,
'max' => 65535,
'quant' => 1,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
'max_values' => 255,
},
{
name => 'negative',
title => 'Negative',
index => 29,
'desc' => 'Swap black and white',
'unit' => SANE_UNIT_NONE,
'type' => SANE_TYPE_BOOL,
'constraint_type' => SANE_CONSTRAINT_NONE,
'cap' => SANE_CAP_SOFT_DETECT +
SANE_CAP_SOFT_SELECT +
SANE_CAP_INACTIVE +
SANE_CAP_AUTOMATIC,
'max_values' => 1,
},
{
name => 'threshold',
title => 'Threshold',
index => 30,
'desc' => 'Select minimum-brightness to get a white point',
constraint => {
'min' => 0,
'max' => 100,
'quant' => 1,
},
'unit' => SANE_UNIT_PERCENT,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
'max_values' => 1,
},
{
name => 'brightness',
title => 'Brightness',
index => 31,
'desc' => 'Controls the brightness of the acquired image.',
'val' => '0',
constraint => {
'min' => -400,
'max' => 400,
'quant' => 1,
},
'unit' => SANE_UNIT_PERCENT,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'contrast',
title => 'Contrast',
index => 32,
'desc' => 'Controls the contrast of the acquired image.',
'val' => '0',
constraint => {
'min' => -100,
'max' => 400,
'quant' => 1,
},
'unit' => SANE_UNIT_PERCENT,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
index => 33,
title => 'Advanced',
'cap' => 0,
'max_values' => 0,
'name' => '',
'unit' => SANE_UNIT_NONE,
'desc' => '',
type => SANE_TYPE_GROUP,
'constraint_type' => SANE_CONSTRAINT_NONE
},
{
name => 'rgb-lpr',
title => 'Rgb lpr',
index => 34,
'desc' =>
'Number of scan lines to request in a SCSI read. Changing this parameter allows you to tune the speed at which data is read from the scanner during scans. If this is set too low, the scanner will have to stop periodically in the middle of a scan; if it\'s set too high, X-based frontends may stop responding to X events and your system could bog down.',
'val' => '4',
constraint => {
'min' => 1,
'max' => 50,
'quant' => 1,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'gs-lpr',
title => 'Gs lpr',
index => 35,
'desc' =>
'Number of scan lines to request in a SCSI read. Changing this parameter allows you to tune the speed at which data is read from the scanner during scans. If this is set too low, the scanner will have to stop periodically in the middle of a scan; if it\'s set too high, X-based frontends may stop responding to X events and your system could bog down.',
constraint => {
'min' => 1,
'max' => 50,
'quant' => 1,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
'max_values' => 1,
},
);
is_deeply( $options->{array}, \@that, 'snapscan' );
is( Gscan2pdf::Scanner::Options->device,
'snapscan:/dev/uscanner0', 'device name' );
gscan2pdf-1.2.3/t/26_unsharp_mask.t 0000644 0001750 0001750 00000002536 12053230657 015435 0 ustar jeff jeff use warnings;
use strict;
use File::Basename; # Split filename into dir, file, ext
use Test::More tests => 3;
BEGIN {
use_ok('Gscan2pdf::Document');
use Gtk2 -init; # Could just call init separately
}
#########################
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Document->setup($logger);
# Create test image
system('convert rose: test.jpg');
my $slist = Gscan2pdf::Document->new;
# dir for temporary files
my $dir = File::Temp->newdir;
$slist->set_dir($dir);
$slist->get_file_info(
path => 'test.jpg',
finished_callback => sub {
my ($info) = @_;
$slist->import_file(
info => $info,
first => 1,
last => 1,
finished_callback => sub {
$slist->unsharp(
page => $slist->{data}[0][2],
radius => 100,
sigma => 5,
amount => 100,
threshold => 0.5,
finished_callback => sub {
is( system("identify $slist->{data}[0][2]{filename}"),
0, 'valid JPG created' );
is( dirname("$slist->{data}[0][2]{filename}"),
"$dir", 'using session directory' );
Gtk2->main_quit;
}
);
}
);
}
);
Gtk2->main;
#########################
unlink 'test.jpg', <$dir/*>;
rmdir $dir;
Gscan2pdf::Document->quit();
gscan2pdf-1.2.3/t/02_Scanner_Options_umax.t 0000644 0001750 0001750 00000067001 12271200642 017061 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 3;
use Sane 0.05; # For enums
BEGIN { use_ok('Gscan2pdf::Scanner::Options') }
#########################
my $filename = 'scanners/umax';
my $output = do { local ( @ARGV, $/ ) = $filename; <> };
my $options = Gscan2pdf::Scanner::Options->new_from_data($output);
my @that = (
{
'index' => 0,
},
{
index => 1,
title => 'Scan Mode',
'cap' => 0,
'max_values' => 0,
'name' => '',
'unit' => SANE_UNIT_NONE,
'desc' => '',
type => SANE_TYPE_GROUP,
'constraint_type' => SANE_CONSTRAINT_NONE
},
{
name => 'mode',
title => 'Mode',
index => 2,
'desc' => 'Selects the scan mode (e.g., lineart, monochrome, or color).',
'val' => 'Color',
'constraint' => [ 'Lineart', 'Gray', 'Color' ],
constraint_type => SANE_CONSTRAINT_STRING_LIST,
'unit' => SANE_UNIT_NONE,
type => SANE_TYPE_STRING,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
max_values => 1,
},
{
name => 'source',
title => 'Source',
index => 3,
'desc' => 'Selects the scan source (such as a document-feeder).',
'val' => 'Flatbed',
'constraint' => ['Flatbed'],
constraint_type => SANE_CONSTRAINT_STRING_LIST,
'unit' => SANE_UNIT_NONE,
type => SANE_TYPE_STRING,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
max_values => 1,
},
{
name => 'resolution',
title => 'Resolution',
index => 4,
'desc' => 'Sets the resolution of the scanned image.',
'val' => '100',
constraint => {
'min' => 5,
'max' => 300,
'quant' => 5,
},
constraint_type => SANE_CONSTRAINT_RANGE,
'unit' => SANE_UNIT_DPI,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
max_values => 1,
},
{
name => 'y-resolution',
title => 'Y resolution',
index => 5,
'desc' => 'Sets the vertical resolution of the scanned image.',
constraint => {
'min' => 5,
'max' => 600,
'quant' => 5,
},
constraint_type => SANE_CONSTRAINT_RANGE,
'unit' => SANE_UNIT_DPI,
type => SANE_TYPE_INT,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
max_values => 1,
},
{
name => 'resolution-bind',
title => 'Resolution bind',
index => 6,
'desc' => 'Use same values for X and Y resolution',
'val' => SANE_TRUE,
constraint_type => SANE_CONSTRAINT_NONE,
'unit' => SANE_UNIT_NONE,
type => SANE_TYPE_BOOL,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
max_values => 1,
},
{
name => 'negative',
title => 'Negative',
index => 7,
'desc' => 'Swap black and white',
constraint_type => SANE_CONSTRAINT_NONE,
'unit' => SANE_UNIT_NONE,
type => SANE_TYPE_BOOL,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
max_values => 1,
},
{
index => 8,
title => 'Geometry',
'cap' => 0,
'max_values' => 0,
'name' => '',
'unit' => SANE_UNIT_NONE,
'desc' => '',
type => SANE_TYPE_GROUP,
'constraint_type' => SANE_CONSTRAINT_NONE
},
{
name => 'l',
title => 'Top-left x',
index => 9,
'desc' => 'Top-left x position of scan area.',
'val' => 0,
constraint => {
'min' => 0,
'max' => 215.9,
},
constraint_type => SANE_CONSTRAINT_RANGE,
'unit' => SANE_UNIT_MM,
type => SANE_TYPE_FIXED,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
max_values => 1,
},
{
name => 't',
title => 'Top-left y',
index => 10,
'desc' => 'Top-left y position of scan area.',
'val' => 0,
constraint => {
'min' => 0,
'max' => 297.18,
},
constraint_type => SANE_CONSTRAINT_RANGE,
'unit' => SANE_UNIT_MM,
type => SANE_TYPE_FIXED,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
max_values => 1,
},
{
name => 'x',
title => 'Width',
index => 11,
'desc' => 'Width of scan-area.',
'val' => 215.9,
constraint => {
'min' => 0,
'max' => 215.9,
},
constraint_type => SANE_CONSTRAINT_RANGE,
'unit' => SANE_UNIT_MM,
type => SANE_TYPE_FIXED,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
max_values => 1,
},
{
name => 'y',
title => 'Height',
index => 12,
'desc' => 'Height of scan-area.',
'val' => 297.18,
constraint => {
'min' => 0,
'max' => 297.18,
},
constraint_type => SANE_CONSTRAINT_RANGE,
'unit' => SANE_UNIT_MM,
type => SANE_TYPE_FIXED,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
max_values => 1,
},
{
index => 13,
title => 'Enhancement',
'cap' => 0,
'max_values' => 0,
'name' => '',
'unit' => SANE_UNIT_NONE,
'desc' => '',
type => SANE_TYPE_GROUP,
'constraint_type' => SANE_CONSTRAINT_NONE
},
{
name => 'depth',
title => 'Depth',
index => 14,
'desc' =>
'Number of bits per sample, typical values are 1 for "line-art" and 8 for multibit scans.',
'val' => '8',
'constraint' => ['8'],
constraint_type => SANE_CONSTRAINT_WORD_LIST,
'unit' => SANE_UNIT_BIT,
type => SANE_TYPE_INT,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
max_values => 1,
},
{
name => 'quality-cal',
title => 'Quality cal',
index => 15,
'desc' => 'Do a quality white-calibration',
'val' => SANE_TRUE,
constraint_type => SANE_CONSTRAINT_NONE,
'unit' => SANE_UNIT_NONE,
type => SANE_TYPE_BOOL,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
max_values => 1,
},
{
name => 'double-res',
title => 'Double res',
index => 16,
'desc' => 'Use lens that doubles optical resolution',
constraint_type => SANE_CONSTRAINT_NONE,
'unit' => SANE_UNIT_NONE,
type => SANE_TYPE_BOOL,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
max_values => 1,
},
{
name => 'warmup',
title => 'Warmup',
index => 17,
'desc' => 'Warmup lamp before scanning',
constraint_type => SANE_CONSTRAINT_NONE,
'unit' => SANE_UNIT_NONE,
type => SANE_TYPE_BOOL,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
max_values => 1,
},
{
name => 'rgb-bind',
title => 'Rgb bind',
index => 18,
'desc' => 'In RGB-mode use same values for each color',
'val' => SANE_FALSE,
constraint_type => SANE_CONSTRAINT_NONE,
'unit' => SANE_UNIT_NONE,
type => SANE_TYPE_BOOL,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
max_values => 1,
},
{
name => 'brightness',
title => 'Brightness',
index => 19,
'desc' => 'Controls the brightness of the acquired image.',
constraint => {
'min' => -100,
'max' => 100,
'quant' => 1,
},
constraint_type => SANE_CONSTRAINT_RANGE,
'unit' => SANE_UNIT_PERCENT,
type => SANE_TYPE_INT,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
max_values => 1,
},
{
name => 'contrast',
title => 'Contrast',
index => 20,
'desc' => 'Controls the contrast of the acquired image.',
constraint => {
'min' => -100,
'max' => 100,
'quant' => 1,
},
constraint_type => SANE_CONSTRAINT_RANGE,
'unit' => SANE_UNIT_PERCENT,
type => SANE_TYPE_INT,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
max_values => 1,
},
{
name => 'threshold',
title => 'Threshold',
index => 21,
'desc' => 'Select minimum-brightness to get a white point',
constraint => {
'min' => 0,
'max' => 100,
},
constraint_type => SANE_CONSTRAINT_RANGE,
'unit' => SANE_UNIT_PERCENT,
type => SANE_TYPE_INT,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
max_values => 1,
},
{
name => 'highlight',
title => 'Highlight',
index => 22,
'desc' => 'Selects what radiance level should be considered "white".',
constraint => {
'min' => 0,
'max' => 100,
},
constraint_type => SANE_CONSTRAINT_RANGE,
'unit' => SANE_UNIT_PERCENT,
type => SANE_TYPE_INT,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
max_values => 1,
},
{
name => 'highlight-r',
title => 'Highlight r',
index => 23,
'desc' => 'Selects what red radiance level should be considered "full red".',
'val' => '100',
constraint => {
'min' => 0,
'max' => 100,
},
constraint_type => SANE_CONSTRAINT_RANGE,
'unit' => SANE_UNIT_PERCENT,
type => SANE_TYPE_INT,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
max_values => 1,
},
{
name => 'highlight-g',
title => 'Highlight g',
index => 24,
'desc' =>
'Selects what green radiance level should be considered "full green".',
'val' => '100',
constraint => {
'min' => 0,
'max' => 100,
},
constraint_type => SANE_CONSTRAINT_RANGE,
'unit' => SANE_UNIT_PERCENT,
type => SANE_TYPE_INT,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
max_values => 1,
},
{
name => 'highlight-b',
title => 'Highlight b',
index => 25,
'desc' =>
'Selects what blue radiance level should be considered "full blue".',
'val' => '100',
constraint => {
'min' => 0,
'max' => 100,
},
constraint_type => SANE_CONSTRAINT_RANGE,
'unit' => SANE_UNIT_PERCENT,
type => SANE_TYPE_INT,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
max_values => 1,
},
{
name => 'shadow',
title => 'Shadow',
index => 26,
'desc' => 'Selects what radiance level should be considered "black".',
constraint => {
'min' => 0,
'max' => 100,
},
constraint_type => SANE_CONSTRAINT_RANGE,
'unit' => SANE_UNIT_PERCENT,
type => SANE_TYPE_INT,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
max_values => 1,
},
{
name => 'shadow-r',
title => 'Shadow r',
index => 27,
'desc' => 'Selects what red radiance level should be considered "black".',
constraint => {
'min' => 0,
'max' => 100,
},
constraint_type => SANE_CONSTRAINT_RANGE,
'unit' => SANE_UNIT_PERCENT,
type => SANE_TYPE_INT,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
max_values => 1,
},
{
name => 'shadow-g',
title => 'Shadow g',
index => 28,
'desc' => 'Selects what green radiance level should be considered "black".',
constraint => {
'min' => 0,
'max' => 100,
},
constraint_type => SANE_CONSTRAINT_RANGE,
'unit' => SANE_UNIT_PERCENT,
type => SANE_TYPE_INT,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
max_values => 1,
},
{
name => 'shadow-b',
title => 'Shadow b',
index => 29,
'desc' => 'Selects what blue radiance level should be considered "black".',
constraint => {
'min' => 0,
'max' => 100,
},
constraint_type => SANE_CONSTRAINT_RANGE,
'unit' => SANE_UNIT_PERCENT,
type => SANE_TYPE_INT,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
max_values => 1,
},
{
name => 'analog-gamma',
title => 'Analog gamma',
index => 30,
'desc' => 'Analog gamma-correction',
constraint => {
'min' => 1,
'max' => 2,
'quant' => 0.00999451,
},
constraint_type => SANE_CONSTRAINT_RANGE,
'unit' => SANE_UNIT_NONE,
type => SANE_TYPE_FIXED,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
max_values => 1,
},
{
name => 'analog-gamma-r',
title => 'Analog gamma r',
index => 31,
'desc' => 'Analog gamma-correction for red',
constraint => {
'min' => 1,
'max' => 2,
'quant' => 0.00999451,
},
constraint_type => SANE_CONSTRAINT_RANGE,
'unit' => SANE_UNIT_NONE,
type => SANE_TYPE_FIXED,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
max_values => 1,
},
{
name => 'analog-gamma-g',
title => 'Analog gamma g',
index => 32,
'desc' => 'Analog gamma-correction for green',
constraint => {
'min' => 1,
'max' => 2,
'quant' => 0.00999451,
},
constraint_type => SANE_CONSTRAINT_RANGE,
'unit' => SANE_UNIT_NONE,
type => SANE_TYPE_FIXED,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
max_values => 1,
},
{
name => 'analog-gamma-b',
title => 'Analog gamma b',
index => 33,
'desc' => 'Analog gamma-correction for blue',
constraint => {
'min' => 1,
'max' => 2,
'quant' => 0.00999451,
},
constraint_type => SANE_CONSTRAINT_RANGE,
'unit' => SANE_UNIT_NONE,
type => SANE_TYPE_FIXED,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
max_values => 1,
},
{
name => 'custom-gamma',
title => 'Custom gamma',
index => 34,
'desc' =>
'Determines whether a builtin or a custom gamma-table should be used.',
'val' => SANE_TRUE,
constraint_type => SANE_CONSTRAINT_NONE,
'unit' => SANE_UNIT_NONE,
type => SANE_TYPE_BOOL,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
max_values => 1,
},
{
name => 'gamma-table',
title => 'Gamma table',
index => 35,
constraint => {
'min' => 0,
'max' => 255,
},
'desc' =>
'Gamma-correction table. In color mode this option equally affects the red, green, and blue channels simultaneously (i.e., it is an intensity gamma table).',
constraint_type => SANE_CONSTRAINT_RANGE,
'unit' => SANE_UNIT_NONE,
type => SANE_TYPE_INT,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
max_values => 255,
},
{
name => 'red-gamma-table',
title => 'Red gamma table',
index => 36,
constraint => {
'min' => 0,
'max' => 255,
},
'desc' => 'Gamma-correction table for the red band.',
constraint_type => SANE_CONSTRAINT_RANGE,
'unit' => SANE_UNIT_NONE,
type => SANE_TYPE_INT,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
max_values => 255,
},
{
name => 'green-gamma-table',
title => 'Green gamma table',
index => 37,
constraint => {
'min' => 0,
'max' => 255,
},
'desc' => 'Gamma-correction table for the green band.',
constraint_type => SANE_CONSTRAINT_RANGE,
'unit' => SANE_UNIT_NONE,
type => SANE_TYPE_INT,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
max_values => 255,
},
{
name => 'blue-gamma-table',
title => 'Blue gamma table',
index => 38,
constraint => {
'min' => 0,
'max' => 255,
},
'desc' => 'Gamma-correction table for the blue band.',
constraint_type => SANE_CONSTRAINT_RANGE,
'unit' => SANE_UNIT_NONE,
type => SANE_TYPE_INT,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
max_values => 255,
},
{
name => 'halftone-size',
title => 'Halftone size',
index => 39,
'desc' =>
'Sets the size of the halftoning (dithering) pattern used when scanning halftoned images.',
'constraint' => [ '2', '4', '6', '8', '12' ],
constraint_type => SANE_CONSTRAINT_WORD_LIST,
'unit' => SANE_UNIT_PIXEL,
type => SANE_TYPE_INT,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
max_values => 1,
},
{
name => 'halftone-pattern',
title => 'Halftone pattern',
index => 40,
'desc' =>
'Defines the halftoning (dithering) pattern for scanning halftoned images.',
constraint => {
'min' => 0,
'max' => 255,
},
constraint_type => SANE_CONSTRAINT_RANGE,
'unit' => SANE_UNIT_NONE,
type => SANE_TYPE_INT,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
max_values => 1,
},
{
index => 41,
title => 'Advanced',
'cap' => 0,
'max_values' => 0,
'name' => '',
'unit' => SANE_UNIT_NONE,
'desc' => '',
type => SANE_TYPE_GROUP,
'constraint_type' => SANE_CONSTRAINT_NONE
},
{
name => 'cal-exposure-time',
title => 'Cal exposure time',
index => 42,
'desc' => 'Define exposure-time for calibration',
constraint => {
'min' => 0,
'max' => 0,
},
constraint_type => SANE_CONSTRAINT_RANGE,
'unit' => SANE_UNIT_MICROSECOND,
type => SANE_TYPE_INT,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
max_values => 1,
},
{
name => 'cal-exposure-time-r',
title => 'Cal exposure time r',
index => 43,
'desc' => 'Define exposure-time for red calibration',
constraint => {
'min' => 0,
'max' => 0,
},
constraint_type => SANE_CONSTRAINT_RANGE,
'unit' => SANE_UNIT_MICROSECOND,
type => SANE_TYPE_INT,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
max_values => 1,
},
{
name => 'cal-exposure-time-g',
title => 'Cal exposure time g',
index => 44,
'desc' => 'Define exposure-time for green calibration',
constraint => {
'min' => 0,
'max' => 0,
},
constraint_type => SANE_CONSTRAINT_RANGE,
'unit' => SANE_UNIT_MICROSECOND,
type => SANE_TYPE_INT,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
max_values => 1,
},
{
name => 'cal-exposure-time-b',
title => 'Cal exposure time b',
index => 45,
'desc' => 'Define exposure-time for blue calibration',
constraint => {
'min' => 0,
'max' => 0,
},
constraint_type => SANE_CONSTRAINT_RANGE,
'unit' => SANE_UNIT_MICROSECOND,
type => SANE_TYPE_INT,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
max_values => 1,
},
{
name => 'scan-exposure-time',
title => 'Scan exposure time',
index => 46,
'desc' => 'Define exposure-time for scan',
constraint => {
'min' => 0,
'max' => 0,
},
constraint_type => SANE_CONSTRAINT_RANGE,
'unit' => SANE_UNIT_MICROSECOND,
type => SANE_TYPE_INT,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
max_values => 1,
},
{
name => 'scan-exposure-time-r',
title => 'Scan exposure time r',
index => 47,
'desc' => 'Define exposure-time for red scan',
constraint => {
'min' => 0,
'max' => 0,
},
constraint_type => SANE_CONSTRAINT_RANGE,
'unit' => SANE_UNIT_MICROSECOND,
type => SANE_TYPE_INT,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
max_values => 1,
},
{
name => 'scan-exposure-time-g',
title => 'Scan exposure time g',
index => 48,
'desc' => 'Define exposure-time for green scan',
constraint => {
'min' => 0,
'max' => 0,
},
constraint_type => SANE_CONSTRAINT_RANGE,
'unit' => SANE_UNIT_MICROSECOND,
type => SANE_TYPE_INT,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
max_values => 1,
},
{
name => 'scan-exposure-time-b',
title => 'Scan exposure time b',
index => 49,
'desc' => 'Define exposure-time for blue scan',
constraint => {
'min' => 0,
'max' => 0,
},
constraint_type => SANE_CONSTRAINT_RANGE,
'unit' => SANE_UNIT_MICROSECOND,
type => SANE_TYPE_INT,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
max_values => 1,
},
{
name => 'disable-pre-focus',
title => 'Disable pre focus',
index => 50,
'desc' => 'Do not calibrate focus',
constraint_type => SANE_CONSTRAINT_NONE,
'unit' => SANE_UNIT_NONE,
type => SANE_TYPE_BOOL,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
max_values => 1,
},
{
name => 'manual-pre-focus',
title => 'Manual pre focus',
index => 51,
'desc' => '',
constraint_type => SANE_CONSTRAINT_NONE,
'unit' => SANE_UNIT_NONE,
type => SANE_TYPE_BOOL,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
max_values => 1,
},
{
name => 'fix-focus-position',
title => 'Fix focus position',
index => 52,
'desc' => '',
constraint_type => SANE_CONSTRAINT_NONE,
'unit' => SANE_UNIT_NONE,
type => SANE_TYPE_BOOL,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
max_values => 1,
},
{
name => 'lens-calibration-in-doc-position',
title => 'Lens calibration in doc position',
index => 53,
'desc' => 'Calibrate lens focus in document position',
constraint_type => SANE_CONSTRAINT_NONE,
'unit' => SANE_UNIT_NONE,
type => SANE_TYPE_BOOL,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
max_values => 1,
},
{
name => 'holder-focus-position-0mm',
title => 'Holder focus position 0mm',
index => 54,
'desc' => 'Use 0mm holder focus position instead of 0.6mm',
constraint_type => SANE_CONSTRAINT_NONE,
'unit' => SANE_UNIT_NONE,
type => SANE_TYPE_BOOL,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
max_values => 1,
},
{
name => 'cal-lamp-density',
title => 'Cal lamp density',
index => 55,
'desc' => 'Define lamp density for calibration',
constraint => {
'min' => 0,
'max' => 100,
},
constraint_type => SANE_CONSTRAINT_RANGE,
'unit' => SANE_UNIT_PERCENT,
type => SANE_TYPE_INT,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
max_values => 1,
},
{
name => 'scan-lamp-density',
title => 'Scan lamp density',
index => 56,
'desc' => 'Define lamp density for scan',
constraint => {
'min' => 0,
'max' => 100,
},
constraint_type => SANE_CONSTRAINT_RANGE,
'unit' => SANE_UNIT_PERCENT,
type => SANE_TYPE_INT,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
max_values => 1,
},
{
name => 'select-exposure-time',
title => 'Select exposure time',
index => 57,
'desc' => 'Enable selection of exposure-time',
constraint_type => SANE_CONSTRAINT_NONE,
'unit' => SANE_UNIT_NONE,
type => SANE_TYPE_BOOL,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
max_values => 1,
},
{
name => 'select-calibration-exposure-time',
title => 'Select calibration exposure time',
index => 58,
'desc' => 'Allow different settings for calibration and scan exposure times',
constraint_type => SANE_CONSTRAINT_NONE,
'unit' => SANE_UNIT_NONE,
type => SANE_TYPE_BOOL,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
max_values => 1,
},
{
name => 'select-lamp-density',
title => 'Select lamp density',
index => 59,
'desc' => 'Enable selection of lamp density',
constraint_type => SANE_CONSTRAINT_NONE,
'unit' => SANE_UNIT_NONE,
type => SANE_TYPE_BOOL,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
max_values => 1,
},
{
name => 'lamp-on',
title => 'Lamp on',
index => 60,
'desc' => 'Turn on scanner lamp',
constraint_type => SANE_CONSTRAINT_NONE,
'unit' => SANE_UNIT_NONE,
type => SANE_TYPE_BUTTON,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
max_values => 0,
},
{
name => 'lamp-off',
title => 'Lamp off',
index => 61,
'desc' => 'Turn off scanner lamp',
constraint_type => SANE_CONSTRAINT_NONE,
'unit' => SANE_UNIT_NONE,
type => SANE_TYPE_BUTTON,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
max_values => 0,
},
{
name => 'lamp-off-at-exit',
title => 'Lamp off at exit',
index => 62,
'desc' => 'Turn off lamp when program exits',
type => SANE_TYPE_BOOL,
constraint_type => SANE_CONSTRAINT_NONE,
'unit' => SANE_UNIT_NONE,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
max_values => 1,
},
{
name => 'batch-scan-start',
title => 'Batch scan start',
index => 63,
'desc' => 'set for first scan of batch',
type => SANE_TYPE_BOOL,
constraint_type => SANE_CONSTRAINT_NONE,
'unit' => SANE_UNIT_NONE,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
max_values => 1,
},
{
name => 'batch-scan-loop',
title => 'Batch scan loop',
index => 64,
'desc' => 'set for middle scans of batch',
type => SANE_TYPE_BOOL,
constraint_type => SANE_CONSTRAINT_NONE,
'unit' => SANE_UNIT_NONE,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
max_values => 1,
},
{
name => 'batch-scan-end',
title => 'Batch scan end',
index => 65,
'desc' => 'set for last scan of batch',
type => SANE_TYPE_BOOL,
constraint_type => SANE_CONSTRAINT_NONE,
'unit' => SANE_UNIT_NONE,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
max_values => 1,
},
{
name => 'batch-scan-next-tl-y',
title => 'Batch scan next tl y',
index => 66,
'desc' => 'Set top left Y position for next scan',
constraint => {
'min' => 0,
'max' => 297.18,
},
constraint_type => SANE_CONSTRAINT_RANGE,
'unit' => SANE_UNIT_MM,
type => SANE_TYPE_FIXED,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
max_values => 1,
},
{
name => 'preview',
title => 'Preview',
index => 67,
'desc' => 'Request a preview-quality scan.',
'val' => SANE_FALSE,
type => SANE_TYPE_BOOL,
constraint_type => SANE_CONSTRAINT_NONE,
'unit' => SANE_UNIT_NONE,
cap => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
max_values => 1,
},
);
is_deeply( $options->{array}, \@that, 'umax' );
is( Gscan2pdf::Scanner::Options->device, 'umax:/dev/sg2', 'device name' );
gscan2pdf-1.2.3/t/non-utf8.html 0000644 0001750 0001750 00000001450 12053230657 014604 0 ustar jeff jeff
Pe
gscan2pdf-1.2.3/t/121_save_djvu.t 0000644 0001750 0001750 00000002076 12053230657 015003 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 2;
BEGIN {
use_ok('Gscan2pdf::Document');
use Gtk2 -init; # Could just call init separately
}
#########################
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Document->setup($logger);
# Create test image
system('convert rose: test.pnm');
my $slist = Gscan2pdf::Document->new;
# dir for temporary files
my $dir = File::Temp->newdir;
$slist->set_dir($dir);
$slist->get_file_info(
path => 'test.pnm',
finished_callback => sub {
my ($info) = @_;
$slist->import_file(
info => $info,
first => 1,
last => 1,
finished_callback => sub {
$slist->save_djvu(
path => 'test.djvu',
list_of_pages => [ $slist->{data}[0][2] ],
finished_callback => sub { Gtk2->main_quit }
);
}
);
}
);
Gtk2->main;
is( -s 'test.djvu', 1054, 'DjVu created with expected size' );
#########################
unlink 'test.pnm', 'test.djvu';
Gscan2pdf::Document->quit();
gscan2pdf-1.2.3/t/172_open_session.t 0000644 0001750 0001750 00000002566 12270574026 015535 0 ustar jeff jeff use warnings;
use strict;
use File::Basename; # Split filename into dir, file, ext
use Test::More tests => 4;
BEGIN {
use Gscan2pdf::Document;
use Gtk2 -init; # Could just call init separately
}
#########################
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
Gscan2pdf::Document->setup(Log::Log4perl::get_logger);
my $slist = Gscan2pdf::Document->new;
my $dir = File::Temp->newdir;
$slist->set_dir($dir);
$slist->open_session_file('test.gs2p');
like(
`file $slist->{data}[0][2]{filename}`,
qr/PNG image data, 70 x 46, 8-bit\/color RGB, non-interlaced/,
'PNG extracted with expected size'
);
is(
$slist->{data}[0][2]{hocr},
'The quick brown fox',
'Basic OCR output extracted'
);
# Add another image to test behaviour with multiple saves
system('convert rose: test.pnm');
$slist->get_file_info(
path => 'test.pnm',
finished_callback => sub {
my ($info) = @_;
$slist->import_file(
info => $info,
first => 1,
last => 1,
finished_callback => sub {
$slist->save_session('test2.gs2p');
Gtk2->main_quit;
}
);
}
);
Gtk2->main;
is(
`file test2.gs2p`,
"test2.gs2p: gzip compressed data\n",
'Session file created'
);
cmp_ok( -s 'test2.gs2p', '>', 0, 'Non-empty Session file created' );
#########################
Gscan2pdf::Document->quit;
unlink 'test.gs2p', 'test.pnm';
gscan2pdf-1.2.3/t/10_Document.t 0000644 0001750 0001750 00000005271 12271546252 014513 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 22;
use Glib 1.210 qw(TRUE FALSE);
use Gtk2 -init; # Could just call init separately
BEGIN {
use_ok('Gscan2pdf::Document');
}
#########################
Glib::set_application_name('gscan2pdf');
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Document->setup($logger);
my $slist = Gscan2pdf::Document->new;
is( $slist->pages_possible( 1, 1 ),
-1, 'pages_possible infinite forwards in empty document' );
is( $slist->pages_possible( 2, -1 ),
2, 'pages_possible finite backwards in empty document' );
my @selected = $slist->get_page_index( 'all', sub { pass('error in all') } );
is_deeply( \@selected, [], 'no pages' );
@{ $slist->{data} } = ( [ 2, undef, undef ] );
@selected =
$slist->get_page_index( 'selected', sub { pass('error in selected') } );
is_deeply( \@selected, [], 'none selected' );
$slist->select(0);
@selected =
$slist->get_page_index( 'selected', sub { fail('no error in selected') } );
is_deeply( \@selected, [0], 'selected' );
@selected = $slist->get_page_index( 'all', sub { fail('no error in all') } );
is_deeply( \@selected, [0], 'all' );
is( $slist->pages_possible( 2, 1 ), 0,
'pages_possible 0 due to existing page' );
is( $slist->pages_possible( 1, 1 ),
1, 'pages_possible finite forwards in non-empty document' );
is( $slist->pages_possible( 1, -1 ),
1, 'pages_possible finite backwards in non-empty document' );
$slist->{data}[0][0] = 1;
is( $slist->pages_possible( 2, 1 ),
-1, 'pages_possible infinite forwards in non-empty document' );
@{ $slist->{data} } =
( [ 1, undef, undef ], [ 3, undef, undef ], [ 5, undef, undef ] );
is( $slist->pages_possible( 2, 1 ),
1, 'pages_possible finite forwards starting in middle of range' );
is( $slist->pages_possible( 2, -1 ),
1, 'pages_possible finite backwards starting in middle of range' );
is( $slist->pages_possible( 6, -2 ),
3, 'pages_possible finite backwards starting at end of range' );
#########################
is( $slist->valid_renumber( 1, 1, 'all' ), TRUE, 'valid_renumber all step 1' );
is( $slist->valid_renumber( 3, -1, 'all' ),
TRUE, 'valid_renumber all start 3 step -1' );
is( $slist->valid_renumber( 2, -1, 'all' ),
FALSE, 'valid_renumber all start 2 step -1' );
$slist->select(0);
is( $slist->valid_renumber( 1, 1, 'selected' ),
TRUE, 'valid_renumber selected ok' );
is( $slist->valid_renumber( 3, 1, 'selected' ),
FALSE, 'valid_renumber selected nok' );
#########################
$slist->renumber( 1, 1, 'all' );
is_deeply(
$slist->{data},
[ [ 1, undef, undef ], [ 2, undef, undef ], [ 3, undef, undef ] ],
'renumber start 1 step 1'
);
#########################
Gscan2pdf::Document->quit();
__END__
gscan2pdf-1.2.3/t/124_cancel_save_djvu.t 0000644 0001750 0001750 00000002472 12270574026 016315 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 1;
BEGIN {
use Gscan2pdf::Document;
use Gtk2 -init; # Could just call init separately
}
#########################
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Document->setup($logger);
# Create test image
system('convert rose: test.pnm');
my $slist = Gscan2pdf::Document->new;
# dir for temporary files
my $dir = File::Temp->newdir;
$slist->set_dir($dir);
$slist->get_file_info(
path => 'test.pnm',
finished_callback => sub {
my ($info) = @_;
$slist->import_file(
info => $info,
first => 1,
last => 1,
finished_callback => sub {
my $pid = $slist->save_djvu(
path => 'test.djvu',
list_of_pages => [ $slist->{data}[0][2] ],
cancelled_callback => sub {
$slist->save_image(
path => 'test.jpg',
list_of_pages => [ $slist->{data}[0][2] ],
finished_callback => sub { Gtk2->main_quit }
);
}
);
$slist->cancel($pid);
}
);
}
);
Gtk2->main;
is( system('identify test.jpg'),
0, 'can create a valid JPG after cancelling save DjVu process' );
#########################
unlink 'test.pnm', 'test.djvu', 'test.jpg';
Gscan2pdf::Document->quit();
gscan2pdf-1.2.3/t/32_ocropus_in_thread.t 0000644 0001750 0001750 00000003103 12053230657 016435 0 ustar jeff jeff use warnings;
use strict;
use File::Basename; # Split filename into dir, file, ext
use Test::More tests => 3;
BEGIN {
use Gscan2pdf::Document;
use_ok('Gscan2pdf::Ocropus');
}
#########################
# Insert your test code below, the Test::More module is use()ed here so read
# its man page ( perldoc Test::More ) for help writing this test script.
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Document->setup($logger);
SKIP: {
skip 'Ocropus not installed', 2 unless Gscan2pdf::Ocropus->setup($logger);
# Create test image
system(
'convert +matte -depth 1 -pointsize 12 -density 300 label:"The quick brown fox" test.png'
);
my $slist = Gscan2pdf::Document->new;
# dir for temporary files
my $dir = File::Temp->newdir;
$slist->set_dir($dir);
$slist->get_file_info(
path => 'test.png',
finished_callback => sub {
my ($info) = @_;
$slist->import_file(
info => $info,
first => 1,
last => 1,
finished_callback => sub {
$slist->ocropus(
page => $slist->{data}[0][2],
language => 'eng',
finished_callback => sub {
like(
$slist->{data}[0][2]{hocr},
qr/The quick brown fox/,
'Ocropus returned sensible text'
);
is( dirname("$slist->{data}[0][2]{filename}"),
"$dir", 'using session directory' );
Gtk2->main_quit;
}
);
}
);
}
);
Gtk2->main;
unlink 'test.png', <$dir/*>;
rmdir $dir;
}
Gscan2pdf::Document->quit();
gscan2pdf-1.2.3/t/169_import_multipage_PDF2.t 0000644 0001750 0001750 00000003545 12237446416 017175 0 ustar jeff jeff use warnings;
use strict;
use File::Temp;
use Test::More tests => 1;
BEGIN {
use Gscan2pdf::Document;
use Gtk2 -init; # Could just call init separately
}
#########################
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Document->setup($logger);
# Create test image
system('convert rose: page1.pdf');
my $content = <<'EOS';
%PDF-1.4
1 0 obj
<< /Type /Catalog
/Outlines 2 0 R
/Pages 3 0 R
>>
endobj
2 0 obj
<< /Type /Outlines
/Count 0
>>
endobj
3 0 obj
<< /Type /Pages
/Kids [ 4 0 R ]
/Count 1
>>
endobj
4 0 obj
<< /Type /Page
/Parent 3 0 R
/MediaBox [ 0 0 612 792 ]
/Contents 5 0 R
/Resources << /ProcSet 6 0 R
/Font << /F1 7 0 R >>
>>
>>
endobj
5 0 obj
<< /Length 73 >>
stream
BT
/F1 24 Tf
100 100 Td
( Hello World ) Tj
ET
endstream
endobj
xref
0 8
0000000000 65535 f
0000000010 00000 n
0000000020 00000 n
0000000030 00000 n
0000000040 00000 n
0000000050 00000 n
0000000060 00000 n
0000000070 00000 n
trailer
<>
startxref
555
%%EOF
EOS
open my $fh, '>', 'page2.pdf' or die 'Cannot open page2.pdf';
print $fh $content;
close $fh;
system('pdftk page1.pdf page2.pdf cat output test.pdf');
my $slist = Gscan2pdf::Document->new;
# dir for temporary files
my $dir = File::Temp->newdir;
$slist->set_dir($dir);
$slist->get_file_info(
path => 'test.pdf',
finished_callback => sub {
my ($info) = @_;
$slist->import_file(
info => $info,
first => 1,
last => 2,
finished_callback => sub {
is( $#{ $slist->{data} }, 0, 'imported 1 image' );
Gtk2->main_quit;
}
);
}
);
Gtk2->main;
#########################
unlink 'page1.pdf', 'page2.pdf', 'test.pdf', <$dir/*>;
rmdir $dir;
Gscan2pdf::Document->quit();
gscan2pdf-1.2.3/t/40_gocr.t 0000644 0001750 0001750 00000002647 12237446416 013701 0 ustar jeff jeff use warnings;
use strict;
use Encode;
use Test::More tests => 4;
BEGIN {
use Gscan2pdf::Document;
use Gtk2 -init; # Could just call init separately
}
#########################
SKIP: {
skip 'gocr not installed', 1
unless ( system("which gocr > /dev/null 2> /dev/null") == 0 );
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Document->setup($logger);
# Create test image
system(
'convert +matte -depth 1 -pointsize 12 -density 300 label:"öÖäÄüÜß" test.pnm'
);
my $slist = Gscan2pdf::Document->new;
# dir for temporary files
my $dir = File::Temp->newdir;
$slist->set_dir($dir);
$slist->get_file_info(
path => 'test.pnm',
finished_callback => sub {
my ($info) = @_;
$slist->import_file(
info => $info,
first => 1,
last => 1,
finished_callback => sub {
$slist->gocr(
page => $slist->{data}[0][2],
finished_callback => sub {
is( Encode::is_utf8( $slist->{data}[0][2]{hocr}, 1 ),
1, "gocr returned UTF8" );
for my $c (qw( ö ä ü )) { # ignoring ß, as gocr doesn't recognise it
my $c2 = decode_utf8($c);
like( $slist->{data}[0][2]{hocr}, qr/$c2/, "gocr returned $c" );
}
Gtk2->main_quit;
}
);
}
);
}
);
Gtk2->main;
unlink 'test.pnm';
Gscan2pdf::Document->quit();
}
gscan2pdf-1.2.3/t/164_import_multiple_images.t 0000644 0001750 0001750 00000002022 12270574026 017567 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 1;
BEGIN {
use Gscan2pdf::Document;
use Gtk2 -init; # Could just call init separately
use File::Copy;
}
#########################
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Document->setup($logger);
# Create test image
system('convert rose: 1.tif');
my $slist = Gscan2pdf::Document->new;
# dir for temporary files
my $dir = File::Temp->newdir;
$slist->set_dir($dir);
for my $i ( 1 .. 10 ) {
copy( '1.tif', "$i.tif" ) if ( $i > 1 );
$slist->get_file_info(
path => "$i.tif",
finished_callback => sub {
my ($info) = @_;
$slist->import_file(
info => $info,
first => 1,
last => 1,
finished_callback => sub {
Gtk2->main_quit if ( $i == 10 );
}
);
}
);
}
Gtk2->main;
is( $#{ $slist->{data} }, 9, 'Imported 10 images' );
#########################
for my $i ( 1 .. 10 ) {
unlink "$i.tif";
}
Gscan2pdf::Document->quit();
gscan2pdf-1.2.3/t/perlcriticrc 0000644 0001750 0001750 00000000152 12053230657 014646 0 ustar jeff jeff severity = 3
[RegularExpressions::RequireExtendedFormatting]
minimum_regex_length_to_complain_about = 3
gscan2pdf-1.2.3/t/112_save_pdf_with_text.t 0000644 0001750 0001750 00000002224 12270574026 016700 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 1;
BEGIN {
use Gscan2pdf::Document;
use Gtk2 -init; # Could just call init separately
use PDF::API2;
}
#########################
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Document->setup($logger);
# Create test image
system('convert rose: test.pnm');
my $slist = Gscan2pdf::Document->new;
# dir for temporary files
my $dir = File::Temp->newdir;
$slist->set_dir($dir);
$slist->get_file_info(
path => 'test.pnm',
finished_callback => sub {
my ($info) = @_;
$slist->import_file(
info => $info,
first => 1,
last => 1,
finished_callback => sub {
$slist->{data}[0][2]{hocr} = 'The quick brown fox';
$slist->save_pdf(
path => 'test.pdf',
list_of_pages => [ $slist->{data}[0][2] ],
finished_callback => sub { Gtk2->main_quit }
);
}
);
}
);
Gtk2->main;
like(
`pdftotext test.pdf -`,
qr/The quick brown fox/,
'PDF with expected text'
);
#########################
unlink 'test.pnm', 'test.pdf';
Gscan2pdf::Document->quit();
gscan2pdf-1.2.3/t/25_negate.t 0000644 0001750 0001750 00000002516 12053230657 014202 0 ustar jeff jeff use warnings;
use strict;
use File::Basename; # Split filename into dir, file, ext
use Test::More tests => 3;
BEGIN {
use_ok('Gscan2pdf::Document');
use Gtk2 -init; # Could just call init separately
}
#########################
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Document->setup($logger);
# Create test image
system('convert xc:white white.pnm');
my $slist = Gscan2pdf::Document->new;
# dir for temporary files
my $dir = File::Temp->newdir;
$slist->set_dir($dir);
$slist->get_file_info(
path => 'white.pnm',
finished_callback => sub {
my ($info) = @_;
$slist->import_file(
info => $info,
first => 1,
last => 1,
finished_callback => sub {
$slist->negate(
page => $slist->{data}[0][2],
finished_callback => sub {
$slist->analyse(
page => $slist->{data}[0][2],
finished_callback => sub {
is( $slist->{data}[0][2]{mean}, 0, 'Found dark page' );
is( dirname("$slist->{data}[0][2]{filename}"),
"$dir", 'using session directory' );
Gtk2->main_quit;
}
);
}
);
}
);
}
);
Gtk2->main;
#########################
unlink 'white.pnm', <$dir/*>;
rmdir $dir;
Gscan2pdf::Document->quit();
gscan2pdf-1.2.3/t/168_import_multipage_PDF.t 0000644 0001750 0001750 00000002047 12237446416 017106 0 ustar jeff jeff use warnings;
use strict;
use File::Temp;
use Test::More tests => 1;
BEGIN {
use Gscan2pdf::Document;
use Gtk2 -init; # Could just call init separately
}
#########################
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Document->setup($logger);
# Create test image
system('convert rose: test.tif');
system('tiffcp test.tif test.tif test2.tif');
system('tiff2pdf -o test2.pdf test2.tif');
my $slist = Gscan2pdf::Document->new;
# dir for temporary files
my $dir = File::Temp->newdir;
$slist->set_dir($dir);
$slist->get_file_info(
path => 'test2.pdf',
finished_callback => sub {
my ($info) = @_;
$slist->import_file(
info => $info,
first => 1,
last => 2,
finished_callback => sub {
is( $#{ $slist->{data} }, 1, 'imported 2 images' );
Gtk2->main_quit;
}
);
}
);
Gtk2->main;
#########################
unlink 'test.tif', 'test2.tif', 'test2.pdf', <$dir/*>;
rmdir $dir;
Gscan2pdf::Document->quit();
gscan2pdf-1.2.3/t/113_save_pdf_with_hocr.t 0000644 0001750 0001750 00000003335 12270574026 016654 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 1;
BEGIN {
use Gscan2pdf::Document;
use Gtk2 -init; # Could just call init separately
use PDF::API2;
}
#########################
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Document->setup($logger);
# Create test image
system('convert rose: test.pnm');
my $slist = Gscan2pdf::Document->new;
# dir for temporary files
my $dir = File::Temp->newdir;
$slist->set_dir($dir);
$slist->get_file_info(
path => 'test.pnm',
finished_callback => sub {
my ($info) = @_;
$slist->import_file(
info => $info,
first => 1,
last => 1,
finished_callback => sub {
$slist->{data}[0][2]{hocr} = <OCR Output
The quick brown fox
EOS
$slist->save_pdf(
path => 'test.pdf',
list_of_pages => [ $slist->{data}[0][2] ],
finished_callback => sub { Gtk2->main_quit }
);
}
);
}
);
Gtk2->main;
like(
`pdftotext test.pdf -`,
qr/The quick brown fox/,
'PDF with expected text'
);
#########################
unlink 'test.pnm', 'test.pdf';
Gscan2pdf::Document->quit();
gscan2pdf-1.2.3/t/068_Dialog_Scan_CLI.t 0000644 0001750 0001750 00000005741 12237446454 015673 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 10;
use Glib qw(TRUE FALSE); # To get TRUE and FALSE
use Gtk2 -init; # Could just call init separately
BEGIN {
use_ok('Gscan2pdf::Dialog::Scan::CLI');
}
#########################
my $window = Gtk2::Window->new;
Glib::set_application_name('gscan2pdf');
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Frontend::CLI->setup($logger);
ok(
my $dialog = Gscan2pdf::Dialog::Scan::CLI->new(
title => 'title',
'transient-for' => $window,
'logger' => $logger,
'reload-triggers' => qw(mode),
),
'Created dialog'
);
isa_ok( $dialog, 'Gscan2pdf::Dialog::Scan::CLI' );
$dialog->set( 'cache-options', TRUE );
$dialog->signal_connect(
'process-error' => sub {
my ( $widget, $process, $msg ) = @_;
Gtk2->main_quit;
}
);
my ( $signal, $signal2 );
$signal = $dialog->signal_connect(
'changed-options-cache' => sub {
$dialog->signal_handler_disconnect($signal);
is( $#{ $dialog->get('current-scan-options') },
-1, 'cached default Gray - no scan option set' );
$signal = $dialog->signal_connect(
'reloaded-scan-options' => sub {
$dialog->signal_handler_disconnect($signal);
$signal = $dialog->signal_connect(
'changed-scan-option' => sub {
my ( $widget, $option, $value ) = @_;
$dialog->signal_handler_disconnect($signal);
is( $option, 'source', 'setting source' );
is(
$value,
'Automatic Document Feeder',
'setting source to Automatic Document Feeder'
);
$signal = $dialog->signal_connect(
'reloaded-scan-options' => sub {
$dialog->signal_handler_disconnect($signal);
my $options = $dialog->get('available-scan-options');
is( $options->by_name('mode')->{val}, 'Color', 'set mode to Color' );
is(
$options->by_name('source')->{val},
'Automatic Document Feeder',
'source still Automatic Document Feeder'
);
$signal = $dialog->signal_connect(
'reloaded-scan-options' => sub {
$dialog->signal_handler_disconnect($signal);
my $options = $dialog->get('available-scan-options');
is( $options->by_name('mode')->{val}, 'Gray', 'set mode to Gray' );
is(
$options->by_name('source')->{val},
'Automatic Document Feeder',
'source still Automatic Document Feeder'
);
Gtk2->main_quit;
}
);
$dialog->set_option(
$dialog->get('available-scan-options')->by_name('mode'), 'Gray' );
}
);
$dialog->set_option(
$dialog->get('available-scan-options')->by_name('mode'), 'Color' );
}
);
$dialog->set_option(
$dialog->get('available-scan-options')->by_name('source'),
'Automatic Document Feeder' );
}
);
}
);
$dialog->set( 'device-list', [ { 'name' => 'test' } ] );
$dialog->set( 'device', 'test' );
Gtk2->main;
#########################
__END__
gscan2pdf-1.2.3/t/33_cuneiform.t 0000644 0001750 0001750 00000001733 12105700644 014721 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 6;
BEGIN {
use_ok('Gscan2pdf::Cuneiform');
use Encode;
}
#########################
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
SKIP: {
skip 'Cuneiform not installed', 5 unless Gscan2pdf::Cuneiform->setup($logger);
# Create test image
system(
'convert +matte -depth 1 -pointsize 12 -density 300 label:"The quick brown fox" test.png'
);
my $got = Gscan2pdf::Cuneiform->hocr( 'test.png', 'eng', $logger );
like( $got, qr/The quick brown fox/, 'Cuneiform returned sensible text' );
# Create test image
system(
"convert +matte -depth 1 -pointsize 12 -density 300 label:'öÖäÄüÜß' test.png"
);
$got = Gscan2pdf::Cuneiform->hocr( 'test.png', 'ger', $logger );
is( Encode::is_utf8( $got, 1 ), 1, "Cuneiform returned UTF8" );
for my $c (qw( ö ä ü )) {
my $c2 = decode_utf8($c);
like( $got, qr/$c2/, "Cuneiform returned $c" );
}
unlink 'test.png';
}
gscan2pdf-1.2.3/t/02_Scanner_Options_hp_scanjet5300c.t 0000644 0001750 0001750 00000024005 12271200642 020675 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 3;
use Sane 0.05; # For enums
BEGIN { use_ok('Gscan2pdf::Scanner::Options') }
#########################
my $filename = 'scanners/hp_scanjet5300c';
my $output = do { local ( @ARGV, $/ ) = $filename; <> };
my $options = Gscan2pdf::Scanner::Options->new_from_data($output);
my @that = (
{
'index' => 0,
},
{
index => 1,
title => 'Scan mode',
'cap' => 0,
'max_values' => 0,
'name' => '',
'unit' => SANE_UNIT_NONE,
'desc' => '',
type => SANE_TYPE_GROUP,
'constraint_type' => SANE_CONSTRAINT_NONE
},
{
name => 'mode',
title => 'Mode',
index => 2,
'desc' => 'Selects the scan mode (e.g., lineart, monochrome, or color).',
'val' => 'Color',
'constraint' =>
[ 'Lineart', 'Dithered', 'Gray', '12bit Gray', 'Color', '12bit Color' ],
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_STRING_LIST,
type => SANE_TYPE_STRING,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'resolution',
title => 'Resolution',
index => 3,
'desc' => 'Sets the resolution of the scanned image.',
'val' => '150',
constraint => {
'min' => 100,
'max' => 1200,
'quant' => 5,
},
'unit' => SANE_UNIT_DPI,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'speed',
title => 'Speed',
index => 4,
'desc' => 'Determines the speed at which the scan proceeds.',
'val' => '0',
constraint => {
'min' => 0,
'max' => 4,
'quant' => 1,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'preview',
title => 'Preview',
index => 5,
'desc' => 'Request a preview-quality scan.',
'val' => SANE_FALSE,
'unit' => SANE_UNIT_NONE,
'type' => SANE_TYPE_BOOL,
'constraint_type' => SANE_CONSTRAINT_NONE,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'source',
title => 'Source',
index => 6,
'desc' => 'Selects the scan source (such as a document-feeder).',
'val' => 'Normal',
'constraint' => [ 'Normal', 'ADF' ],
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_STRING_LIST,
type => SANE_TYPE_STRING,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
index => 7,
title => 'Geometry',
'cap' => 0,
'max_values' => 0,
'name' => '',
'unit' => SANE_UNIT_NONE,
'desc' => '',
type => SANE_TYPE_GROUP,
'constraint_type' => SANE_CONSTRAINT_NONE
},
{
name => 'l',
title => 'Top-left x',
index => 8,
'desc' => 'Top-left x position of scan area.',
'val' => 0,
constraint => {
'min' => 0,
'max' => 216,
},
'unit' => SANE_UNIT_MM,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 't',
title => 'Top-left y',
index => 9,
'desc' => 'Top-left y position of scan area.',
'val' => 0,
constraint => {
'min' => 0,
'max' => 296,
},
'unit' => SANE_UNIT_MM,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'x',
title => 'Width',
index => 10,
'desc' => 'Width of scan-area.',
'val' => 216,
constraint => {
'min' => 0,
'max' => 216,
},
'unit' => SANE_UNIT_MM,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'y',
title => 'Height',
index => 11,
'desc' => 'Height of scan-area.',
'val' => 296,
constraint => {
'min' => 0,
'max' => 296,
},
'unit' => SANE_UNIT_MM,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
index => 12,
title => 'Enhancement',
'cap' => 0,
'max_values' => 0,
'name' => '',
'unit' => SANE_UNIT_NONE,
'desc' => '',
type => SANE_TYPE_GROUP,
'constraint_type' => SANE_CONSTRAINT_NONE
},
{
name => 'brightness',
title => 'Brightness',
index => 13,
'desc' => 'Controls the brightness of the acquired image.',
'val' => '0',
constraint => {
'min' => -100,
'max' => 100,
'quant' => 1,
},
'unit' => SANE_UNIT_PERCENT,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'contrast',
title => 'Contrast',
index => 14,
'desc' => 'Controls the contrast of the acquired image.',
'val' => '0',
constraint => {
'min' => -100,
'max' => 100,
'quant' => 1,
},
'unit' => SANE_UNIT_PERCENT,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'quality-scan',
title => 'Quality scan',
index => 15,
'desc' => 'Turn on quality scanning (slower but better).',
'val' => SANE_TRUE,
'unit' => SANE_UNIT_NONE,
'type' => SANE_TYPE_BOOL,
'constraint_type' => SANE_CONSTRAINT_NONE,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'quality-cal',
title => 'Quality cal',
index => 16,
'desc' => 'Do a quality white-calibration',
'val' => SANE_TRUE,
'unit' => SANE_UNIT_NONE,
'type' => SANE_TYPE_BOOL,
'constraint_type' => SANE_CONSTRAINT_NONE,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'gamma-table',
title => 'Gamma table',
index => 17,
'desc' =>
'Gamma-correction table. In color mode this option equally affects the red, green, and blue channels simultaneously (i.e., it is an intensity gamma table).',
constraint => {
'min' => 0,
'max' => 255,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 255,
},
{
name => 'red-gamma-table',
title => 'Red gamma table',
index => 18,
'desc' => 'Gamma-correction table for the red band.',
constraint => {
'min' => 0,
'max' => 255,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
'max_values' => 255,
},
{
name => 'green-gamma-table',
title => 'Green gamma table',
index => 19,
'desc' => 'Gamma-correction table for the green band.',
constraint => {
'min' => 0,
'max' => 255,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
'max_values' => 255,
},
{
name => 'blue-gamma-table',
title => 'Blue gamma table',
index => 20,
'desc' => 'Gamma-correction table for the blue band.',
constraint => {
'min' => 0,
'max' => 255,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
'max_values' => 255,
},
{
name => 'frame',
title => 'Frame',
index => 21,
'desc' => 'Selects the number of the frame to scan',
constraint => {
'min' => 0,
'max' => 0,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
'max_values' => 1,
},
{
name => 'power-save-time',
title => 'Power save time',
index => 22,
'desc' =>
'Allows control of the scanner\'s power save timer, dimming or turning off the light.',
'val' => '65535',
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_NONE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'nvram-values',
title => 'Nvram values',
index => 23,
'desc' =>
'Allows access obtaining the scanner\'s NVRAM values as pretty printed text.',
'val' =>
"Vendor: HP \nModel: ScanJet 5300C \nFirmware: 4.00\nSerial: 3119ME\nManufacturing date: 0-0-0\nFirst scan date: 65535-0-0\nFlatbed scans: 65547\nPad scans: -65536\nADF simplex scans: 136183808",
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_NONE,
type => SANE_TYPE_STRING,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
);
is_deeply( $options->{array}, \@that, 'hp_scanjet5300c' );
is( Gscan2pdf::Scanner::Options->device,
'avision:libusb:001:005', 'device name' );
gscan2pdf-1.2.3/t/39_gocr.t 0000644 0001750 0001750 00000002375 12237446416 013707 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 1;
BEGIN {
use Gscan2pdf::Document;
use Gtk2 -init; # Could just call init separately
}
#########################
SKIP: {
skip 'gocr not installed', 1
unless ( system("which gocr > /dev/null 2> /dev/null") == 0 );
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Document->setup($logger);
# Create test image
system(
'convert +matte -depth 1 -pointsize 12 -density 300 label:"The quick brown fox" test.pnm'
);
my $slist = Gscan2pdf::Document->new;
# dir for temporary files
my $dir = File::Temp->newdir;
$slist->set_dir($dir);
$slist->get_file_info(
path => 'test.pnm',
finished_callback => sub {
my ($info) = @_;
$slist->import_file(
info => $info,
first => 1,
last => 1,
finished_callback => sub {
$slist->gocr(
page => $slist->{data}[0][2],
finished_callback => sub {
like(
$slist->{data}[0][2]{hocr},
qr/The quick brown fox/,
'gocr returned sensible text'
);
Gtk2->main_quit;
}
);
}
);
}
);
Gtk2->main;
unlink 'test.pnm';
Gscan2pdf::Document->quit();
}
gscan2pdf-1.2.3/t/115_save_pdf_with_utf8.t 0000644 0001750 0001750 00000002632 12053230657 016606 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 1;
BEGIN {
use Gscan2pdf::Document;
use Gtk2 -init; # Could just call init separately
use PDF::API2;
}
#########################
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Document->setup($logger);
# Create test image
system('convert rose: test.pnm');
my %options;
$options{font} = `fc-list : file | grep times.ttf | head -n 1`;
chomp $options{font};
$options{font} =~ s/: $//;
my $slist = Gscan2pdf::Document->new;
# dir for temporary files
my $dir = File::Temp->newdir;
$slist->set_dir($dir);
$slist->get_file_info(
path => 'test.pnm',
finished_callback => sub {
my ($info) = @_;
$slist->import_file(
info => $info,
first => 1,
last => 1,
finished_callback => sub {
use utf8;
$slist->{data}[0][2]{hocr} =
'пени способствовала сохранению';
$slist->save_pdf(
path => 'test.pdf',
list_of_pages => [ $slist->{data}[0][2] ],
options => \%options,
finished_callback => sub { Gtk2->main_quit }
);
}
);
}
);
Gtk2->main;
like(
`pdftotext test.pdf -`,
qr/пени способствовала сохранению/,
'PDF with expected text'
);
#########################
unlink 'test.pnm', 'test.pdf';
Gscan2pdf::Document->quit();
gscan2pdf-1.2.3/t/02_Scanner_Options_libsane-perl.t 0000644 0001750 0001750 00000016414 12270574026 020477 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 17;
BEGIN { use_ok('Gscan2pdf::Scanner::Options') }
#########################
my $data = [
{
'cap' => '0',
'unit' => '0',
'max_values' => '0',
'desc' => '',
'name' => '',
'title' => 'Geometry',
'type' => '5',
'constraint_type' => '0'
},
{
'cap' => '5',
'max_values' => '1',
'name' => 'tl-x',
'val' => '0',
'unit' => '3',
'desc' => 'Top-left x position of scan area.',
'constraint' => {
'min' => '0',
'max' => '200',
'quant' => '1'
},
'title' => 'Top-left x',
'type' => '2',
'constraint_type' => '1'
},
{
'cap' => '5',
'max_values' => '1',
'name' => 'tl-y',
'val' => '0',
'unit' => '3',
'desc' => 'Top-left y position of scan area.',
'constraint' => {
'min' => '0',
'max' => '200',
'quant' => '1'
},
'title' => 'Top-left y',
'type' => '2',
'constraint_type' => '1'
},
{
'cap' => '5',
'max_values' => '1',
'name' => 'br-x',
'val' => '80',
'unit' => '3',
'desc' => 'Bottom-right x position of scan area.',
'constraint' => {
'min' => '0',
'max' => '200',
'quant' => '1'
},
'title' => 'Bottom-right x',
'type' => '2',
'constraint_type' => '1'
},
{
'cap' => '5',
'max_values' => '1',
'name' => 'br-y',
'val' => '100',
'unit' => '3',
'desc' => 'Bottom-right y position of scan area.',
'constraint' => {
'min' => '0',
'max' => '200',
'quant' => '1'
},
'title' => 'Bottom-right y',
'type' => '2',
'constraint_type' => '1'
},
{
'cap' => '5',
'max_values' => '1',
'name' => 'page-width',
'val' => '200',
'unit' => '3',
'desc' =>
'Specifies the width of the media. Required for automatic centering of sheet-fed scans.',
'constraint' => {
'min' => '0',
'max' => '300',
'quant' => '1'
},
'title' => 'Page width',
'type' => '2',
'constraint_type' => '1'
},
{
'cap' => '5',
'max_values' => '1',
'name' => 'page-height',
'val' => '200',
'unit' => '3',
'desc' => 'Specifies the height of the media.',
'constraint' => {
'min' => '0',
'max' => '300',
'quant' => '1'
},
'title' => 'Page height',
'type' => '2',
'constraint_type' => '1'
},
];
my $options = Gscan2pdf::Scanner::Options->new_from_data($data);
my @that = (
{
index => 0,
'cap' => '0',
'unit' => '0',
'max_values' => '0',
'desc' => '',
'name' => '',
'title' => 'Geometry',
'type' => '5',
'constraint_type' => '0'
},
{
index => 1,
'cap' => '5',
'max_values' => '1',
'name' => 'tl-x',
'val' => '0',
'unit' => '3',
'desc' => 'Top-left x position of scan area.',
'constraint' => {
'min' => '0',
'max' => '200',
'quant' => '1'
},
'title' => 'Top-left x',
'type' => '2',
'constraint_type' => '1'
},
{
index => 2,
'cap' => '5',
'max_values' => '1',
'name' => 'tl-y',
'val' => '0',
'unit' => '3',
'desc' => 'Top-left y position of scan area.',
'constraint' => {
'min' => '0',
'max' => '200',
'quant' => '1'
},
'title' => 'Top-left y',
'type' => '2',
'constraint_type' => '1'
},
{
index => 3,
'cap' => '5',
'max_values' => '1',
'name' => 'br-x',
'val' => '80',
'unit' => '3',
'desc' => 'Bottom-right x position of scan area.',
'constraint' => {
'min' => '0',
'max' => '200',
'quant' => '1'
},
'title' => 'Bottom-right x',
'type' => '2',
'constraint_type' => '1'
},
{
index => 4,
'cap' => '5',
'max_values' => '1',
'name' => 'br-y',
'val' => '100',
'unit' => '3',
'desc' => 'Bottom-right y position of scan area.',
'constraint' => {
'min' => '0',
'max' => '200',
'quant' => '1'
},
'title' => 'Bottom-right y',
'type' => '2',
'constraint_type' => '1'
},
{
index => 5,
'cap' => '5',
'max_values' => '1',
'name' => 'page-width',
'val' => '200',
'unit' => '3',
'desc' =>
'Specifies the width of the media. Required for automatic centering of sheet-fed scans.',
'constraint' => {
'min' => '0',
'max' => '300',
'quant' => '1'
},
'title' => 'Page width',
'type' => '2',
'constraint_type' => '1'
},
{
index => 6,
'cap' => '5',
'max_values' => '1',
'name' => 'page-height',
'val' => '200',
'unit' => '3',
'desc' => 'Specifies the height of the media.',
'constraint' => {
'min' => '0',
'max' => '300',
'quant' => '1'
},
'title' => 'Page height',
'type' => '2',
'constraint_type' => '1'
},
);
is_deeply( $options->{array}, \@that, 'libsane-perl' );
is(
$options->supports_paper(
{
x => 210,
y => 297,
l => 0,
t => 0,
},
0
),
1,
'page-width supports_paper'
);
is(
$options->supports_paper(
{
x => 210,
y => 297,
l => 0,
t => -10,
},
0
),
0,
'page-width paper crosses top border'
);
is(
$options->supports_paper(
{
x => 210,
y => 297,
l => 0,
t => 600,
},
0
),
0,
'page-width paper crosses bottom border'
);
is(
$options->supports_paper(
{
x => 210,
y => 297,
l => -10,
t => 0,
},
0
),
0,
'page-width paper crosses left border'
);
is(
$options->supports_paper(
{
x => 210,
y => 297,
l => 100,
t => 0,
},
0
),
0,
'page-width paper crosses right border'
);
is(
$options->supports_paper(
{
x => 301,
y => 297,
l => 0,
t => 0,
},
0
),
0,
'page-width paper too wide'
);
is(
$options->supports_paper(
{
x => 210,
y => 870,
l => 0,
t => 0,
},
0
),
0,
'page-width paper too tall'
);
$options->delete_by_name('page-width');
$options->delete_by_name('page-height');
delete $options->{geometry}{w};
delete $options->{geometry}{h};
is(
$options->supports_paper(
{
x => 200,
y => 200,
l => 0,
t => 0,
},
0
),
1,
'supports_paper'
);
is(
$options->supports_paper(
{
x => 200,
y => 200,
l => 0,
t => -10,
},
0
),
0,
'paper crosses top border'
);
is(
$options->supports_paper(
{
x => 200,
y => 200,
l => 0,
t => 600,
},
0
),
0,
'paper crosses bottom border'
);
is(
$options->supports_paper(
{
x => 200,
y => 200,
l => -10,
t => 0,
},
0
),
0,
'paper crosses left border'
);
is(
$options->supports_paper(
{
x => 200,
y => 200,
l => 100,
t => 0,
},
0
),
0,
'paper crosses right border'
);
is(
$options->supports_paper(
{
x => 201,
y => 200,
l => 0,
t => 0,
},
0
),
0,
'paper too wide'
);
is(
$options->supports_paper(
{
x => 200,
y => 270,
l => 0,
t => 0,
},
0
),
0,
'paper too tall'
);
is( $options->by_name('page-height'), undef, 'by name undefined' );
gscan2pdf-1.2.3/t/46_cancel_negate.t 0000644 0001750 0001750 00000002711 12270574026 015511 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 2;
BEGIN {
use Gscan2pdf::Document;
use Gtk2 -init; # Could just call init separately
}
#########################
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Document->setup($logger);
# Create test image
system('convert xc:white white.pnm');
my $slist = Gscan2pdf::Document->new;
# dir for temporary files
my $dir = File::Temp->newdir;
$slist->set_dir($dir);
$slist->get_file_info(
path => 'white.pnm',
finished_callback => sub {
my ($info) = @_;
$slist->import_file(
info => $info,
first => 1,
last => 1,
finished_callback => sub {
my $md5sum = `md5sum $slist->{data}[0][2]{filename} | cut -c -32`;
my $pid = $slist->negate(
page => $slist->{data}[0][2],
cancelled_callback => sub {
is(
$md5sum,
`md5sum $slist->{data}[0][2]{filename} | cut -c -32`,
'image not modified'
);
$slist->save_image(
path => 'test.jpg',
list_of_pages => [ $slist->{data}[0][2] ],
finished_callback => sub { Gtk2->main_quit }
);
}
);
$slist->cancel($pid);
}
);
}
);
Gtk2->main;
is( system('identify test.jpg'),
0, 'can create a valid JPG after cancelling previous process' );
#########################
unlink 'white.pnm', 'test.jpg';
Gscan2pdf::Document->quit();
gscan2pdf-1.2.3/t/061_Dialog_Scan_Sane.t 0000644 0001750 0001750 00000027741 12270574026 016141 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 45;
use Glib qw(TRUE FALSE); # To get TRUE and FALSE
use Gtk2 -init; # Could just call init separately
use Sane 0.05; # To get SANE_* enums
BEGIN {
use_ok('Gscan2pdf::Dialog::Scan::Sane');
}
#########################
my $window = Gtk2::Window->new;
Glib::set_application_name('gscan2pdf');
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Frontend::Sane->setup($logger);
ok(
my $dialog = Gscan2pdf::Dialog::Scan::Sane->new(
title => 'title',
'transient-for' => $window,
'logger' => $logger
),
'Created dialog'
);
isa_ok( $dialog, 'Gscan2pdf::Dialog::Scan::Sane' );
is( $dialog->get('device'), '', 'device' );
is( $dialog->get('device-list'), undef, 'device-list' );
is( $dialog->get('dir'), undef, 'dir' );
is( $dialog->get('num-pages'), 1, 'num-pages' );
is( $dialog->get('max-pages'), 0, 'max-pages' );
is( $dialog->get('page-number-start'), 1, 'page-number-start' );
is( $dialog->get('page-number-increment'), 1, 'page-number-increment' );
is( $dialog->get('side-to-scan'), 'facing', 'side-to-scan' );
is( $dialog->get('available-scan-options'), undef, 'available-scan-options' );
$dialog->{signal} = $dialog->signal_connect(
'changed-num-pages' => sub {
my ( $widget, $n, $signal ) = @_;
$dialog->signal_handler_disconnect( $dialog->{signal} );
is( $n, 0, 'changed-num-pages' );
}
);
$dialog->set( 'num-pages', 0 );
$dialog->{signal} = $dialog->signal_connect(
'changed-page-number-start' => sub {
my ( $widget, $n ) = @_;
$dialog->signal_handler_disconnect( $dialog->{signal} );
is( $n, 2, 'changed-page-number-start' );
}
);
$dialog->set( 'page-number-start', 2 );
$dialog->{signal} = $dialog->signal_connect(
'changed-page-number-increment' => sub {
my ( $widget, $n ) = @_;
$dialog->signal_handler_disconnect( $dialog->{signal} );
is( $n, 2, 'changed-page-number-increment' );
$dialog->{signal} = $dialog->signal_connect(
'changed-side-to-scan' => sub {
my ( $widget, $side ) = @_;
$dialog->signal_handler_disconnect( $dialog->{signal} );
is( $side, 'reverse', 'changed-side-to-scan' );
is( $dialog->get('page-number-increment'),
-2, 'reverse side gives increment -2' );
}
);
$dialog->set( 'side-to-scan', 'reverse' );
}
);
$dialog->set( 'page-number-increment', 2 );
$dialog->{reloaded_signal} = $dialog->signal_connect(
'reloaded-scan-options' => sub {
$dialog->signal_handler_disconnect( $dialog->{reloaded_signal} );
ok( 1, 'reloaded-scan-options' );
# So that it can be used in hash
my $resolution = SANE_NAME_SCAN_RESOLUTION;
$dialog->{signal} = $dialog->signal_connect(
'added-profile' => sub {
my ( $widget, $name, $profile ) = @_;
$dialog->signal_handler_disconnect( $dialog->{signal} );
is( $name, 'my profile', 'added-profile name' );
is_deeply(
$profile,
[ { $resolution => 52 }, { mode => 'Color' } ],
'added-profile profile'
);
}
);
$dialog->add_profile( 'my profile',
[ { $resolution => 52 }, { mode => 'Color' } ] );
######################################
$dialog->{signal} = $dialog->signal_connect(
'added-profile' => sub {
my ( $widget, $name, $profile ) = @_;
$dialog->signal_handler_disconnect( $dialog->{signal} );
is( $name, 'old profile', 'added-profile old name' );
is_deeply(
$profile,
[ { mode => 'Gray' }, { $resolution => 51 } ],
'added-profile profile as hash'
);
}
);
$dialog->add_profile( 'old profile', { $resolution => 51, mode => 'Gray' } );
######################################
$dialog->signal_connect(
'removed-profile' => sub {
my ( $widget, $profile ) = @_;
is( $profile, 'old profile', 'removed-profile' );
}
);
$dialog->remove_profile('old profile');
######################################
# need a new main loop because of the timeout
my $loop = Glib::MainLoop->new;
my $flag = FALSE;
$dialog->{signal} = $dialog->signal_connect(
'changed-profile' => sub {
my ( $widget, $profile ) = @_;
$dialog->signal_handler_disconnect( $dialog->{signal} );
is( $profile, 'my profile', 'changed-profile' );
is_deeply(
$dialog->get('current-scan-options'),
[ { $resolution => 52 }, { mode => 'Color' } ],
'current-scan-options with profile'
);
$flag = TRUE;
$loop->quit;
}
);
$dialog->set( 'profile', 'my profile' );
$loop->run unless ($flag);
######################################
$dialog->add_profile( 'my profile2',
[ { $resolution => 52 }, { mode => 'Color' } ] );
# need a new main loop because of the timeout
$loop = Glib::MainLoop->new;
$flag = FALSE;
$dialog->{signal} = $dialog->signal_connect(
'changed-profile' => sub {
my ( $widget, $profile ) = @_;
$dialog->signal_handler_disconnect( $dialog->{signal} );
is( $profile, 'my profile2', 'set profile with identical options' );
$flag = TRUE;
$loop->quit;
}
);
$dialog->set( 'profile', 'my profile2' );
$loop->run unless ($flag);
######################################
# need a new main loop because of the timeout
$loop = Glib::MainLoop->new;
$flag = FALSE;
$dialog->{signal} = $dialog->signal_connect(
'changed-scan-option' => sub {
my ( $widget, $option, $value ) = @_;
$dialog->signal_handler_disconnect( $dialog->{signal} );
is( $dialog->get('profile'),
undef, 'changing an option deselects the current profile' );
is_deeply(
$dialog->get('current-scan-options'),
[ { mode => 'Color' }, { $resolution => 51 } ],
'current-scan-options without profile'
);
$flag = TRUE;
$loop->quit;
}
);
my $options = $dialog->get('available-scan-options');
$dialog->set_option( $options->by_name($resolution), 51 );
$loop->run unless ($flag);
my @geometry_widgets = keys %{ $options->{box} };
cmp_ok(
$#geometry_widgets == 3,
'||',
$#geometry_widgets == 5,
'Only 4 or 6 options should be flagged as geometry'
);
######################################
# need a new main loop because of the timeout
$loop = Glib::MainLoop->new;
$flag = FALSE;
# Reset profile for next test
$dialog->{signal} = $dialog->signal_connect(
'changed-profile' => sub {
my ( $widget, $profile ) = @_;
$dialog->signal_handler_disconnect( $dialog->{signal} );
is( $profile, 'my profile', 'reset profile' );
$flag = TRUE;
$loop->quit;
}
);
$dialog->set( 'profile', 'my profile' );
$loop->run unless ($flag);
######################################
# need a new main loop because of the timeout
$loop = Glib::MainLoop->new;
$flag = FALSE;
$dialog->{signal} = $dialog->signal_connect(
'changed-profile' => sub {
my ( $widget, $profile ) = @_;
$dialog->signal_handler_disconnect( $dialog->{signal} );
is( $profile, undef,
'changing an option fires the changed-profile signal if a profile is set'
);
is_deeply(
$dialog->get('current-scan-options'),
[ { mode => 'Color' }, { $resolution => 51 } ],
'current-scan-options without profile (again)'
);
my $reloaded_options = $dialog->get('available-scan-options');
is( $reloaded_options->by_name($resolution)->{val},
51, 'option value updated when reloaded' );
$flag = TRUE;
$loop->quit;
}
);
$options = $dialog->get('available-scan-options');
$dialog->set_option( $options->by_name($resolution), 51 );
$loop->run unless ($flag);
######################################
$dialog->set(
'paper-formats',
{
new => {
l => 1,
y => 50,
x => 50,
t => 2,
}
}
);
$dialog->add_profile( 'cli geometry',
[ { 'Paper size' => 'new' }, { $resolution => 50 } ] );
# need a new main loop because of the timeout
$loop = Glib::MainLoop->new;
$flag = FALSE;
$dialog->{signal} = $dialog->signal_connect(
'changed-profile' => sub {
my ( $widget, $profile ) = @_;
$dialog->signal_handler_disconnect( $dialog->{signal} );
my $options = $dialog->get('available-scan-options');
my $expected = [ { 'Paper size' => 'new' } ];
push @$expected, { scalar(SANE_NAME_PAGE_HEIGHT) => 52 }
if ( defined $options->by_name(SANE_NAME_PAGE_HEIGHT) );
push @$expected, { scalar(SANE_NAME_PAGE_WIDTH) => 51 }
if ( defined $options->by_name(SANE_NAME_PAGE_WIDTH) );
push @$expected, { scalar(SANE_NAME_SCAN_TL_X) => 1 },
{ scalar(SANE_NAME_SCAN_TL_Y) => 2 },
{ scalar(SANE_NAME_SCAN_BR_X) => 51 },
{ scalar(SANE_NAME_SCAN_BR_Y) => 52 },
{ $resolution => 50 };
is_deeply( $dialog->get('current-scan-options'),
$expected, 'CLI geometry option names' );
$flag = TRUE;
$loop->quit;
}
);
$dialog->set( 'profile', 'cli geometry' );
$loop->run unless ($flag);
######################################
$dialog->signal_connect(
'changed-paper-formats' => sub {
my ( $widget, $formats ) = @_;
ok( 1, 'changed-paper-formats' );
}
);
$dialog->set(
'paper-formats',
{
new2 => {
l => 0,
y => 10,
x => 10,
t => 0,
}
}
);
$dialog->signal_connect(
'changed-paper' => sub {
my ( $widget, $paper ) = @_;
is( $paper, 'new2', 'changed-paper' );
}
);
$dialog->set( 'paper', 'new2' );
my $s_signal;
$s_signal = $dialog->signal_connect(
'started-process' => sub {
$dialog->signal_handler_disconnect($s_signal);
ok( 1, 'started-process' );
}
);
my $c_signal;
$c_signal = $dialog->signal_connect(
'changed-progress' => sub {
$dialog->signal_handler_disconnect($c_signal);
ok( 1, 'changed-progress' );
}
);
my $f_signal;
$f_signal = $dialog->signal_connect(
'finished-process' => sub {
my ( $widget, $process ) = @_;
$dialog->signal_handler_disconnect($f_signal);
is( $process, 'set_option', 'finished-process set_option' );
}
);
my $n;
$dialog->signal_connect(
'new-scan' => sub {
( my $widget, $n ) = @_;
}
);
$dialog->signal_connect(
'finished-process' => sub {
my ( $widget, $process ) = @_;
if ( $process eq 'scan_pages' ) {
is( $n, 1, 'new-scan emitted once' );
# changing device via the combobox should really change the device!
$dialog->{signal} = $dialog->signal_connect(
'changed-device' => sub {
my ( $widget, $name ) = @_;
$dialog->signal_handler_disconnect( $dialog->{signal} );
is( $name, 'test:1', 'changed-device via combobox' );
my $e_signal;
$e_signal = $dialog->signal_connect(
'process-error' => sub {
my ( $widget, $process, $message ) = @_;
$dialog->signal_handler_disconnect($e_signal);
is( $process, 'open_device', 'caught error opening device' );
Gtk2->main_quit;
}
);
# setting an unknown device should throw an error
$dialog->set( 'device', 'error' );
}
);
$dialog->{combobd}->set_active(1);
}
}
);
$dialog->set( 'num-pages', 1 );
$dialog->set( 'page-number-start', 1 );
$dialog->set( 'side-to-scan', 'facing' );
$dialog->scan;
}
);
$dialog->{signal} = $dialog->signal_connect(
'changed-device-list' => sub {
$dialog->signal_handler_disconnect( $dialog->{signal} );
ok( 1, 'changed-device-list' );
is_deeply(
$dialog->get('device-list'),
[
{ 'name' => 'test:0', 'model' => 'test:0', 'label' => 'test:0' },
{ 'name' => 'test:1', 'model' => 'test:1', 'label' => 'test:1' }
],
'add model field if missing'
);
$dialog->{signal} = $dialog->signal_connect(
'changed-device' => sub {
my ( $widget, $name ) = @_;
$dialog->signal_handler_disconnect( $dialog->{signal} );
is( $name, 'test:0', 'changed-device' );
}
);
$dialog->set( 'device', 'test:0' );
}
);
$dialog->set( 'device-list',
[ { 'name' => 'test:0' }, { 'name' => 'test:1' } ] );
Gtk2->main;
Gscan2pdf::Frontend::Sane->quit;
__END__
gscan2pdf-1.2.3/t/52_cancel_cuneiform.t 0000644 0001750 0001750 00000003050 12053230657 016225 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 2;
BEGIN {
use Gscan2pdf::Document;
use Gscan2pdf::Cuneiform;
use Gtk2 -init; # Could just call init separately
}
#########################
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
SKIP: {
skip 'Cuneiform not installed', 2 unless Gscan2pdf::Cuneiform->setup($logger);
Gscan2pdf::Document->setup($logger);
# Create test image
system(
'convert +matte -depth 1 -pointsize 12 -density 300 label:"The quick brown fox" test.png'
);
my $slist = Gscan2pdf::Document->new;
# dir for temporary files
my $dir = File::Temp->newdir;
$slist->set_dir($dir);
$slist->get_file_info(
path => 'test.png',
finished_callback => sub {
my ($info) = @_;
$slist->import_file(
info => $info,
first => 1,
last => 1,
finished_callback => sub {
my $pid = $slist->cuneiform(
page => $slist->{data}[0][2],
language => 'eng',
cancelled_callback => sub {
is( $slist->{data}[0][2]{hocr}, undef, 'no OCR output' );
$slist->save_image(
path => 'test.jpg',
list_of_pages => [ $slist->{data}[0][2] ],
finished_callback => sub { Gtk2->main_quit }
);
}
);
$slist->cancel($pid);
}
);
}
);
Gtk2->main;
is( system('identify test.jpg'),
0, 'can create a valid JPG after cancelling previous process' );
unlink 'test.png', 'test.jpg';
Gscan2pdf::Document->quit();
}
gscan2pdf-1.2.3/t/99_pod.t 0000644 0001750 0001750 00000000233 12053230657 013526 0 ustar jeff jeff use warnings;
use strict;
use Test::More;
eval "use Test::Pod 1.00";
plan skip_all => "Test::Pod 1.00 required for testing POD" if $@;
all_pod_files_ok();
gscan2pdf-1.2.3/t/53_cancel_unpaper.t 0000644 0001750 0001750 00000004137 12270574026 015722 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 2;
BEGIN {
use Gscan2pdf::Document;
use Gscan2pdf::Unpaper;
use Gtk2 -init; # Could just call init separately
}
#########################
SKIP: {
skip 'unpaper not installed', 2
unless ( system("which unpaper > /dev/null 2> /dev/null") == 0 );
my $unpaper =
Gscan2pdf::Unpaper->new( { 'output-pages' => 2, layout => 'double' } );
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Document->setup($logger);
# Create test image
system(
'convert +matte -depth 1 -border 2x2 -bordercolor black -pointsize 12 -density 300 label:"The quick brown fox" 1.pnm'
);
system(
'convert +matte -depth 1 -border 2x2 -bordercolor black -pointsize 12 -density 300 label:"The slower lazy dog" 2.pnm'
);
system('convert -size 100x100 xc:black black.pnm');
system('convert 1.pnm black.pnm 2.pnm +append test.pnm');
my $slist = Gscan2pdf::Document->new;
# dir for temporary files
my $dir = File::Temp->newdir;
$slist->set_dir($dir);
$slist->get_file_info(
path => 'test.pnm',
finished_callback => sub {
my ($info) = @_;
$slist->import_file(
info => $info,
first => 1,
last => 1,
finished_callback => sub {
my $md5sum = `md5sum $slist->{data}[0][2]{filename} | cut -c -32`;
my $pid = $slist->unpaper(
page => $slist->{data}[0][2],
options => $unpaper->get_cmdline,
cancelled_callback => sub {
is(
$md5sum,
`md5sum $slist->{data}[0][2]{filename} | cut -c -32`,
'image not modified'
);
$slist->save_image(
path => 'test.jpg',
list_of_pages => [ $slist->{data}[0][2] ],
finished_callback => sub { Gtk2->main_quit }
);
}
);
$slist->cancel($pid);
}
);
}
);
Gtk2->main;
is( system('identify test.jpg'),
0, 'can create a valid JPG after cancelling previous process' );
unlink 'test.pnm', '1.pnm', '2.pnm', 'black.pnm', 'test.jpg';
Gscan2pdf::Document->quit();
}
gscan2pdf-1.2.3/t/81_scanadf-perl.t 0000644 0001750 0001750 00000000760 12053230657 015277 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 1;
#########################
SKIP: {
skip 'scanadf v1.0.14 not installed', 1
unless ( `scanadf --version` eq "scanadf (sane-frontends) 1.0.14\n" );
my $output = `perl bin/scanadf-perl --device=test --help`;
$output =~ s/scanadf-perl/scanadf/g;
my $example = `scanadf --device=test --help`;
my @output = split( "\n", $output );
my @example = split( "\n", $example );
is_deeply( \@output, \@example, "basic help functionality" );
}
gscan2pdf-1.2.3/t/1111_save_pdf_with_locale.t 0000644 0001750 0001750 00000002244 12053230657 017233 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 1;
use Gtk2 -init; # Could just call init separately
use POSIX qw(locale_h);
BEGIN {
use Gscan2pdf::Document;
use PDF::API2;
}
#########################
setlocale( LC_NUMERIC, "de_DE" );
Glib::set_application_name('gscan2pdf');
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Document->setup($logger);
# Create test image
system('convert rose: test.pnm');
my $slist = Gscan2pdf::Document->new;
# dir for temporary files
my $dir = File::Temp->newdir;
$slist->set_dir($dir);
$slist->get_file_info(
path => 'test.pnm',
finished_callback => sub {
my ($info) = @_;
$slist->import_file(
info => $info,
first => 1,
last => 1,
finished_callback => sub {
$slist->save_pdf(
path => 'test.pdf',
list_of_pages => [ $slist->{data}[0][2] ],
finished_callback => sub { Gtk2->main_quit }
);
}
);
}
);
Gtk2->main;
is( system('identify test.pdf'), 0, 'valid PDF created' );
#########################
unlink 'test.pnm', 'test.pdf';
Gscan2pdf::Document->quit();
gscan2pdf-1.2.3/t/04_Unpaper.t 0000644 0001750 0001750 00000004002 12053230657 014336 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 5;
BEGIN {
use_ok('Gscan2pdf::Unpaper');
use Gtk2 -init; # Could just call init separately
use version;
}
#########################
my $unpaper = Gscan2pdf::Unpaper->new;
my $vbox = Gtk2::VBox->new;
$unpaper->add_options($vbox);
is(
$unpaper->get_cmdline,
'unpaper --output-pages 1 --white-threshold 0.9 --layout single --black-threshold 0.33 --deskew-scan-direction left,right --border-margin 0,0 --overwrite '
. (
version->parse( $unpaper->version ) > version->parse('v0.3')
? '%s %s %s'
: '--input-file-sequence %s --output-file-sequence %s %s'
),
'Basic functionality'
);
$unpaper = Gscan2pdf::Unpaper->new( { layout => 'Double' } );
$unpaper->add_options($vbox);
is(
$unpaper->get_cmdline,
'unpaper --output-pages 1 --white-threshold 0.9 --layout double --black-threshold 0.33 --deskew-scan-direction left,right --border-margin 0,0 --overwrite '
. (
version->parse( $unpaper->version ) > version->parse('v0.3')
? '%s %s %s'
: '--input-file-sequence %s --output-file-sequence %s %s'
),
'Defaults'
);
is_deeply(
$unpaper->get_options,
{
'no-blackfilter' => '',
'output-pages' => '1',
'no-deskew' => '',
'no-border-scan' => '',
'no-noisefilter' => '',
'no-blurfilter' => '',
'white-threshold' => '0.9',
'layout' => 'double',
'no-mask-scan' => '',
'no-grayfilter' => '',
'no-border-align' => '',
'black-threshold' => '0.33',
'deskew-scan-direction' => 'left,right',
'border-margin' => '0,0'
},
'get_options'
);
#########################
$unpaper = Gscan2pdf::Unpaper->new(
{
'white-threshold' => '0.8',
'black-threshold' => '0.35',
},
);
is(
$unpaper->get_cmdline,
'unpaper --white-threshold 0.8 --black-threshold 0.35 --overwrite '
. (
version->parse( $unpaper->version ) > version->parse('v0.3')
? '%s %s %s'
: '--input-file-sequence %s --output-file-sequence %s %s'
),
'no GUI'
);
__END__
gscan2pdf-1.2.3/t/54_cancel_user_defined.t 0000644 0001750 0001750 00000003003 12270574026 016674 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 2;
BEGIN {
use Gscan2pdf::Document;
use Gtk2 -init; # Could just call init separately
}
#########################
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Document->setup($logger);
# Create test image
system('convert xc:white white.pnm');
my $slist = Gscan2pdf::Document->new;
# dir for temporary files
my $dir = File::Temp->newdir;
$slist->set_dir($dir);
$slist->get_file_info(
path => 'white.pnm',
finished_callback => sub {
my ($info) = @_;
$slist->import_file(
info => $info,
first => 1,
last => 1,
finished_callback => sub {
my $md5sum = `md5sum $slist->{data}[0][2]{filename} | cut -c -32`;
my $pid = $slist->user_defined(
page => $slist->{data}[0][2],
command => 'convert %i -negate %o',
cancelled_callback => sub {
is(
$md5sum,
`md5sum $slist->{data}[0][2]{filename} | cut -c -32`,
'image not modified'
);
$slist->save_image(
path => 'test.jpg',
list_of_pages => [ $slist->{data}[0][2] ],
finished_callback => sub { Gtk2->main_quit }
);
}
);
$slist->cancel($pid);
}
);
}
);
Gtk2->main;
is( system('identify test.jpg'),
0, 'can create a valid JPG after cancelling previous process' );
#########################
unlink 'white.pnm', 'test.jpg';
Gscan2pdf::Document->quit();
gscan2pdf-1.2.3/t/36_unpaper2.t 0000644 0001750 0001750 00000003655 12053230657 014502 0 ustar jeff jeff use warnings;
use strict;
use File::Basename; # Split filename into dir, file, ext
use Test::More tests => 3;
BEGIN {
use Gscan2pdf::Document;
use Gscan2pdf::Unpaper;
use Gtk2 -init; # Could just call init separately
}
SKIP: {
skip 'unpaper not installed', 2
unless ( system("which unpaper > /dev/null 2> /dev/null") == 0 );
my $unpaper =
Gscan2pdf::Unpaper->new( { 'output-pages' => 2, layout => 'double' } );
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
Gscan2pdf::Document->setup(Log::Log4perl::get_logger);
# Create test image
system(
'convert +matte -depth 1 -border 2x2 -bordercolor black -pointsize 12 -density 300 label:"The quick brown fox" 1.pnm'
);
system(
'convert +matte -depth 1 -border 2x2 -bordercolor black -pointsize 12 -density 300 label:"The slower lazy dog" 2.pnm'
);
system('convert -size 100x100 xc:black black.pnm');
system('convert 1.pnm black.pnm 2.pnm +append test.pnm');
my $slist = Gscan2pdf::Document->new;
# dir for temporary files
my $dir = File::Temp->newdir;
$slist->set_dir($dir);
$slist->get_file_info(
path => 'test.pnm',
finished_callback => sub {
my ($info) = @_;
$slist->import_file(
info => $info,
first => 1,
last => 1,
finished_callback => sub {
$slist->unpaper(
page => $slist->{data}[0][2],
options => $unpaper->get_cmdline,
finished_callback => sub {
is( system("identify $slist->{data}[0][2]{filename}"),
0, 'valid PNM created for LH' );
is( system("identify $slist->{data}[1][2]{filename}"),
0, 'valid PNM created for RH' );
is( dirname("$slist->{data}[0][2]{filename}"),
"$dir", 'using session directory' );
Gtk2->main_quit;
}
);
}
);
}
);
Gtk2->main;
unlink 'test.pnm', '1.pnm', '2.pnm', 'black.pnm', <$dir/*>;
rmdir $dir;
Gscan2pdf::Document->quit();
}
gscan2pdf-1.2.3/t/374_user_defined.t 0000644 0001750 0001750 00000003713 12237446416 015470 0 ustar jeff jeff use warnings;
use strict;
use File::Basename; # Split filename into dir, file, ext
use Test::More tests => 5;
BEGIN {
use Gscan2pdf::Document;
use Gtk2 -init; # Could just call init separately
}
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
Gscan2pdf::Document->setup(Log::Log4perl::get_logger);
my %paper_sizes = (
A4 => {
x => 210,
y => 297,
l => 0,
t => 0,
},
'US Letter' => {
x => 216,
y => 279,
l => 0,
t => 0,
},
'US Legal' => {
x => 216,
y => 356,
l => 0,
t => 0,
},
);
# Create test image
system('convert -size 210x297 xc:white white.pnm');
my $slist = Gscan2pdf::Document->new;
# dir for temporary files
my $dir = File::Temp->newdir;
$slist->set_dir($dir);
$slist->set_paper_sizes( \%paper_sizes );
$slist->get_file_info(
path => 'white.pnm',
finished_callback => sub {
my ($info) = @_;
$slist->import_file(
info => $info,
first => 1,
last => 1,
finished_callback => sub {
is( int( abs( $slist->{data}[0][2]{resolution} - 25.4 ) ),
0, 'Resolution of imported image' );
$slist->user_defined(
page => $slist->{data}[0][2],
command => 'convert %i tmp.pgm;mv tmp.pgm %i',
finished_callback => sub {
is( int( abs( $slist->{data}[0][2]{resolution} - 25.4 ) ),
0, 'Resolution of converted image' );
my ( $dir, $base, $suffix ) =
fileparse( "$slist->{data}[0][2]{filename}", qr/\.[^.]*/ );
is( $dir, "$dir", 'using session directory' );
is( $suffix, ".pgm", 'still has an extension' );
$slist->save_pdf(
path => 'test.pdf',
list_of_pages => [ $slist->{data}[0][2] ],
finished_callback => sub { Gtk2->main_quit }
);
}
);
}
);
}
);
Gtk2->main;
like( `pdfinfo test.pdf`, qr/A4/, 'PDF is A4' );
#########################
unlink 'white.pnm', 'test.pdf', <$dir/*>;
rmdir $dir;
Gscan2pdf::Document->quit();
gscan2pdf-1.2.3/t/02_Scanner_Options_Brother_DCP-7025.t 0000644 0001750 0001750 00000012222 12271200642 020570 0 ustar jeff jeff use warnings;
use strict;
use Sane 0.05; # For enums
use Test::More tests => 3;
BEGIN { use_ok('Gscan2pdf::Scanner::Options') }
#########################
my $filename = 'scanners/Brother_DCP-7025';
my $output = do { local ( @ARGV, $/ ) = $filename; <> };
my $options = Gscan2pdf::Scanner::Options->new_from_data($output);
my @that = (
{
'index' => 0,
},
{
title => 'Mode',
type => SANE_TYPE_GROUP,
'cap' => 0,
'max_values' => 0,
'name' => '',
'unit' => SANE_UNIT_NONE,
'index' => 1,
'desc' => '',
type => SANE_TYPE_GROUP,
'constraint_type' => SANE_CONSTRAINT_NONE
},
{
name => 'mode',
title => 'Mode',
index => 2,
'desc' => 'Select the scan mode',
'val' => 'Black & White',
'constraint' => [
'Black & White',
'Gray[Error Diffusion]',
'True Gray',
'24bit Color',
'24bit Color[Fast]'
],
constraint_type => SANE_CONSTRAINT_STRING_LIST,
'unit' => SANE_UNIT_NONE,
type => SANE_TYPE_STRING,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'resolution',
title => 'Resolution',
index => 3,
'desc' => 'Sets the resolution of the scanned image.',
'val' => 200,
'constraint' => [ 100, 150, 200, 300, 400, 600, 1200, 2400, 4800, '9600' ],
'unit' => SANE_UNIT_DPI,
constraint_type => SANE_CONSTRAINT_WORD_LIST,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'source',
title => 'Source',
index => 4,
'desc' => 'Selects the scan source (such as a document-feeder).',
'val' => 'Automatic Document Feeder',
'constraint' => [ 'FlatBed', 'Automatic Document Feeder' ],
'unit' => SANE_UNIT_NONE,
type => SANE_TYPE_STRING,
constraint_type => SANE_CONSTRAINT_STRING_LIST,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'brightness',
title => 'Brightness',
index => 5,
'desc' => 'Controls the brightness of the acquired image.',
'val' => 0,
constraint => {
'min' => -50,
'max' => 50,
'quant' => 1,
},
constraint_type => SANE_CONSTRAINT_RANGE,
'unit' => SANE_UNIT_PERCENT,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'contrast',
title => 'Contrast',
index => 6,
'desc' => 'Controls the contrast of the acquired image.',
constraint => {
'min' => -50,
'max' => 50,
'quant' => 1,
},
constraint_type => SANE_CONSTRAINT_RANGE,
'unit' => SANE_UNIT_PERCENT,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
'max_values' => 1,
},
{
index => 7,
title => 'Geometry',
type => SANE_TYPE_GROUP,
'cap' => 0,
'max_values' => 0,
'name' => '',
'unit' => SANE_UNIT_NONE,
'desc' => '',
'constraint_type' => SANE_CONSTRAINT_NONE
},
{
name => 'l',
title => 'Top-left x',
index => 8,
'desc' => 'Top-left x position of scan area.',
'val' => 0,
constraint => {
'min' => 0,
'max' => 210,
'quant' => 0.0999908,
},
constraint_type => SANE_CONSTRAINT_RANGE,
'unit' => SANE_UNIT_MM,
type => SANE_TYPE_FIXED,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 't',
title => 'Top-left y',
index => 9,
'desc' => 'Top-left y position of scan area.',
'val' => 0,
constraint => {
'min' => 0,
'max' => 297,
'quant' => 0.0999908,
},
constraint_type => SANE_CONSTRAINT_RANGE,
'unit' => SANE_UNIT_MM,
type => SANE_TYPE_FIXED,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'x',
title => 'Width',
index => 10,
'desc' => 'Width of scan-area.',
'val' => 209.981,
constraint => {
'min' => 0,
'max' => 210,
'quant' => 0.0999908,
},
constraint_type => SANE_CONSTRAINT_RANGE,
'unit' => SANE_UNIT_MM,
type => SANE_TYPE_FIXED,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'y',
title => 'Height',
index => 11,
'desc' => 'Height of scan-area.',
'val' => 296.973,
constraint => {
'min' => 0,
'max' => 297,
'quant' => 0.0999908,
},
constraint_type => SANE_CONSTRAINT_RANGE,
'unit' => SANE_UNIT_MM,
type => SANE_TYPE_FIXED,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
}
);
is_deeply( $options->{array}, \@that, 'Brother_DCP-7025' );
is( Gscan2pdf::Scanner::Options->device, 'brother2:bus5;dev1', 'device name' );
gscan2pdf-1.2.3/t/067_Dialog_Scan_CLI.t 0000644 0001750 0001750 00000006201 12237446454 015662 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 9;
use Glib qw(TRUE FALSE); # To get TRUE and FALSE
use Gtk2 -init; # Could just call init separately
BEGIN {
use_ok('Gscan2pdf::Dialog::Scan::CLI');
}
#########################
my $window = Gtk2::Window->new;
Glib::set_application_name('gscan2pdf');
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Frontend::CLI->setup($logger);
ok(
my $dialog = Gscan2pdf::Dialog::Scan::CLI->new(
title => 'title',
'transient-for' => $window,
'logger' => $logger,
'reload-triggers' => qw(mode),
),
'Created dialog'
);
isa_ok( $dialog, 'Gscan2pdf::Dialog::Scan::CLI' );
$dialog->set( 'cache-options', TRUE );
$dialog->signal_connect(
'process-error' => sub {
my ( $widget, $process, $msg ) = @_;
Gtk2->main_quit;
}
);
my ( $signal, $signal2 );
$signal = $dialog->signal_connect(
'changed-options-cache' => sub {
$dialog->signal_handler_disconnect($signal);
is( $#{ $dialog->get('current-scan-options') },
-1, 'cached default Gray - no scan option set' );
$signal = $dialog->signal_connect(
'reloaded-scan-options' => sub {
$dialog->signal_handler_disconnect($signal);
$signal = $dialog->signal_connect(
'changed-options-cache' => sub {
$dialog->signal_handler_disconnect($signal);
is( $#{ $dialog->get('current-scan-options') },
0, 'cached Color - 1 scan option set' );
$signal2 = $dialog->signal_connect(
'fetched-options-cache' => sub {
my ( $widget, $device, $cache_key ) = @_;
$dialog->signal_handler_disconnect($signal2);
pass('fetched-options-cache');
}
);
$signal = $dialog->signal_connect(
'reloaded-scan-options' => sub {
$dialog->signal_handler_disconnect($signal);
is( $#{ $dialog->get('current-scan-options') },
0, 'retrieved Gray from cache - 1 scan option set' );
$signal = $dialog->signal_connect(
'reloaded-scan-options' => sub {
$dialog->signal_handler_disconnect($signal);
is( $#{ $dialog->get('current-scan-options') },
0, 'retrieved Color from cache - 1 scan option set' );
$signal = $dialog->signal_connect(
'reloaded-scan-options' => sub {
$dialog->signal_handler_disconnect($signal);
is( $#{ $dialog->get('current-scan-options') },
0, 'retrieved Gray from cache #2 - 1 scan option set' );
Gtk2->main_quit;
}
);
$dialog->set_option(
$dialog->get('available-scan-options')->by_name('mode'), 'Gray' );
}
);
$dialog->set_option(
$dialog->get('available-scan-options')->by_name('mode'), 'Color' );
}
);
$dialog->set_option(
$dialog->get('available-scan-options')->by_name('mode'), 'Gray' );
}
);
$dialog->set_option(
$dialog->get('available-scan-options')->by_name('mode'), 'Color' );
}
);
}
);
$dialog->set( 'device-list', [ { 'name' => 'test' } ] );
$dialog->set( 'device', 'test' );
Gtk2->main;
#########################
__END__
gscan2pdf-1.2.3/t/166_cancel_import.t 0000644 0001750 0001750 00000002524 12270574026 015645 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 2;
BEGIN {
use Gscan2pdf::Document;
use Gtk2 -init; # Could just call init separately
}
#########################
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Document->setup($logger);
# Create test image
system('convert rose: test.tif');
my $old = `identify -format '%m %G %g %z-bit %r' test.tif`;
my $slist = Gscan2pdf::Document->new;
# dir for temporary files
my $dir = File::Temp->newdir;
$slist->set_dir($dir);
$slist->get_file_info(
path => 'test.tif',
finished_callback => sub {
my ($info) = @_;
my $pid = $slist->import_file(
info => $info,
first => 1,
last => 1,
cancelled_callback => sub {
is( defined( $slist->{data}[0] ), '', 'TIFF not imported' );
$slist->import_file(
info => $info,
first => 1,
last => 1,
finished_callback => sub {
system("cp $slist->{data}[0][2]{filename} test.tif");
Gtk2->main_quit;
}
);
}
);
$slist->cancel($pid);
}
);
Gtk2->main;
is( `identify -format '%m %G %g %z-bit %r' test.tif`,
$old, 'TIFF imported correctly after cancelling previous import' );
#########################
unlink 'test.tif';
Gscan2pdf::Document->quit();
gscan2pdf-1.2.3/t/167_import_with_error.t 0000644 0001750 0001750 00000003466 12237446416 016617 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 3;
BEGIN {
use Gscan2pdf::Document;
use Gtk2 -init; # Could just call init separately
}
#########################
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Document->setup($logger);
# Create test images
system('touch test.ppm');
system('convert rose: test.tif');
my $old = `identify -format '%m %G %g %z-bit %r' test.tif`;
my $slist = Gscan2pdf::Document->new;
# dir for temporary files
my $dir = File::Temp->newdir;
$slist->set_dir($dir);
$slist->get_file_info(
path => 'test.ppm',
error_callback => sub {
my ($text) = @_;
is(
$text,
'test.ppm is not a recognised image type',
'message opening empty image'
);
$slist->get_file_info(
path => 'test.png',
error_callback => sub {
my ($text) = @_;
is( $text, 'File test.png not found',
'message opening non-existent image' );
$slist->get_file_info(
path => 'test.tif',
finished_callback => sub {
my ($info) = @_;
$slist->import_file(
info => $info,
first => 1,
last => 1,
finished_callback => sub {
is(
`identify -format '%m %G %g %z-bit %r' $slist->{data}[0][2]{filename}`,
$old,
'TIFF imported correctly after previous errors'
);
Gtk2->main_quit;
}
);
},
error_callback => sub {
ok( 0, 'error callback triggered after previous errors' );
Gtk2->main_quit;
}
);
},
finished_callback => sub {
Gtk2->main_quit;
}
);
},
finished_callback => sub {
Gtk2->main_quit;
}
);
Gtk2->main;
#########################
unlink 'test.ppm', 'test.tif', <$dir/*>;
rmdir $dir;
Gscan2pdf::Document->quit();
gscan2pdf-1.2.3/t/34_cuneiform_in_thread.t 0000644 0001750 0001750 00000002761 12053230657 016745 0 ustar jeff jeff use warnings;
use strict;
use File::Basename; # Split filename into dir, file, ext
use Test::More tests => 3;
BEGIN {
use Gscan2pdf::Document;
use_ok('Gscan2pdf::Cuneiform');
use Gtk2 -init; # Could just call init separately
}
#########################
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
SKIP: {
skip 'Cuneiform not installed', 2 unless Gscan2pdf::Cuneiform->setup($logger);
Gscan2pdf::Document->setup($logger);
# Create test image
system(
'convert +matte -depth 1 -pointsize 12 -density 300 label:"The quick brown fox" test.png'
);
my $slist = Gscan2pdf::Document->new;
# dir for temporary files
my $dir = File::Temp->newdir;
$slist->set_dir($dir);
$slist->get_file_info(
path => 'test.png',
finished_callback => sub {
my ($info) = @_;
$slist->import_file(
info => $info,
first => 1,
last => 1,
finished_callback => sub {
$slist->cuneiform(
page => $slist->{data}[0][2],
language => 'eng',
finished_callback => sub {
like(
$slist->{data}[0][2]{hocr},
qr/The quick brown fox/,
'Cuneiform returned sensible text'
);
is( dirname("$slist->{data}[0][2]{filename}"),
"$dir", 'using session directory' );
Gtk2->main_quit;
}
);
}
);
}
);
Gtk2->main;
unlink 'test.png', <$dir/*>;
rmdir $dir;
Gscan2pdf::Document->quit();
}
gscan2pdf-1.2.3/t/29_tesseract.t 0000644 0001750 0001750 00000006204 12237446416 014744 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 22;
BEGIN {
use_ok('Gscan2pdf::Tesseract');
use Encode;
}
#########################
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
my $output = <setup($logger);
# Create test image
system(
'convert +matte -depth 1 -colorspace Gray -pointsize 12 -density 300 label:"The quick brown fox" test.png'
);
my ( $got, $messages ) =
Gscan2pdf::Tesseract->hocr( 'test.png', 'eng', $logger );
like( $got, qr/The/, 'Tesseract returned "The"' );
like( $got, qr/quick/, 'Tesseract returned "quick"' );
like( $got, qr/brown/, 'Tesseract returned "brown"' );
like( $got, qr/fox/, 'Tesseract returned "fox"' );
my $languages = Gscan2pdf::Tesseract->languages;
skip 'German language pack for Tesseract not installed', 5
unless ( defined $languages->{'deu'} );
# Create test image
system(
"convert +matte -depth 1 -colorspace Gray -pointsize 12 -density 300 label:'öÖäÄüÜß' test.png"
);
( $got, $messages ) = Gscan2pdf::Tesseract->hocr( 'test.png', 'deu', $logger );
is( Encode::is_utf8( $got, 1 ), 1, "Tesseract returned UTF8" );
for my $c (qw( ö ä ü ß )) {
my $c2 = decode_utf8($c);
like( $got, qr/$c2/, "Tesseract returned $c" );
}
unlink 'test.png';
}
__END__
gscan2pdf-1.2.3/t/02_Scanner_Options_brother.t 0000644 0001750 0001750 00000012107 12271200642 017551 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 3;
use Sane 0.05; # For enums
BEGIN { use_ok('Gscan2pdf::Scanner::Options') }
#########################
my $filename = 'scanners/brother';
my $output = do { local ( @ARGV, $/ ) = $filename; <> };
my $options = Gscan2pdf::Scanner::Options->new_from_data($output);
my @that = (
{
index => 0,
},
{
name => '',
index => 1,
title => 'Mode',
cap => 0,
type => SANE_TYPE_GROUP,
'constraint_type' => SANE_CONSTRAINT_NONE,
'unit' => SANE_UNIT_NONE,
'max_values' => 0,
'desc' => '',
},
{
name => 'mode',
title => 'Mode',
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
index => 2,
'desc' => 'Select the scan mode',
'val' => '24bit Color',
'constraint' => [
'Black & White',
'Gray[Error Diffusion]',
'True Gray',
'24bit Color',
'24bit Color[Fast]'
],
'type' => SANE_TYPE_STRING,
constraint_type => SANE_CONSTRAINT_STRING_LIST,
'unit' => SANE_UNIT_NONE,
'max_values' => 1,
},
{
name => 'resolution',
title => 'Resolution',
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
index => 3,
'desc' => 'Sets the resolution of the scanned image.',
'val' => '200',
'constraint' => [
'100', '150', '200', '300', '400', '600', '1200', '2400', '4800', '9600'
],
'type' => SANE_TYPE_INT,
constraint_type => SANE_CONSTRAINT_WORD_LIST,
'unit' => SANE_UNIT_DPI,
'max_values' => 1,
},
{
name => 'source',
title => 'Source',
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
index => 4,
'desc' => 'Selects the scan source (such as a document-feeder).',
'val' => 'Automatic Document Feeder',
'constraint' => [ 'FlatBed', 'Automatic Document Feeder' ],
'type' => SANE_TYPE_STRING,
constraint_type => SANE_CONSTRAINT_STRING_LIST,
'unit' => SANE_UNIT_NONE,
'max_values' => 1,
},
{
name => 'brightness',
title => 'Brightness',
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
index => 5,
'desc' => 'Controls the brightness of the acquired image.',
constraint => {
'min' => -50,
'max' => 50,
'quant' => 1,
},
'type' => SANE_TYPE_INT,
constraint_type => SANE_CONSTRAINT_RANGE,
'unit' => SANE_UNIT_PERCENT,
'max_values' => 1,
},
{
name => 'contrast',
title => 'Contrast',
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
index => 6,
'desc' => 'Controls the contrast of the acquired image.',
constraint => {
'min' => -50,
'max' => 50,
'quant' => 1,
},
'type' => SANE_TYPE_INT,
constraint_type => SANE_CONSTRAINT_RANGE,
'unit' => SANE_UNIT_PERCENT,
'max_values' => 1,
},
{
name => '',
index => 7,
title => 'Geometry',
cap => 0,
type => SANE_TYPE_GROUP,
'constraint_type' => SANE_CONSTRAINT_NONE,
'unit' => SANE_UNIT_NONE,
'max_values' => 0,
'desc' => '',
},
{
name => 'l',
title => 'Top-left x',
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
index => 8,
'desc' => 'Top-left x position of scan area.',
'val' => 0,
constraint => {
'min' => 0,
'max' => 210,
'quant' => 0.0999908,
},
'type' => SANE_TYPE_FIXED,
constraint_type => SANE_CONSTRAINT_RANGE,
'unit' => SANE_UNIT_MM,
'max_values' => 1,
},
{
name => 't',
title => 'Top-left y',
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
index => 9,
'desc' => 'Top-left y position of scan area.',
'val' => 0,
constraint => {
'min' => 0,
'max' => 297,
'quant' => 0.0999908,
},
'type' => SANE_TYPE_FIXED,
constraint_type => SANE_CONSTRAINT_RANGE,
'unit' => SANE_UNIT_MM,
'max_values' => 1,
},
{
name => 'x',
title => 'Width',
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
index => 10,
'desc' => 'Width of scan-area.',
'val' => 209.981,
constraint => {
'min' => 0,
'max' => 210,
'quant' => 0.0999908,
},
'type' => SANE_TYPE_FIXED,
constraint_type => SANE_CONSTRAINT_RANGE,
'unit' => SANE_UNIT_MM,
'max_values' => 1,
},
{
name => 'y',
title => 'Height',
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
index => 11,
'desc' => 'Height of scan-area.',
'val' => 296.973,
constraint => {
'min' => 0,
'max' => 297,
'quant' => 0.0999908,
},
'type' => SANE_TYPE_FIXED,
constraint_type => SANE_CONSTRAINT_RANGE,
'unit' => SANE_UNIT_MM,
'max_values' => 1,
}
);
is_deeply( $options->{array}, \@that, 'brother' );
is( Gscan2pdf::Scanner::Options->device, 'brother2:net1;dev0', 'device name' );
gscan2pdf-1.2.3/t/163_import_pdf.t 0000644 0001750 0001750 00000002356 12053230657 015167 0 ustar jeff jeff use warnings;
use strict;
use File::Basename; # Split filename into dir, file, ext
use Test::More tests => 3;
BEGIN {
use_ok('Gscan2pdf::Document');
use Gtk2 -init; # Could just call init separately
}
#########################
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Document->setup($logger);
# Create test image
system('convert rose: test.pdf');
system('convert rose: test.png');
my $old = `identify -format '%m %G %g %z-bit %r' test.png`;
my $slist = Gscan2pdf::Document->new;
# dir for temporary files
my $dir = File::Temp->newdir;
$slist->set_dir($dir);
$slist->get_file_info(
path => 'test.pdf',
finished_callback => sub {
my ($info) = @_;
$slist->import_file(
info => $info,
first => 1,
last => 1,
finished_callback => sub {
is( `identify -format '%m %G %g %z-bit %r' $slist->{data}[0][2]{filename}`,
$old, 'PDF imported correctly' );
is( dirname("$slist->{data}[0][2]{filename}"),
"$dir", 'using session directory' );
Gtk2->main_quit;
}
);
}
);
Gtk2->main;
#########################
unlink 'test.pdf', 'test.png', <$dir/*>;
rmdir $dir;
Gscan2pdf::Document->quit();
gscan2pdf-1.2.3/t/118_save_multipage_pdf.t 0000644 0001750 0001750 00000002606 12270574026 016662 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 1;
BEGIN {
use Gscan2pdf::Document;
use Gtk2 -init; # Could just call init separately
use PDF::API2;
use File::Copy;
}
#########################
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Document->setup($logger);
# Create test image
system('convert rose: 1.pnm');
# number of pages
my $n = 3;
my @pages;
my $slist = Gscan2pdf::Document->new;
# dir for temporary files
my $dir = File::Temp->newdir;
$slist->set_dir($dir);
for my $i ( 1 .. $n ) {
copy( '1.pnm', "$i.pnm" ) if ( $i > 1 );
$slist->get_file_info(
path => "$i.pnm",
finished_callback => sub {
my ($info) = @_;
$slist->import_file(
info => $info,
first => 1,
last => 1,
finished_callback => sub {
use utf8;
$slist->{data}[ $i - 1 ][2]{hocr} = 'hello world';
push @pages, $slist->{data}[ $i - 1 ][2];
$slist->save_pdf(
path => 'test.pdf',
list_of_pages => \@pages,
finished_callback => sub { Gtk2->main_quit }
) if ( $i == $n );
}
);
}
);
}
Gtk2->main;
is( `pdffonts test.pdf | grep -c Times-Roman` + 0,
1, 'font embedded once in multipage PDF' );
#########################
for my $i ( 1 .. $n ) {
unlink "$i.pnm";
}
unlink 'test.pdf';
Gscan2pdf::Document->quit();
gscan2pdf-1.2.3/t/02_Scanner_Options_epson_3490.t 0000644 0001750 0001750 00000037215 12271200642 017716 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 3;
use Sane 0.05; # For enums
BEGIN { use_ok('Gscan2pdf::Scanner::Options') }
#########################
my $filename = 'scanners/epson_3490';
my $output = do { local ( @ARGV, $/ ) = $filename; <> };
my $options = Gscan2pdf::Scanner::Options->new_from_data($output);
my @that = (
{
'index' => 0,
},
{
index => 1,
title => 'Scan Mode',
'cap' => 0,
'max_values' => 0,
'name' => '',
'unit' => SANE_UNIT_NONE,
'desc' => '',
type => SANE_TYPE_GROUP,
'constraint_type' => SANE_CONSTRAINT_NONE
},
{
name => 'resolution',
title => 'Resolution',
index => 2,
'desc' => 'Sets the resolution of the scanned image.',
'val' => '300',
'constraint' => [
'50', '150', '200', '240', '266', '300', '350', '360',
'400', '600', '720', '800', '1200', '1600', '3200'
],
'unit' => SANE_UNIT_DPI,
constraint_type => SANE_CONSTRAINT_WORD_LIST,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_AUTOMATIC,
'max_values' => 1,
},
{
name => 'preview',
title => 'Preview',
index => 3,
'desc' => 'Request a preview-quality scan.',
'val' => SANE_FALSE,
'unit' => SANE_UNIT_NONE,
'type' => SANE_TYPE_BOOL,
'constraint_type' => SANE_CONSTRAINT_NONE,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_AUTOMATIC,
'max_values' => 1,
},
{
name => 'mode',
title => 'Mode',
index => 4,
'desc' => 'Selects the scan mode (e.g., lineart, monochrome, or color).',
'val' => 'Color',
'constraint' => [ 'Color', 'Gray', 'Lineart' ],
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_STRING_LIST,
type => SANE_TYPE_STRING,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_AUTOMATIC,
'max_values' => 1,
},
{
name => 'preview-mode',
title => 'Preview mode',
index => 5,
'desc' =>
'Select the mode for previews. Greyscale previews usually give the best combination of speed and detail.',
'val' => 'Auto',
'constraint' => [ 'Auto', 'Color', 'Gray', 'Lineart' ],
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_STRING_LIST,
type => SANE_TYPE_STRING,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_AUTOMATIC,
'max_values' => 1,
},
{
name => 'high-quality',
title => 'High quality',
index => 6,
'desc' => 'Highest quality but lower speed',
'val' => SANE_FALSE,
'unit' => SANE_UNIT_NONE,
'type' => SANE_TYPE_BOOL,
'constraint_type' => SANE_CONSTRAINT_NONE,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_AUTOMATIC,
'max_values' => 1,
},
{
name => 'source',
title => 'Source',
index => 7,
'desc' => 'Selects the scan source (such as a document-feeder).',
'val' => 'Flatbed',
'constraint' => [ 'Flatbed', 'Transparency Adapter' ],
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_STRING_LIST,
type => SANE_TYPE_STRING,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_AUTOMATIC,
'max_values' => 1,
},
{
index => 8,
title => 'Geometry',
'cap' => 0,
'max_values' => 0,
'name' => '',
'unit' => SANE_UNIT_NONE,
'desc' => '',
type => SANE_TYPE_GROUP,
'constraint_type' => SANE_CONSTRAINT_NONE
},
{
name => 'l',
title => 'Top-left x',
index => 9,
'desc' => 'Top-left x position of scan area.',
'val' => 0,
constraint => {
'min' => 0,
'max' => 216,
},
'unit' => SANE_UNIT_MM,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 't',
title => 'Top-left y',
index => 10,
'desc' => 'Top-left y position of scan area.',
'val' => 0,
constraint => {
'min' => 0,
'max' => 297,
},
'unit' => SANE_UNIT_MM,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'x',
title => 'Width',
index => 11,
'desc' => 'Width of scan-area.',
'val' => 216,
constraint => {
'min' => 0,
'max' => 216,
},
'unit' => SANE_UNIT_MM,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'y',
title => 'Height',
index => 12,
'desc' => 'Height of scan-area.',
'val' => 297,
constraint => {
'min' => 0,
'max' => 297,
},
'unit' => SANE_UNIT_MM,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'predef-window',
title => 'Predef window',
index => 13,
'desc' =>
'Provides standard scanning areas for photographs, printed pages and the like.',
'val' => 'None',
'constraint' => [ 'None', '6x4 (inch)', '8x10 (inch)', '8.5x11 (inch)' ],
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_STRING_LIST,
type => SANE_TYPE_STRING,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
index => 14,
title => 'Enhancement',
'cap' => 0,
'max_values' => 0,
'name' => '',
'unit' => SANE_UNIT_NONE,
'desc' => '',
type => SANE_TYPE_GROUP,
'constraint_type' => SANE_CONSTRAINT_NONE
},
{
name => 'depth',
title => 'Depth',
index => 15,
'desc' =>
'Number of bits per sample, typical values are 1 for "line-art" and 8 for multibit scans.',
'val' => '8',
'constraint' => [ '8', '16' ],
'unit' => SANE_UNIT_BIT,
constraint_type => SANE_CONSTRAINT_WORD_LIST,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'quality-cal',
title => 'Quality cal',
index => 16,
'desc' => 'Do a quality white-calibration',
'val' => SANE_TRUE,
'unit' => SANE_UNIT_NONE,
'type' => SANE_TYPE_BOOL,
'constraint_type' => SANE_CONSTRAINT_NONE,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'halftoning',
title => 'Halftoning',
index => 17,
'desc' =>
'Selects whether the acquired image should be halftoned (dithered).',
'unit' => SANE_UNIT_NONE,
'type' => SANE_TYPE_BOOL,
'constraint_type' => SANE_CONSTRAINT_NONE,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
'max_values' => 1,
},
{
name => 'halftone-pattern',
title => 'Halftone pattern',
index => 18,
'desc' =>
'Defines the halftoning (dithering) pattern for scanning halftoned images.',
'constraint' => [ 'DispersedDot8x8', 'DispersedDot16x16' ],
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_STRING_LIST,
type => SANE_TYPE_STRING,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
'max_values' => 1,
},
{
name => 'custom-gamma',
title => 'Custom gamma',
index => 19,
'desc' =>
'Determines whether a builtin or a custom gamma-table should be used.',
'val' => SANE_FALSE,
'unit' => SANE_UNIT_NONE,
'type' => SANE_TYPE_BOOL,
'constraint_type' => SANE_CONSTRAINT_NONE,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'analog-gamma-bind',
title => 'Analog gamma bind',
index => 20,
'desc' => 'In RGB-mode use same values for each color',
'val' => SANE_FALSE,
'unit' => SANE_UNIT_NONE,
'type' => SANE_TYPE_BOOL,
'constraint_type' => SANE_CONSTRAINT_NONE,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'analog-gamma',
title => 'Analog gamma',
index => 21,
'desc' => 'Analog gamma-correction',
constraint => {
'min' => 0,
'max' => 4,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
'max_values' => 1,
},
{
name => 'analog-gamma-r',
title => 'Analog gamma r',
index => 22,
'desc' => 'Analog gamma-correction for red',
'val' => '1.79999',
constraint => {
'min' => 0,
'max' => 4,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_FIXED,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'analog-gamma-g',
title => 'Analog gamma g',
index => 23,
'desc' => 'Analog gamma-correction for green',
'val' => '1.79999',
constraint => {
'min' => 0,
'max' => 4,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_FIXED,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'analog-gamma-b',
title => 'Analog gamma b',
index => 24,
'desc' => 'Analog gamma-correction for blue',
'val' => '1.79999',
constraint => {
'min' => 0,
'max' => 4,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_FIXED,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'gamma-table',
title => 'Gamma table',
index => 25,
'desc' =>
'Gamma-correction table. In color mode this option equally affects the red, green, and blue channels simultaneously (i.e., it is an intensity gamma table).',
constraint => {
'min' => 0,
'max' => 65535,
'quant' => 1,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
'max_values' => 255,
},
{
name => 'red-gamma-table',
title => 'Red gamma table',
index => 26,
'desc' => 'Gamma-correction table for the red band.',
constraint => {
'min' => 0,
'max' => 65535,
'quant' => 1,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
'max_values' => 255,
},
{
name => 'green-gamma-table',
title => 'Green gamma table',
index => 27,
'desc' => 'Gamma-correction table for the green band.',
constraint => {
'min' => 0,
'max' => 65535,
'quant' => 1,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
'max_values' => 255,
},
{
name => 'blue-gamma-table',
title => 'Blue gamma table',
index => 28,
'desc' => 'Gamma-correction table for the blue band.',
constraint => {
'min' => 0,
'max' => 65535,
'quant' => 1,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
'max_values' => 255,
},
{
name => 'negative',
title => 'Negative',
index => 29,
'desc' => 'Swap black and white',
'unit' => SANE_UNIT_NONE,
'type' => SANE_TYPE_BOOL,
'constraint_type' => SANE_CONSTRAINT_NONE,
'cap' => SANE_CAP_SOFT_DETECT +
SANE_CAP_SOFT_SELECT +
SANE_CAP_AUTOMATIC +
SANE_CAP_INACTIVE,
'max_values' => 1,
},
{
name => 'threshold',
title => 'Threshold',
index => 30,
'desc' => 'Select minimum-brightness to get a white point',
constraint => {
'min' => 0,
'max' => 100,
'quant' => 1,
},
'unit' => SANE_UNIT_PERCENT,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
'max_values' => 1,
},
{
name => 'brightness',
title => 'Brightness',
index => 31,
'desc' => 'Controls the brightness of the acquired image.',
'val' => '0',
constraint => {
'min' => -400,
'max' => 400,
'quant' => 1,
},
'unit' => SANE_UNIT_PERCENT,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'contrast',
title => 'Contrast',
index => 32,
'desc' => 'Controls the contrast of the acquired image.',
'val' => '0',
constraint => {
'min' => -100,
'max' => 400,
'quant' => 1,
},
'unit' => SANE_UNIT_PERCENT,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
index => 33,
title => 'Advanced',
'cap' => 0,
'max_values' => 0,
'name' => '',
'unit' => SANE_UNIT_NONE,
'desc' => '',
type => SANE_TYPE_GROUP,
'constraint_type' => SANE_CONSTRAINT_NONE
},
{
name => 'rgb-lpr',
title => 'Rgb lpr',
index => 34,
'desc' =>
'Number of scan lines to request in a SCSI read. Changing this parameter allows you to tune the speed at which data is read from the scanner during scans. If this is set too low, the scanner will have to stop periodically in the middle of a scan; if it\'s set too high, X-based frontends may stop responding to X events and your system could bog down.',
'val' => '4',
constraint => {
'quant' => 1,
'min' => 1,
'max' => 50,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'gs-lpr',
title => 'Gs lpr',
index => 35,
'desc' =>
'Number of scan lines to request in a SCSI read. Changing this parameter allows you to tune the speed at which data is read from the scanner during scans. If this is set too low, the scanner will have to stop periodically in the middle of a scan; if it\'s set too high, X-based frontends may stop responding to X events and your system could bog down.',
constraint => {
'quant' => 1,
'min' => 1,
'max' => 50,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
'max_values' => 1,
},
);
is_deeply( $options->{array}, \@that, 'epson_3490' );
is( Gscan2pdf::Scanner::Options->device,
'snapscan:libusb:005:007', 'device name' );
gscan2pdf-1.2.3/t/48_cancel_crop.t 0000644 0001750 0001750 00000002753 12270574026 015221 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 2;
BEGIN {
use Gscan2pdf::Document;
use Gtk2 -init; # Could just call init separately
}
#########################
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Document->setup($logger);
# Create test image
system('convert rose: test.jpg');
my $slist = Gscan2pdf::Document->new;
# dir for temporary files
my $dir = File::Temp->newdir;
$slist->set_dir($dir);
$slist->get_file_info(
path => 'test.jpg',
finished_callback => sub {
my ($info) = @_;
$slist->import_file(
info => $info,
first => 1,
last => 1,
finished_callback => sub {
my $pid = $slist->crop(
page => $slist->{data}[0][2],
x => 10,
y => 10,
w => 10,
h => 10,
cancelled_callback => sub {
is(
-s 'test.jpg',
-s "$slist->{data}[0][2]{filename}",
'image not modified'
);
$slist->save_image(
path => 'test2.jpg',
list_of_pages => [ $slist->{data}[0][2] ],
finished_callback => sub { Gtk2->main_quit }
);
}
);
$slist->cancel($pid);
}
);
}
);
Gtk2->main;
is( system('identify test2.jpg'),
0, 'can create a valid JPG after cancelling previous process' );
#########################
unlink 'test.jpg', 'test2.jpg';
Gscan2pdf::Document->quit();
gscan2pdf-1.2.3/t/111_save_pdf.t 0000644 0001750 0001750 00000002214 12103156350 014566 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 2;
use Gtk2 -init; # Could just call init separately
BEGIN {
use_ok('Gscan2pdf::Document');
}
#########################
Glib::set_application_name('gscan2pdf');
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Document->setup($logger);
# Create test image
system('convert rose: test.pnm');
my $slist = Gscan2pdf::Document->new;
# dir for temporary files
my $dir = File::Temp->newdir;
$slist->set_dir($dir);
$slist->get_file_info(
path => 'test.pnm',
finished_callback => sub {
my ($info) = @_;
$slist->import_file(
info => $info,
first => 1,
last => 1,
finished_callback => sub {
$slist->save_pdf(
path => 'test.pdf',
list_of_pages => [ $slist->{data}[0][2] ],
finished_callback => sub { Gtk2->main_quit }
);
}
);
}
);
Gtk2->main;
is(
`pdfinfo test.pdf | grep 'Page size:'`,
"Page size: 70 x 46 pts\n",
'valid PDF created'
);
#########################
unlink 'test.pnm', 'test.pdf';
Gscan2pdf::Document->quit();
gscan2pdf-1.2.3/t/069_Dialog_Scan_CLI.t 0000644 0001750 0001750 00000003123 12237446454 015664 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 4;
use Glib qw(TRUE FALSE); # To get TRUE and FALSE
use Gtk2 -init; # Could just call init separately
BEGIN {
use_ok('Gscan2pdf::Dialog::Scan::CLI');
}
#########################
my $window = Gtk2::Window->new;
Glib::set_application_name('gscan2pdf');
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Frontend::CLI->setup($logger);
ok(
my $dialog = Gscan2pdf::Dialog::Scan::CLI->new(
title => 'title',
'transient-for' => $window,
'logger' => $logger,
'reload-triggers' => qw(mode),
),
'Created dialog'
);
isa_ok( $dialog, 'Gscan2pdf::Dialog::Scan::CLI' );
$dialog->set( 'cache-options', TRUE );
$dialog->signal_connect(
'process-error' => sub {
my ( $widget, $process, $msg ) = @_;
Gtk2->main_quit;
}
);
my ( $signal, $signal2 );
$signal = $dialog->signal_connect(
'reloaded-scan-options' => sub {
$dialog->signal_handler_disconnect($signal);
$signal = $dialog->signal_connect(
'changed-options-cache' => sub {
my ( $widget, $cache ) = @_;
$dialog->signal_handler_disconnect($signal);
my @keys = keys( %{ $cache->{test} } );
is_deeply(
\@keys,
[ 'mode,Color', 'mode,Gray', 'default' ],
'starting with a non-default profile'
);
Gtk2->main_quit;
}
);
$dialog->set_option( $dialog->get('available-scan-options')->by_name('mode'),
'Color' );
}
);
$dialog->set( 'device-list', [ { 'name' => 'test' } ] );
$dialog->set( 'device', 'test' );
Gtk2->main;
#########################
__END__
gscan2pdf-1.2.3/t/09_NetPBM.t 0000644 0001750 0001750 00000000774 12053230657 014032 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 7;
BEGIN {
use_ok('Gscan2pdf::NetPBM');
}
#########################
for (qw(pbm pgm ppm)) {
my $file = "test.$_";
system("convert -resize 8x5 rose: $file");
is( Gscan2pdf::NetPBM::file_size_from_header($file),
-s $file, "get_size_from_PNM $_ 8 wide" );
system("convert -resize 9x6 rose: $file");
is( Gscan2pdf::NetPBM::file_size_from_header($file),
-s $file, "get_size_from_PNM $_ 9 wide" );
unlink $file;
}
#########################
__END__
gscan2pdf-1.2.3/t/02_Scanner_Options_officejet_5500.t 0000644 0001750 0001750 00000020430 12271200642 020511 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 10;
use Sane 0.05; # For enums
BEGIN { use_ok('Gscan2pdf::Scanner::Options') }
#########################
my $filename = 'scanners/officejet_5500';
my $output = do { local ( @ARGV, $/ ) = $filename; <> };
my $options = Gscan2pdf::Scanner::Options->new_from_data($output);
my @that = (
{
'index' => 0,
},
{
index => 1,
title => 'Scan mode',
'cap' => 0,
'max_values' => 0,
'name' => '',
'unit' => SANE_UNIT_NONE,
'desc' => '',
type => SANE_TYPE_GROUP,
'constraint_type' => SANE_CONSTRAINT_NONE
},
{
name => 'mode',
title => 'Mode',
index => 2,
'desc' => 'Selects the scan mode (e.g., lineart, monochrome, or color).',
'val' => 'Color',
'constraint' => [ 'Lineart', 'Grayscale', 'Color' ],
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_STRING_LIST,
type => SANE_TYPE_STRING,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'resolution',
title => 'Resolution',
index => 3,
'desc' => 'Sets the resolution of the scanned image.',
'val' => '75',
constraint => {
'min' => 75,
'max' => 600,
},
'unit' => SANE_UNIT_DPI,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
index => 4,
title => 'Advanced',
'cap' => 0,
'max_values' => 0,
'name' => '',
'unit' => SANE_UNIT_NONE,
'desc' => '',
type => SANE_TYPE_GROUP,
'constraint_type' => SANE_CONSTRAINT_NONE
},
{
name => 'contrast',
title => 'Contrast',
index => 5,
'desc' => 'Controls the contrast of the acquired image.',
constraint => {
'min' => 0,
'max' => 100,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
'max_values' => 1,
},
{
name => 'compression',
title => 'Compression',
index => 6,
'desc' =>
'Selects the scanner compression method for faster scans, possibly at the expense of image quality.',
'val' => 'JPEG',
'constraint' => [ 'None', 'JPEG' ],
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_STRING_LIST,
type => SANE_TYPE_STRING,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'jpeg-compression-factor',
title => 'JPEG compression factor',
index => 7,
'desc' =>
'Sets the scanner JPEG compression factor. Larger numbers mean better compression, and smaller numbers mean better image quality.',
'val' => '10',
constraint => {
'min' => 0,
'max' => 100,
},
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'batch-scan',
title => 'Batch scan',
index => 8,
'desc' =>
'Guarantees that a "no documents" condition will be returned after the last scanned page, to prevent endless flatbed scans after a batch scan. For some models, option changes in the middle of a batch scan don\'t take effect until after the last page.',
'val' => SANE_FALSE,
'unit' => SANE_UNIT_NONE,
'type' => SANE_TYPE_BOOL,
'constraint_type' => SANE_CONSTRAINT_NONE,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'source',
title => 'Source',
index => 9,
'desc' =>
'Selects the desired scan source for models with both flatbed and automatic document feeder (ADF) capabilities. The "Auto" setting means that the ADF will be used if it\'s loaded, and the flatbed (if present) will be used otherwise.',
'val' => 'Auto',
'constraint' => [ 'Auto', 'Flatbed', 'ADF' ],
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_STRING_LIST,
type => SANE_TYPE_STRING,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'duplex',
title => 'Duplex',
index => 10,
'desc' =>
'Enables scanning on both sides of the page for models with duplex-capable document feeders. For pages printed in "book"-style duplex mode, one side will be scanned upside-down. This feature is experimental.',
'unit' => SANE_UNIT_NONE,
'type' => SANE_TYPE_BOOL,
'constraint_type' => SANE_CONSTRAINT_NONE,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT + SANE_CAP_INACTIVE,
'max_values' => 1,
},
{
index => 11,
title => 'Geometry',
'cap' => 0,
'max_values' => 0,
'name' => '',
'unit' => SANE_UNIT_NONE,
'desc' => '',
type => SANE_TYPE_GROUP,
'constraint_type' => SANE_CONSTRAINT_NONE
},
{
name => 'length-measurement',
title => 'Length measurement',
index => 12,
'desc' =>
'Selects how the scanned image length is measured and reported, which is impossible to know in advance for scrollfed scans.',
'val' => 'Padded',
'constraint' => [ 'Unknown', 'Approximate', 'Padded' ],
'unit' => SANE_UNIT_NONE,
constraint_type => SANE_CONSTRAINT_STRING_LIST,
type => SANE_TYPE_STRING,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'l',
title => 'Top-left x',
index => 13,
'desc' => 'Top-left x position of scan area.',
'val' => 0,
constraint => {
'min' => 0,
'max' => 215.9,
},
'unit' => SANE_UNIT_MM,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_FIXED,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 't',
title => 'Top-left y',
index => 14,
'desc' => 'Top-left y position of scan area.',
'val' => 0,
constraint => {
'min' => 0,
'max' => 381,
},
'unit' => SANE_UNIT_MM,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'x',
title => 'Width',
index => 15,
'desc' => 'Width of scan-area.',
'val' => 215.9,
constraint => {
'min' => 0,
'max' => 215.9,
},
'unit' => SANE_UNIT_MM,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_FIXED,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
},
{
name => 'y',
title => 'Height',
index => 16,
'desc' => 'Height of scan-area.',
'val' => 381,
constraint => {
'min' => 0,
'max' => 381,
},
'unit' => SANE_UNIT_MM,
constraint_type => SANE_CONSTRAINT_RANGE,
type => SANE_TYPE_INT,
'cap' => SANE_CAP_SOFT_DETECT + SANE_CAP_SOFT_SELECT,
'max_values' => 1,
}
);
is_deeply( $options->{array}, \@that, 'officejet_5500' );
is(
$options->supports_paper(
{
x => 210,
y => 297,
l => 0,
t => 0,
},
0
),
1,
'supports_paper'
);
is(
$options->supports_paper(
{
x => 210,
y => 297,
l => 0,
t => -10,
},
0
),
0,
'paper crosses top border'
);
is(
$options->supports_paper(
{
x => 210,
y => 297,
l => 0,
t => 90,
},
0
),
0,
'paper crosses bottom border'
);
is(
$options->supports_paper(
{
x => 210,
y => 297,
l => -10,
t => 0,
},
0
),
0,
'paper crosses left border'
);
is(
$options->supports_paper(
{
x => 210,
y => 297,
l => 10,
t => 0,
},
0
),
0,
'paper crosses right border'
);
is(
$options->supports_paper(
{
x => 225,
y => 297,
l => 0,
t => 0,
},
0
),
0,
'paper too wide'
);
is(
$options->supports_paper(
{
x => 210,
y => 870,
l => 0,
t => 0,
},
0
),
0,
'paper too tall'
);
is(
Gscan2pdf::Scanner::Options->device,
'hpaio:/usb/officejet_5500_series?serial=MY42QF209H96',
'device name'
);
gscan2pdf-1.2.3/t/062_Dialog_Scan_Sane.t 0000644 0001750 0001750 00000004211 12237446454 016133 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 7;
use Glib qw(TRUE FALSE); # To get TRUE and FALSE
use Gtk2 -init; # Could just call init separately
use Sane 0.05; # To get SANE_* enums
BEGIN {
use_ok('Gscan2pdf::Dialog::Scan::Sane');
}
#########################
my $window = Gtk2::Window->new;
Glib::set_application_name('gscan2pdf');
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Frontend::Sane->setup($logger);
ok(
my $dialog = Gscan2pdf::Dialog::Scan::Sane->new(
title => 'title',
'transient-for' => $window,
'logger' => $logger
),
'Created dialog'
);
isa_ok( $dialog, 'Gscan2pdf::Dialog::Scan::Sane' );
my $signal;
$signal = $dialog->signal_connect(
'reloaded-scan-options' => sub {
$dialog->signal_handler_disconnect($signal);
# So that it can be used in hash
my $resolution = SANE_NAME_SCAN_RESOLUTION;
$dialog->add_profile( 'my profile', [ { $resolution => 52 } ] );
my $loop;
my $option_signal;
$option_signal = $dialog->signal_connect(
'changed-scan-option' => sub {
my ( $widget, $option, $value ) = @_;
is_deeply(
$dialog->get('current-scan-options'),
[ { $resolution => 52 } ],
'current-scan-options'
);
$dialog->signal_handler_disconnect($option_signal);
$loop->quit;
}
);
$signal = $dialog->signal_connect(
'changed-profile' => sub {
my ( $widget, $profile ) = @_;
$dialog->signal_handler_disconnect($signal);
is( $profile, 'my profile', 'changed-profile' );
}
);
# need a new main loop because of the timeout
$loop = Glib::MainLoop->new;
$dialog->set( 'profile', 'my profile' );
$loop->run;
$dialog->signal_connect(
'reloaded-scan-options' => sub {
is( $dialog->get('profile'),
undef, 'reloading scan options unsets profile' );
is( $dialog->get('current-scan-options'),
undef, 'reloading scan options unsets current-scan-options' );
Gtk2->main_quit;
}
);
$dialog->scan_options('test');
}
);
$dialog->set( 'device', 'test' );
$dialog->scan_options('test');
Gtk2->main;
Gscan2pdf::Frontend::Sane->quit;
__END__
gscan2pdf-1.2.3/t/117_save_multipage_pdf_with_utf8.t 0000644 0001750 0001750 00000003136 12053230657 020657 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 1;
BEGIN {
use Gscan2pdf::Document;
use Gtk2 -init; # Could just call init separately
use PDF::API2;
use File::Copy;
}
#########################
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Document->setup($logger);
# Create test image
system('convert rose: 1.pnm');
# number of pages
my $n = 3;
my @pages;
my %options;
$options{font} = `fc-list : file | grep times.ttf | head -n 1`;
chomp $options{font};
$options{font} =~ s/: $//;
my $slist = Gscan2pdf::Document->new;
# dir for temporary files
my $dir = File::Temp->newdir;
$slist->set_dir($dir);
for my $i ( 1 .. $n ) {
copy( '1.pnm', "$i.pnm" ) if ( $i > 1 );
$slist->get_file_info(
path => "$i.pnm",
finished_callback => sub {
my ($info) = @_;
$slist->import_file(
info => $info,
first => 1,
last => 1,
finished_callback => sub {
use utf8;
$slist->{data}[ $i - 1 ][2]{hocr} =
'пени способствовала сохранению';
push @pages, $slist->{data}[ $i - 1 ][2];
$slist->save_pdf(
path => 'test.pdf',
list_of_pages => \@pages,
options => \%options,
finished_callback => sub { Gtk2->main_quit }
) if ( $i == $n );
}
);
}
);
}
Gtk2->main;
is( `pdffonts test.pdf | grep -c TrueType` + 0,
1, 'font embedded once in multipage PDF' );
#########################
for my $i ( 1 .. $n ) {
unlink "$i.pnm";
}
unlink 'test.pdf';
Gscan2pdf::Document->quit();
gscan2pdf-1.2.3/t/122_save_djvu_with_text.t 0000644 0001750 0001750 00000002202 12270574026 017074 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 1;
BEGIN {
use Gscan2pdf::Document;
use Gtk2 -init; # Could just call init separately
}
#########################
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Document->setup($logger);
# Create test image
system('convert rose: test.pnm');
my $slist = Gscan2pdf::Document->new;
# dir for temporary files
my $dir = File::Temp->newdir;
$slist->set_dir($dir);
$slist->get_file_info(
path => 'test.pnm',
finished_callback => sub {
my ($info) = @_;
$slist->import_file(
info => $info,
first => 1,
last => 1,
finished_callback => sub {
$slist->{data}[0][2]{hocr} = 'The quick brown fox';
$slist->save_djvu(
path => 'test.djvu',
list_of_pages => [ $slist->{data}[0][2] ],
finished_callback => sub { Gtk2->main_quit }
);
}
);
}
);
Gtk2->main;
like( `djvutxt test.djvu`, qr/The quick brown fox/, 'DjVu with expected text' );
#########################
unlink 'test.pnm', 'test.djvu';
Gscan2pdf::Document->quit();
gscan2pdf-1.2.3/t/91_critic.t 0000644 0001750 0001750 00000000731 12053230657 014214 0 ustar jeff jeff use strict;
use warnings;
use File::Spec;
use Test::More;
if ( not $ENV{TEST_AUTHOR} ) {
my $msg = 'Author test. Set $ENV{TEST_AUTHOR} to a true value to run.';
plan( skip_all => $msg );
}
if ( not eval { require Test::Perl::Critic; } ) {
my $msg = 'Test::Perl::Critic required to criticise code';
plan( skip_all => $msg );
}
my $rcfile = File::Spec->catfile( 't', 'perlcriticrc' );
Test::Perl::Critic->import( -profile => $rcfile );
all_critic_ok( 'bin', 'lib' );
gscan2pdf-1.2.3/t/51_cancel_ocropus.t 0000644 0001750 0001750 00000003036 12270574026 015735 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 2;
BEGIN {
use Gscan2pdf::Document;
use Gscan2pdf::Ocropus;
use Gtk2 -init; # Could just call init separately
}
#########################
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
my $logger = Log::Log4perl::get_logger;
Gscan2pdf::Document->setup($logger);
SKIP: {
skip 'Ocropus not installed', 2 unless Gscan2pdf::Ocropus->setup($logger);
# Create test image
system(
'convert +matte -depth 1 -pointsize 12 -density 300 label:"The quick brown fox" test.png'
);
my $slist = Gscan2pdf::Document->new;
# dir for temporary files
my $dir = File::Temp->newdir;
$slist->set_dir($dir);
$slist->get_file_info(
path => 'test.png',
finished_callback => sub {
my ($info) = @_;
$slist->import_file(
info => $info,
first => 1,
last => 1,
finished_callback => sub {
my $pid = $slist->ocropus(
page => $slist->{data}[0][2],
language => 'eng',
cancelled_callback => sub {
is( $slist->{data}[0][2]{hocr}, undef, 'no OCR output' );
$slist->save_image(
path => 'test.jpg',
list_of_pages => [ $slist->{data}[0][2] ],
finished_callback => sub { Gtk2->main_quit }
);
}
);
$slist->cancel($pid);
}
);
}
);
Gtk2->main;
is( system('identify test.jpg'),
0, 'can create a valid JPG after cancelling previous process' );
unlink 'test.png', 'test.jpg';
}
Gscan2pdf::Document->quit();
gscan2pdf-1.2.3/t/03_Page.t 0000644 0001750 0001750 00000016753 12105514007 013607 0 ustar jeff jeff use warnings;
use strict;
use Test::More tests => 10;
BEGIN {
use_ok('Gscan2pdf::Page');
use Encode;
}
#########################
Glib::set_application_name('gscan2pdf');
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($WARN);
# Create test image
system('convert rose: test.pnm');
Gscan2pdf::Page->set_logger(Log::Log4perl::get_logger);
my $page = Gscan2pdf::Page->new(
filename => 'test.pnm',
format => 'Portable anymap',
resolution => 72,
dir => File::Temp->newdir,
);
$page->{hocr} = <<'EOS';
'