Introdução
Como eu já relatei em um outro tópico, eu estava tendo problemas para escanear imagens. O Epson Scan (que eu usava inicialmente) parou de funcionar.
Depois fui para o Simple Scan do Gnome, que parou de funcionar direito depois que escaneei uns documentos e salvei em PDF. Não importava se eu escolhesse JPEG, PNG ou WebP, tudo o que era salvo no Simple Scan era em PDF.
Por fim, acabei encontrando o xSANE no AUR, e apesar dele ser bem feio (e um pouco confuso no começo), ele funcionou bem, mas por ser do AUR, me recomendaram remover esse pacote. E assim eu fiz.
E pesquisando uma forma de usar o SANE por linha de comando, acabei encontrando uma página na Arch Wiki explicando sobre o scanimage
que escaneia imagens por linha de comando. Com isso, decidi fazer esse Script.
E uma demonstração de como esse Script pode funcionar:
Código do Script
O código do inSANE 1.0.0 está disponível no Pastebin. Basta baixar o código pelo próprio Pastebin…
… ou copiar o conteúdo, colar num editor de texto e salvar com algum nome. Se for baixar do Pastebin, renomeie para insane.sh
. E nos dois casos, dê a permissão de execução.
Código do inSANE se quiser copiar e colar num editor de texto
#! /bin/bash
## Rotina para carregar as variáveis padrões do inSANE
configurarVariaveis () {
PastaPadrao=~/Imagens/Scan ## Pasta onde o Scan será salvo
ResolucaoPadrao=600 ## Resolução da imagem em DPI
}
## Rotina para verificar se a Pasta de Scans existe
pastaScan () {
echo "Verificando pasta de Scans..."
if [ -d $Pasta ]; then # Verificando se a pasta existe
echo "Pasta de Escaneamento... OK" # Jogando a saída fora para prosseguir com o Script
else
echo "Criando a pasta de Escaneamento..."
mkdir $Pasta # Se não existe, criar a pasta
fi
}
## Rotina para carregar as configurações
arquivoConfiguracao () {
configurarVariaveis
echo "Verificando Arquivo de Configuração..."
config=~/.insane.conf ## Arquivo de Configuração Padrão
if [ -e "$config" ]; then ## Verificando se o Arquivo de Configuração existe
echo "Lendo arquivo de configuração..."
source $config ## Se existir, carrega o Arquivo de Configuração para verificar as variáveis
echo -e "Verificando variáveis...\n"
if [ -z $Pasta ]; then ## Verificando se a Variável da Pasta existe no Arquivo
echo -e "\n Pasta... Erro na Configuração: Esse parâmetro não está configurado\n Usando o parâmetro padrão da Pasta..."
Pasta=$PastaPadrao
echo -e " Pasta de Escaneamento:" $Pasta "\n"
else
echo -e " Pasta... OK \n Pasta de Escaneamento:" $Pasta "\n"
fi
if [ -z $Resolucao ]; then ## Verificando se a Veriável da Resolução existe no Arquivo
echo -e " Resolução... Erro na Configuração: Esse parâmetro não está configurado\n Usando parâmetro padrão da Resolução..."
Resolucao=$ResolucaoPadrao
echo -e " Resolução:" $Resolucao "\n"
else
echo -e " Resolução... OK\n Resolução:" $Resolucao "\n"
fi
pastaScan ## Verificar se a pasta do Escaneamento existe
else
echo "Usando configurações padrões..."
Pasta=$PastaPadrao
Resolucao=$ResolucaoPadrao
echo -e " Pasta de Escaneamento:" $Pasta "\n Resolução:" $Resolucao "\n"
pastaScan
fi
}
selecionarScanner () {
scanimage -L | grep -v Camera | gawk -F '`' -P '{ print $2 }' | cut -d"'" -f1 ## Primeiro indentifica os Scanners, Depois retira a Camera Integrada e por fim extrai o ID do dispositivo,
}
## Rotina para verificar se o Zenity está instalado para exibir uma barra de progresso. O Zenity é uma dependência opcional
progresso () {
if [ -z `command -v zenity` ]; then ## Verificando se o Zenity está instalado
echo "" > /dev/null ## Se o Zenity não estiver instalado, prossiga
else
zenity --progress --title="inSANE" --pulsate --auto-close --no-cancel --text="Escaneando..." ## Se o Zenity estiver instalado, exiba uma caixa de diálogo com uma barra de progresso
fi
}
echo -e "\nBem-vindo ao inSANE\nEsse é um Script simples para usar o Scanner por meio do SANE\nVersão 1.0.0\nScript desenvolvido por Rapoelho\n"
arquivoConfiguracao
echo "Detectando Scanner..."
Scanner=`selecionarScanner` ## Selecionando o Scanner
echo "Foi Detectado o Scanner" $Scanner"."
echo "Escaneando..."
scanimage --device "$Scanner" --format=jpeg --output-file $Pasta/Scan_`date +"%Y-%m-%d_%H-%M-%S"`.jpg --resolution $Resolucao | progresso
if [ $? -eq 0 ]; then
echo "Imagem escaneada com sucesso em" $Pasta "em" $Resolucao "DPI"
fi
Como Funciona
O inSANE funciona de uma forma bem simples: Ele detecta o seu Scanner, e usa o scanimage
para escanear a imagem na resolução de 600 DPI e na pasta ~/Imagens/Scan
.
E claro, tem como configurar esses dois parâmetros criando um arquivo .insane.conf
que o inSANE procura antes de usar os valores padrões, com o arquivo tendo as variáveis da Pasta e da Resolução, sendo mais ou menos assim:
Pasta=~/Imagens/Escaneados
Resolucao=300
Como funciona a detecção automática do Scanner?
Essa pra mim foi uma das partes mais interessantes desse Script e por isso decidi comentar ela. Para o scanimage funcionar, ele precisa ter o dispositivo, o formato do arquivo, o arquivo de saída. Na Arch Wiki, o exemplo que tem é esse aqui:
scanimage --device "pixma:04A91749_247936" --format=tiff --output-file test.tiff --progress
Então a forma para detectar automaticamente o Scanner foi essa aqui:
scanimage -L | grep -v Camera | gawk -F '`' -P '{ print $2 }' | cut -d"'" -f1
E porque esse comando para poder extrair um ID de dispositivo? Começando pelo primeiro comando, o scanimage -L
ele existe para que seja feita uma lista de quais dispositivos existem. E a saída dele acaba sendo essa aqui:
Como observado, só preciso do Scanner, no caso a minha Epson L3150, e não da câmera integrada. Com isso, vem o segundo comando, o grep -v Camera
para poder retirar o “Noname Integrated Camera” do caminho.
Com isso, a linha do Scanner foi isolada. Mas ainda é preciso limpar bastante essa linha, pois preciso apenas do
epsonds:libusb:001:091
. E nisso, vem o terceiro comando, o…
gawk -F '`' -P '{ print $2 }'
… para retirar o device
do começo da linha. Com isso, a saída fica assim:
E por fim, tem que limpar o restante da linha. Com isso, vem o cut -d"'" -f1
, que faz esse serviço de cortar tudo o que há depois do '. E por fim, a saída se torna assim, que é o que quero para esse Script.
E isso foi necessário, pois toda vez que eu desconecto e reconecto o Hub USB em que está o Scanner, o ID dele muda. E pode ser que essa Detecção não funcione para todos e que precise de ajustes.
Detecção do Arquivo de Configuração
Esse Script foi feito se ajustando as minhas necessidades, que é salvar o arquivo na pasta ~/Imagens/Scan
e com uma resolução de 600 DPI, mas isso não quer dizer que ele não seja configurável.
Basicamente há uma rotina que verifica se o arquivo .insane.conf
existe na pasta pessoal do usuário e se as variáveis existem.
Infelizmente não consegui uma forma de ver se essas variáveis são válidas, o que pode causar erros se as variáveis existirem no arquivo, mas não forem adequadas para o scanimage
E claro, se o arquivo de configuração e/ou alguma variável não existir, o inSANE passará os valores padrão para o scanimage e assim fazer o escaneamento do arquivo.
Detecção da Pasta de Escaneamento
Outra coisa que o inSANE também faz é verificar se a pasta em que os arquivos serão escaneados existe. Se a pasta existir, o escaneamento será feito normalmente e se não existir, o próprio inSANE cria a pasta. Seja a pasta padrão (~/Imagens/Scan
), seja a pasta configurada com a variável Pasta=
no .insane.conf
.
O escaneamento em si
E por fim, o escaneamento. Com todas as variáveis carregadas e configuradas, é hora de usar o scanimage
scanimage --device "$Scanner" --format=jpeg --output-file $Pasta/Scan_`date +"%Y-%m-%d_%H-%M-%S"`.jpg --resolution $Resolucao
A variável $Scanner
é obtida por meio da rotina de detecção do Scanner, o formato do Arquivo é o JPEG, que dentre os formatos que o meu Scanner suporta é o mais “leve”.
A variável $Resolução
é obtida com a rotina que detecta o arquivo de configuração. E por fim, uma das coisas mais legais desse comando:
--output-file $Pasta/Scan_`date +"%Y-%m-%d_%H-%M-%S"`.jpg
Essa é a variável do Arquivo de saída. Independentemente de onde o Script for executado, ele salvará ou na pasta padrão ou na pasta que está configurada no .insane.conf
. E uma coisa é que esse Script sempre salvará os arquivos com o prefixo Scan_
e com a data e hora em que o escaneamento começou.
Optei por isso, pois essa era a forma em que o XnViewMP escaneava os arquivos do Windows: Salvando com o prefixo Scan_
junto com a Data e Hora em que o escaneamento foi feito. É uma forma de salvar o arquivo sem pensar muito no nome dele e de manter os arquivos escaneados organizados.
E um outro detalhe: Se o Zenity estiver instalado, o inSANE vai exibir um diálogo com uma barra de progresso para mostrar que o escaneamento está acontecendo.
Problemas conhecidos
Um bug que me deparei com esse código é que às vezes o scanimage -L
não consegue detectar o scanner. A solução pra isso é desconectar e conectar o cabo USB do Scanner.
E o que pode ser um problema: Até onde testei, o inSANE funciona apenas com Scanners conectados via USB. Não consegui testar com nada via Rede.
Palavras Finais
Assim como a experiência de fazer aquele Script para a Bateria, essa foi uma experiência que gostei bastante e que decidi compartilhar com vocês. Sei que tem muita coisa que pode ser melhorada, mas para uma primeira versão desse Script estou bem satisfeito.
Talvez eu possa melhorar esse Script com a adição de opções para digitalizar arquivos em PDF, ou talvez com outros formatos de imagem. Ou mesmo quem sabe, com a opção de rotacionar o arquivo digitalizado (e que pode ser muito útil).
Enfim, esse foi um Script que fiz seguindo as minhas necessidades, mas que ajustei ele um pouco para atender as necessidades de algumas outras pessoas.