Esses dias, um amigo me pergunta no Google Talk:
duvida de linux
tenho uma imagem
bem grande
e quero que ela seja impressa
em varias paginas
tipo um pedaco numa pagina
outro pedaco em outra
(Antes de prosseguir, uma nota: uma imagem nos formatos JPEG, PNG etc. não possui um tamanho, mas sim uma resolução. Assim, você pode exibir a imagem em qualquer tamanho, mas a resolução provavelmente vai impor limites à qualidade da imagem. Do mesmo modo, uma imagem de, digamos 1900 x 1200 pixels não tem um tamanho definido, mas sim uma resolução, e pode ser impressa tanto numa folha A3, folha A4 ou qualquer outra, variando apenas a qualidade da impressão.)
Quando alguém me fala de processar imagens no Linux, a primeira coisa que me vem a mente é a suíte ImageMagick. Entre as ferramentas do ImageMagick, a que mais uso é o convert
, um programa de linha de comando que permite executar inúmeras operações sobre imagens, como converter de formato, redimensionar, gerar negativo, extrair um pedaço etc. etc.
A minha abordagem seria, então, dividir a imagem em pequenas imagens contíguas e retangulares. Para imprimir numa folha A4, por exemplo, as pequenas imagens deveriam ter proporções de uma folha A4. Como fazer isso?
O primeiro passo é descobrir como recuperar um retângulo de uma imagem. Isto é bem simples com o convert
, basta utilizar a opção -crop
. Para nossa missão, nós usaremos essa opção com uma string na forma
<width>x<height>+<x>+<y>
onde <width>
é a largura da imagem resultante, em pixels; <height>
é a altura da imagem resultante, em pixels; <x>
e <y>
são as coordenadas do pixel a partir de onde a imagem será cortada. Desse modo, se quisermos extrair um retângulo de 100 x 100 pixels de uma figura no arquivo lena.png
de 512 x 512 pixels a partir do centro, faríamos algo como
convert -crop 100x100+256+256 lena.png output.png
Se a imagem for essa:
o resultado do comando acima será:
(Note que a opção -crop
pode ser utilizada de outras maneiras. Confira na documentação da opção.)
Agora, precisamos gerar várias imagens a partir da primeira. Para não ficar fazendo isso na mão, podemos usar o comando for
junto com o comando seq
. (Se você não sabe usar o comando for
e o comando seq
do bash, essa página explica muito bem como funcionam.) Desse modo, se eu quisesse dividir a imagem da Lena acima em retângulos de 100 x 200 pixels, eu faria algo como:
for i in `seq 0 $((512/100))`; do for j in `seq 0 $((512/200))`; do convert -crop 100x200+$((i*100))+$((j*200)) lena.png lena-$j-$i.png done done
Estou dividindo a imagem numa planilha de imagens. Para cada linha, eu vou gerar 512/100 +1 = 6 imagens; para cada coluna, eu vou gerar 512/200 +1 = 3 imagens. (Se você não entendeu o “+1”, lembre-se que estamos contando a partir de zero, como em C, Java etc). A primeira imagem será o retângulo que vai do pixel de coordenada (0, 0) até o pixel de coordenada (100, 200); a segunda imagem irá do pixel de coordenada (100, 0) até o pixel de coordenada (200, 200); do mesmo modo, a primeira imagem da linha abaixo irá do pixel de coordenada (0, 200) até o pixel de coordenada (100, 400) etc. etc., contando as coordenadas a partir do canto superior esquerdo.
Ao rodar isso, gerei dezoito imagens. O resultado, que uni em uma imagem só por praticidade, pode ser visto abaixo. As linhas brancas separam as imagens geradas.
(Note como o convert
, ao encontrar um retângulo com um pedaço vazio, gera a maior figura possível. Isso pode ser notado nas bordas direita e inferior.)
Vamos generalizar o algoritmo. Faremos um script que recebe como parâmetro as dimensões originais do arquivo, as dimensões das imagens a serem geradas e o nome do arquivo original. O resultado será algo como
file=$1 originalx=$2 originaly=$3 slicex=$4 slicey=$5 numberx=$((originalx/slicex)) numbery=$((originaly/slicey)) for i in `seq 0 $numberx`; do for j in `seq 0 $numbery`; do convert -crop ${slicex}x${slicey}+$((i*slicex))+$((j*slicey)) $file $file-$j-$i.png done done
Agora, é só rodar o script dando como argumentos as dimensões originais e algumas dimensões proporcionais ao papel que queremos utilizar. Obteremos imagens que caberão perfeitamente no papel. (Vale lembrar que uma imagem não tem um tamanho em si, mas uma resolução: a qualidade final pode não ficar muito boa, dependendo da resolução da sua imagem.)
Para facilitar o trabalho, vamos juntar todas as imagens em um único arquivo PDF, o que facilitaria a impressão. O convert
do ImageMagick pode fazer isso de maneira bem simples: se invocarmos o convert
passando como parâmetro uma série de imagens e, ao final, o nome de um arquivo com extensão .pdf
, o resultado será um arquivo PDF com uma imagem por página. Assim sendo, ao chamar algo como
convert fig1.png fig2.png fig3.png one-per-page.pdf
one-per-page.pdf
vai conter, ao vai conter, ao final, três páginas. Na primeira, estará fig1.png
; na segunda, teremos fig2.png
e, na terceira página, estará fig3.png
.
Assim, vamos complementar o script criando uma variável que armazena o nome de todos os arquivos gerados (separados por um espaço em branco). Após gerar todas as imagens, vamos colocá-las todas em um arquivo PDF. O script final, você pode vê-lo no pastebin.
Eu apliquei o script sobre nossa imagem, usando as dimensões proporcionais a papel A4 (210 x 297 mm):
./split.sh lena.png 512 512 210 297
O resultado pode ser encontrado aqui. As páginas acabaram em formato A7, mas, se mandar imprimir, elas preencherão toda a folha A4 sem problemas.
O script está disponível para quem quiser fazer qualquer uso dele. Ademais, pode ser melhorado: é possível, por exemplo, fazer com que o ImageMagick descubra ele mesmo as dimensões iniciais da imagem. Entretanto, acredito que ele já possa ser bem útil
Obrigado, Renan Mendes, pela dica sobre como gerar PDFs. A todos, até mais!
Post Revisions:
There are no revisions for this post.