#!/usr/bin/perl # (C) Luis Angel Cofiño - Noviembre 2008 # # Este programa perl escanea un documento y lo pasa a formato djvu automáticamente, # y ha de considerarse como de Dominio Público, por supuesto. Puedes usarlo o modificarlo # como te apetezca, pero si lo modificas y lo haces público agradecería que se me # citara un poquito. Pura presunción. ;-) use strict; use Text::CSV_XS; use Cwd; # Variables y entorno {{{ my $raiz; my $config="$ENV{HOME}/configuraciones/escaner.conf"; my $tmpdir="/tmp/scan"; my %ajuste; my $ancho="215mm"; my $alto="295mm"; my $setup=0; my $ayuda=0; my $duo=0; my $opcionnoadf=0; my $existefichero=0; my $simulacro=0; my $modo; my $fichero; my @escaner; my @dispositivo; if (!-d "$ENV{HOME}/scan") { mkdir("$ENV{HOME}/scan") || die "No pude crear el directorio $ENV{HOME}/scan\n"; } if (!-d $tmpdir) { mkdir("$tmpdir") || die "No pude crear el directorio temporal\n"; } my $trabajo="$ENV{HOME}/scan"; my $pwd=cwd(); # }}} comprueba_linea_comandos(); if ($ayuda) { ayuda(); } else { lee_config() if -f $config; if ($ajuste{'escaner'} eq '' || $ajuste{'preguntas'} eq 'Si' || $setup) { encuentra_escaner(); } if ($simulacro) { simulacion(); } else { graba_config(); if (!$setup) { chdir("$tmpdir"); escanea(); chdir("$pwd"); } } } # Comprobación de la línea de comandos {{{ sub comprueba_linea_comandos { my $opcion; my $valido=0; while ($opcion=shift(@ARGV)) { if ($opcion eq "--ayuda") { ayuda(); exit 0; } elsif ($opcion eq "--ajuste") { $setup=1; } elsif ($opcion eq "--duo") { $duo=1; } elsif ($opcion eq "--noadf") { $opcionnoadf=1 } elsif ($opcion eq "--lineart") { $modo="Lineart" } elsif ($opcion eq "--gris") { $modo="Gray" } elsif ($opcion eq "--color") { $modo="Color" } elsif ($opcion eq "--simulacro") { $simulacro=1; } elsif ($opcion =~ /\.djvu$/) { $fichero=$opcion; $valido=1; } else { print "\n"; print " Error: Tienes que especificar un nombre de fichero djvu.\n"; print " --------------------------------------------------------\n"; ayuda(); exit 405; } } if ((!$fichero || !$valido) && !$setup) { print "\n"; print " Error: Tienes que especificar al menos un fichero.\n"; print " --------------------------------------------------\n"; ayuda(); exit 404; } else { mueve_a_temporal() if $fichero; } } # }}} # Subrutina que se ejecuta cuando queremos un simulacro {{{ sub simulacion { my $n=proximapagina(); $modo=$ajuste{'modo'} if !$modo; print "Ajuste es $setup\n"; print "Duo es $duo\n"; print "Noadf es $opcionnoadf\n"; print "Modo es $modo\n"; print "Simula es $simulacro\n"; print "Fichero es $fichero\n"; print "Base es $raiz y "; print "ya existe (se continuará en $n)\n" if $existefichero; print "será creado nuevo\n" if !$existefichero; } # }}} # Subrutina que toma una ruta y devuelve el fichero sin ruta {{{ sub basename { my @cadena=split(/\//,"@_"); return $cadena[-1]; } # }}} # Mueve el fichero existente al directorio temporal {{{ sub mueve_a_temporal { $raiz=basename($fichero); chomp($raiz); if (-f "$fichero") { system("mv $fichero $tmpdir/.") if !$simulacro; $existefichero=1; } elsif (-f "$trabajo/$raiz") { system("mv $trabajo/$raiz $tmpdir/.") if !$simulacro; $existefichero=1; } else { $existefichero=0; } $fichero="$tmpdir/$raiz"; } # }}} # Lectura de la configuración {{{ sub lee_config { my $cont; my $linea; my $valor; my $opcion; open(ARCH, "<", $config) || die "No se pudo abrir el fichero de configuración en modo lectura.\n"; while ($linea=) { ($opcion,$valor)=split(/=/,$linea); chomp($opcion); chomp($valor); if ($opcion ne "" && $opcion=~ /^[a-zA-Z0-9]/) { $ajuste{"$opcion"}=$valor; $cont++; } } close ARCH; } # }}} # Escritura de la configuración {{{ sub graba_config { open(ARCH, ">" , $config) || die "No se pudo abrir el fichero de configuración en modo escritura.\n"; print ARCH "preguntas=$ajuste{'preguntas'}\n"; print ARCH "escaner=$ajuste{'escaner'}\n"; print ARCH "dispositivo=$ajuste{'dispositivo'}\n"; print ARCH "adf=$ajuste{'adf'}\n"; print ARCH "modo=$ajuste{'modo'}\n"; close ARCH; } # }}} # Decide cual es la próxima página {{{ sub proximapagina { my $inicio; my $consulta; my $previo=0; if ($existefichero) { open (TEST,"djvm -l $fichero > /dev/null 2>&1 |"); while ($consulta=) { if ($consulta=~/PAGE/) { $previo++; } } close TEST; if ($previo==0) { my $consulta=`file $fichero`; if ($consulta=~/DjVu Image file/) { $previo=1; } } $inicio=$previo+1; } else { $inicio=1; } return $inicio; } # }}} # Escanea el documento {{{ sub escanea { my $tmpfich; my $salida; my $cont; my $pnm; my $dispositivo=$ajuste{'dispositivo'}; my $inicio=proximapagina(); $modo=$ajuste{'modo'} if !$modo; chdir("$tmpdir"); if ($ajuste{'adf'} eq 'Si' && !$opcionnoadf) { if ($duo) { my $cambio; my $impar=1; my $par=2; print "Presta atención al diálogo. Algunos ADF solo soportan 25 hojas o menos,\n"; print "pero tu documento puede que sea más largo. Te pediré primero todos los\n"; print "anversos, del documento entero, de la primera hoja a la última. Cuando\n"; print "terminemos, te pediré todos los reversos, también de la primera hoja a\n"; print "la última. ¡Puede que tengas que darle la vuelta a las hojas por tu cuenta\n"; print "antes de meter los reversos en el ADF!.\n\n"; do { print "Pon los originales en el ADF para escanear anversos y pulsa ..."; $cambio=; system("scanimage -d $dispositivo --format=pnm --batch=scan%03d.pnm --batch-start=$impar --batch-double --source ADF --mode $modo --resolution 300 -x $ancho -y $alto"); $impar+=2; print "Parece que se terminó. ¿Hay más anversos en el documento? (Si/No): "; $cambio=; chomp($cambio); $cambio=~tr/A-Z/a-z/; } while ($cambio eq "si"); print "\n¡Ahora deben entrar reversos, desde el $par hacia el final, presta atención!\n"; do { print "Pon los originales en el ADF para escanear reversos y pulsa ..."; $cambio=; system("scanimage -d $dispositivo --format=pnm --batch=scan%03d.pnm --batch-start=$par --batch-double --source ADF --mode $modo --resolution 300 -x $ancho -y $alto"); $par+=2; print "Parece que se terminó. ¿Hay más reversos en el documento? (Si/No): "; $cambio=; chomp($cambio); $cambio=~tr/A-Z/a-z/; } while ($cambio eq "si"); } else { system("scanadf -d $dispositivo -s $inicio --mode $modo --source ADF --resolution 300 -x $ancho -y $alto -o scan%03d.pnm"); } while ($pnm=<*.pnm>) { if ($modo eq "Color" || $modo eq "Gray") { convierte("$pnm","color"); } else { convierte("$pnm","bw"); } } } else { my $entrada=$modo; my $cont=$inicio; print "Pulsa para seguir o escribe 'fin' para terminar.\n"; print "O también puedes teclear 'lineart', 'gris' o 'color' para escanear\n"; print "cambiando temporalmente el modo, solo para las siguientes páginas.\n"; print "\n"; do { my $corr; my $ultracorr; if ($inicio<10) { $corr="0"; } else { $corr=""; } if ($inicio<100) { $ultracorr="0"; } else { $ultracorr=""; } print "Escaneando. Por favor, espera... "; system("scanimage -d $dispositivo --mode $modo --resolution 300 -x $ancho -y $alto > scan$corr$ultracorr$cont.pnm") if !$simulacro; if ($modo eq "Color" || $modo eq "Gray") { convierte("scan$corr$ultracorr$cont.pnm","color"); } else { convierte("scan$corr$ultracorr$cont.pnm","bw"); } $cont++; print "Vale. Tu dirás qué hacemos: "; $entrada=; chomp($entrada); $entrada=~tr/A-Z/a-z/; if ($entrada eq "color") { $modo="Color"; } elsif ($entrada eq "gris") { $modo="Gray"; } elsif ($entrada eq "lineart") { $modo="Lineart"; } else { #$modo=$ajuste{'modo'}; } } while ($entrada ne "fin"); } system("scanimage --lamp-off --dont-scan -d $dispositivo"); system("mv $fichero $trabajo"); chdir("$trabajo"); rmdir("$tmpdir") || die "No puedo borrar el directorio temporal\n"; } # }}} # Conversión a Djvu {{{ sub convierte { (my $fichtemporal, my $version)=@_; if ($version eq "color") { system("c44 $fichtemporal $fichtemporal.tmp"); } else { system("cjb2 $fichtemporal $fichtemporal.tmp"); } unlink("$fichtemporal"); system("djvm -c $fichtemporal.djvu $fichtemporal.tmp"); unlink("$fichtemporal.tmp"); if ($fichtemporal eq "scan001.pnm" || !$existefichero) { rename("$fichtemporal.djvu","$fichero"); $existefichero=1; } else { system("djvm -i $fichero $fichtemporal.djvu"); } unlink("$fichtemporal.djvu"); } # }}} # Ayuda {{{ sub ayuda { print "\n"; print "escaneo v0.95\n"; print "-------------\n"; print "\n"; print "Este comando escanea un documento y lo convierte a formato DJVU\n"; print "El comando se configura la primera vez que se usa y guarda el setup en\n"; print "el fichero $config\n"; print "\n"; print " Uso: escaneo [opcion] fichero.djvu\n"; print "\n"; print "'opcion' puede ser una (y solo una) de las siguientes:\n"; print "\n"; print " --ayuda Muestra esta ayuda y sale sin escanear\n"; print " --ajuste Reconfigura el programa\n"; print " --duo Escanea documentos impresos a dos caras\n"; print " (esta opción solo funciona si se usa ADF)\n"; print " --noadf Escanea sin el ADF. No cambia la configuración\n"; print " --lineart Escanea en Lineart. No cambia la configuración\n"; print " --gris Escanea en modo Gray. No cambia la configuración\n"; print " --color Escanea en modo Color. No cambia la configuración\n"; print "\n"; } # }}} # Encuentra el escaner {{{ sub encuentra_escaner { my @deteccion=`scanimage -f "%d,%m\n"`; my $eleccion; my $x; for ($x=0; $x<@deteccion; $x++) { ($dispositivo[$x],$escaner[$x])=split(/,/,$deteccion[$x]); chomp($dispositivo[$x]); chomp($escaner[$x]); } if (@deteccion==1) { $ajuste{'escaner'}=$escaner[0]; } elsif (@deteccion==0) { print "No se ha encontrado ningún escaner.\n"; print "Necesitar configurar SANE, antes de usar este script.\n"; print "\n"; exit 1; } else { print "Se han detectado los siguientes escaners:\n"; print "-----------------------------------------\n"; for ($x=0; $x<@escaner; $x++) { print "$x) $escaner[$x]\n"; } print "\n"; do { print "Elige el escaner que vas a usar: "; $eleccion=; chomp($eleccion); } while ($eleccion<0 || $eleccion>@escaner); for ($x=0; $x<@escaner; $x++) { $ajuste{'escaner'}=$escaner[$x] if $eleccion==$x; $ajuste{'dispositivo'}=$dispositivo[$x] if $eleccion==$x; } print "\n"; } print "El escaner configurado será $ajuste{'escaner'} en $ajuste{'dispositivo'}\n"; print "¿Este escaner tiene alimentador automático de hojas (Si/No)?: "; do { $eleccion=; chomp($eleccion); $eleccion=~tr/A-Z/a-z/; if ($eleccion eq "si") { $ajuste{'adf'}="Si"; } if ($eleccion eq "no") { $ajuste{'adf'}="No"; } } while ($eleccion ne "si" && $eleccion ne "no"); print "\n"; print "Están disponibles los siguientes modos:\n"; print "---------------------------------------\n"; print "0) Lineart (recomendado)\n"; print "1) Grises\n"; print "2) Color\n"; print "\n"; do { print "Elige el modo: "; $eleccion=; chomp($eleccion); if ($eleccion eq "") { $eleccion=0; } if ($eleccion==2) { $ajuste{'modo'}="Color"; } elsif ($eleccion==1) { $ajuste{'modo'}="Gray"; } else { $ajuste{'modo'}="Lineart"; } } while ($eleccion<0 || $eleccion>2); if ($ajuste{'preguntas'} ne 'Si') { $ajuste{'preguntas'}='No'; } print "\n"; }# }}}