29 mar 2012

RenPy é um engine para a criação de Visual Novels, aqueles jogos que funcionam como narrações visuais interativas. Já falei dele rapidamente em outra ocasião e agora vamos ver como preparar o ambiente para usá-lo.

Para começar - e creio que não deve causar nenhum espanto - você vai precisar do Python instalado. Enquanto a maioria das distribuições GNU/Linux já vem com Python (mesmo as distribuições pequenas), no Windows você precisará instalá-lo. Para isso, pode baixá-lo de Python.Org. O CyanPack inclui a versão mais recente do Python para Windows e se você tiver o CyanPack poderá instalar o Python a partir dele.

Se você usa Trisquel, Ubuntu, Debian ou algo parecido ou derivado, para instalar o RenPy basta procurar o pacote renpy via Synaptic e instalá-lo. Ou executar o comando apt-get install renpy (ou sudo apt-get install renpy). É bom instalar também o renpy-demo e o renpy-thequestion. Assim você terá exemplos completos de uso da ferramenta.

Pois bem, uma vez instalado o RenPy, a principal ferramenta que você vai utilizar - o que fará interface entre você e o RenPy propriamente - é o Launcher. Ele é feito em Python e tem rotina para criar e configurar os projetos, o que já ajuda muito e evita que você tenha que se preocupar com a criação dos diretórios e arquivos iniciais. O Launcher tem o seguinte aspecto:

RenPy Launcher

Nesta tela, você vê um projeto já criado (Agenda Mundial). As opções para o projeto aberto são:

  • Launch - executar o projeto (jogar)
  • Edit Script - editar o arquivo principal do projeto (o arquivo em que você vai efetivamente trabalhar) com o editor de textos padrão do RenPy (veremos sobre isso mais adiante)
  • Game Directory - abre a pasta do jogo no gerenciador de arquivos
  • Check Script (Lint) - checar o código-fonte do jogo em busca de erros, validar
  • Choose Theme - escolher a paleta de cores do projeto
  • Delet Persistent - tarefa de manutenção - remoção de arquivos persistentes do projeto
  • Archive Files - cria um arquivo compactado com tudo o que se encontra dentro da pasta de projeto
  • Build Distributions - parecido com Archive Files, mas já adiciona o script necessário para o Sistema Operacional desejado

As opções globais ficam na sessão Ren'Py e são:

  • Select Project - permite ecolher um projeto que exista no diretório padrão do RenPy
  • New Project - cria um novo projeto no diretório padrão do RenPy
  • Ren'Py Games List - vai para o site do projeto RenPy listar os jogos que estão lá cadastrados
  • Quit - dar o fora
  • Options - permite definir qual o editor de textos padrão do RenPy e qual o diretório padrão (onde estão os seus projetos de jogos)
  • Ren'Py Help - abre a documentação do RenPy no navegador

Bom, agora você já sabe do básico, mas isso não é tudo, pelo menos aqui na minha instalação do Trisquel não foi tudo.

O problema basicamente foi que o editorde textos não funcionou. Indo na configuração, vi que havia duas opções: Debian e jEdit. O problema é que o editor padrão do Debian é um editor sem interface gráfica e, por isso, não funciona direito aqui. Tudo bem, podemos escolher o jEdit, mas isso também não é uma solução por si, já que o jEdit não vem com o RenPy.

Bem, então vou apresentar duas soluções de editor de textos que funcionam em GNU/Linux.

Usando o jEdit

Não importa em que Sistema Operacional você vai usar o jEdit. Para usá-lo, obviamente, você precisará de suporte Java instalado.

Em Windows, você pode baixar o Java diretamente do site Java.com. O jedit você baixa de jEdit.org e de preferência o coloca dentro do diretório onde ficou instalado o RenPy. Isso deve funcionar.

Agora, se estamos utilizando uma distribuição GNU/Linux que use pacotes .deb, certamente queremos as coisas mais organizadas. Por isso, devemos instalar o pacote jedit via Synaptic. Ou, como antes, simplesmente executar o comando apt-get install jedit. Isso por si só instalará o Java - caso não esteja insatlado - e o jEdit.

Tá, mas não acabou. Isso muito bem instala o jEdit, mas o RenPy não vai encontrá-lo. Para que o RenPy o encontre, execute esta linha no terminal:

ln -s /usr/share/jedit /usr/games/renpy

Isso criará um link simbólico para toda a pasta do jedit, como se ele tivesse sido instalado dentro do RenPy. Assim, o RenPy vai chamar o jEdit sem problemas.

Usando o Geany

Uma opção mais atrativa talvez seja usar o editor Geany, especialmente para quem utiliza o Trisquel que é distribuído junto com o CyanPack, já que o Geany já vem instalado nesse caso.

Se você ainda não tem o Geany instalado, instale o pacote geany.

Para usar o Geany, você vai precisar adicionar um arquivo de sintaxe e alterar outro, ambos da instalação do próprio Geany, além de um do próprio RenPy. Todas essas operações devem ser feitas com privilégios administrativos (como usuário root ou com sudo).

Comece baixando este arquivo (13). Você vai descompactá-lo e jogar o arquivo geany.editor.py no diretório /usr/share/games/renpy/launcher. Pronto, isso basta para que o RenPy possa reconhecer o Geany como um editor de textos (para usá-lo de fato, você deve alterar o editor de textos padrão via interface Launcher - em Options. Ao reabrir o RenPy depois de colocado o tal arquivo lá, o RenPy já vai listar o Geany como opção de editor, junto com o Debian e o jEdit).

Bem, agora o RenPy já abre o Geany com os arquivos que queremos editar, mas o Geany não colore. Para que o destaque sintático do Geany funcione, você precisa adicionar o arquivo filetypes.Ren'Py source.conf ao diretório /usr/share/geany. O arquivo está dentro deste arquivo compactado (14).

Ok, falta pouco. Agora abra o arquivo /usr/share/geany/filetype_extensions.conf e adicione a linha:

Ren'Py source=*.rpy;*.rpym;

Pronto! Está feito! Agora você já tem o ambiente RenPy funcional e pode criar suas próprias histórias interativas! Claro, numa sintaxe própria derivada do Python. Uma sintaxe da qual falarei em uma outra oportunidade...

Special: 
28 mar 2012

Em 28 de março de 2002 era lançado no Japão o jogo Kingdom Hearts para Playstation 2. Um jogo inovador idealizado e projetado por duas grandes empresas do mercado de entretenimento, misturando conceitos e personagens: Square (atualmente Square Enix), produtora de jogos famosa com sua série Final Fantasy; Disney, nome indiscutivelmente famoso na área de desenhos e animações. O novo título era um mistério para o público e trazia uma só pergunta a todos: isso vai dar certo?

Deu certo. Hoje Kingdom Hearts completa 10 anos de vida e continua tendo títulos lançados e fazendo sucesso em vários consoles. Os títulos mais importantes (sim, ainda há outros) da série são:

  1. Kingdom Hearts, para Playstation 2 (2002)
  2. Kingdom Hearts: Chain of Memories, para Game Boy Advance (2004)
  3. Kingdom Hearts II, para Playstation 2 (2005)
  4. Kingdom Hearts 358/2 Days, para Nintendo DS (2009)
  5. Kingdom Hearts Birth by Sleep, para Playstation Portable (2010)

As aventuras acontecem em um universo criado especialmente para a série. Sora, o personagem principal de grande parte da série, tem que partir a procura de seus amigos, interagindo com personagens da Disney e do universo de Final Fantasy, vagando por cenários variados (como o mundo da Pequena Sereia, a terra do Rei Leão e o mundo digital de Tron). Usando uma curiosa espada em formato de chave, a Keyblade, objeto mágico fundamental em toda a história.

É uma série que certamente deve ser apreciada por quem gosta de RPG ou da Disney. RPGs com qualidade Square Enix e o carisma de Mickey, Donald e outros. Inclusive, com as vozes oficiais dos personagens.

Estão por vir Kingdom Hearts III (para Playstation 3 e sem data prevista) e, comemorando os 10 anos da franquia, Kingdom Hearts 3D: Dream Drop Distance (para Nintendo 3DS). Esse último será lançado amanhã no Japão, com direito a kit especial comemorativo, com um 3DS temático mais o jogo. Com a popularidade cada vez mais crescente do 3DS não duvido que será outro sucesso. Veja um trailer:

Apesar de ser lançado amanhã no Japão, a versão americana só deve vir no final do ano. De qualquer forma, já está disponível em pré-venda no eStarLand.

Special: 
27 mar 2012

Desafio a Pedro Cevada

Submitted by bardo

Desafio a Pedro Cevada

No sertão de Alagoas
Morava um certo artista
Chamado Pedro Cevada
Poeta e humorista
Nem simpático nem novo
Mas querido pelo povo
E metido a repentista

Um dia ele acorda
Com Maria, sua senhora
Que lhe traz uma notícia
Que o pobre se apavora
É alguém que ela viu
Lhe fazendo um desafio
Procurando ele lá fora

- Mas Maria, tou lascado!
Vou fugir dessa cidade
- Home, é só um repentista
Tu é frouxo pra sua idade
- Ele é como tu falou?
Me confirma, por favor!
- É assim mesmo, verdade!

- Não tem jeito, vou-me embora
Que danado! Que meleca!
Como vou passar por isso?
Quase borrei a cueca
Eu sendo desafiado
Por um cabra de outro estado
Um cego com uma rabeca!

- Que vergonha, meu Pedrinho
Que enorme embaraço
Não é você que me diz
"Tudo o que eu quero eu faço
Pois só besta arruma briga
Com quem faz cordel, cantiga
É humorista ou palhaço"?

- Home, esqueça dessa história
Traz biscoito pra mim, traz?
Uma garrafa de água
Ou cachaça, tanto faz
Tou com medo e não nego
Mas um repentista cego!
Com rabeca ainda mais!

Esse povo é perigoso
Isso desde a antiguidade
Trucida qualquer rival
Sem a menor piedade
E tu ainda vem dizer
Que um desse veio me ver
Aqui na nossa cidade

- Você quer dizer, Pedrinho
Que cê vai me abandonar?
Fugindo prum canto e outro
Como um bandido vulgar?
Vou passar necessidade
Só pra sua vaidade
Poder em paz descansar?

- Pode ser, mas olha: eu volto!
Lá pra março ou fevereiro
Deixa ele ir embora
Pra ver que chego ligeiro
Não quero viver nas ruas
É uma semana ou duas
Nem carece desespero

- Pois Pedro, preste atenção
Nisso que vou te falar
Se passar daquela porta
Não precisa mais voltar
Eu arrumo outro parceiro
Volte que te quebro inteiro
Com a tábua de cortar

- Maria, minha criança
Não me dê ao urubu
Olha aqui a minha trouxa
E a janela dá pro Sul
Me perdoa, vou embora
É que o meu medo de agora
É mais dele que de tu

-- Cárlisson Galdino

26 mar 2012

Universo Retrato

Submitted by bardo

O tempo que passa não voltaráLágrima Lunar
O Universo se expande, é natural
E não há gravidade que reverta
Ou talvez tudo vá se repetir

Talvez o Universo vá se fundir
E um novo Big Bang aconteça
E sempre se repita, sempre igual
Assim como voltam chuvas pro mar

Olhando para o Sistema Solar
Do solo dessa Lua sem ninguém
É que se nota o quanto isso é fato

O Universo é quase um retrato
E quando muda um pouco, é por bem
Que tudo volte pro mesmo lugar

-- Cárlisson Galdino

Special: 
25 mar 2012

Escarlate III #12 - O Primo Globru

Finalmente chega o dono da casa. A porta da frente se abre e ouve-se um grito “Oi! Cheguei!”. Fran sai correndo para receber seu pai Globru.

- Pai! Vem ver! O primo tá aqui!

- Ô, minha gracinha! Primo? Que primo?

- O primo do senhor!

Ela o puxa e ele chega à sala, parando espantado. Logo ali nos sofás está Zand de pé, ajeitando a lira próximo à moxila de viagem, a lança deitada no chão.

- Zand!?

A visão um do outro fatalmente traz as memórias daquele tempo distante a cada um dos dois. Zand sorri e vai abraçar Globru.

- Zand! Por onde tem andado? Quanto tempo esteve longe, não é? Ora!

- Muito tempo, realmente.

- Que surpresa boa! Olha, Fran! É o primo Zand!

Fran franze a testa e responde:

- Eu conheço o primo Zand. Olha, pai, ele faz música!

- É, vejo que sim! Já conheceu Xepyana?

- Já sim.

- Nossa! Sente aí! Vai almoçar conosco, não é? Está de passagem? Se precisar de um lugar pra passar a noite, minha casa está à sua disposição!

- Ah, obrigado. Na verdade, eu vinha na esperança de encontrar...

- Já sei. O tio e a tia faleceram há mais de dois ano. Os dois morreram de velhice, penso eu. Apesar de dizerem por aí que o tio morreu foi de tristeza. Ele morreu menos de um ano depois da tia.

Zand abaixa lentamente a cabeça, em confirmação.

- Me desculpe falar desses assuntos assim. Deve ser muito chato. Mas diga: o que tem feito? Andado pelo mundo? Ouvi falar de um Zand que tinha derrotado o dragão e ficava pensando comigo mesmo: só pode ter sido meu primo Zand!

- Dragão!? Não fala besteira, pai! Ele toca música! Toca uma, primo!

- Menina, respeite seu pai! - Globru olha sério para a filha, voltando-se em seguida para a visita. - Desculpa isso, Zand. Ela está assim ultimamente, respondona. Deve ser coisa da idade.

- Não, tudo bem.

- De qualquer forma, depois gostaria sim de ouvir você tocar alguma coisa. - Globru fala, empolgado, colocando a filha no colo. Logo depois se inclina em direção à cozinha para gritar. - Xepyana! Cadê a comida?


Um almoço agitado é o que acontece naquela casa. É durante o almoço que Zand fala sobre o golpe em Noak e sobre como foi lá e conseguiu derrotar os criminosos. Oculta, porém, a dolorosa parte que envolve Knova.

Também é nesse almoço que Zand ouve as novidades de Uah. E até que há algumas novidades, a despeito da pequenez da cidade. Zand descobre, por exemplo, sobre o castelo. Na verdade é uma mansão com ares de castelo, que foi erguida pelo prefeito de Uah. De onde viera tanto dinheiro para se erguer uma mansão em pouco tempo? O povo não sabe. Uns falam de negócios ilegais, outros de prêmio por parte do rei de Wimow.

Ao fim do almoço, os quatro se reunem na varanda. Zand toca algumas canções para eles, dedilhando com maestria a bela Lira de Knova.

- Toca muito bem, primo!

- Obrigado!

- Fica aqui conosco uns tempos!

- Hmmm... Não sei.

- Ora, precisa repousar uns dias!

- É verdade. - Xepyana, abraçada ao marido, opina também. - Bem se vê que ainda não está curado por completo.

- Se ficar andando pra cima e pra baixo por aí pode acabar piorando, primo!

- Tudo bem. - Zand se dá por vencido. - Vocês tem razão. Tenho que repousar. Vou ficar por aqui uns dias.

- Êêêêêêê! - Fran comemora com os braços pra cima.

- Mas queria que fizesse uma coisa por mim.

- Claro, primo! Manda!

- Gostaria de ver onde meus pais foram enterrados.

- Claro... Vamos lá. Posso te levar ainda hoje se quiser.

- E o trabalho, amor? - Xepyana olha preocupada.

- Ah, mulher... - Globru responde, se sacudindo um pouco. - Hoje é um dia especial. Não é sempre que recebemos uma visita tão ilustre e querida! Vamos quando quiser, primo!

- Obrigado.


É estranho para Zand ver as lápides ali, com os nomes de seus pais. Já era próximo o fim da tarde quando ele foi visitar o cemitério, levado por Globru.

Ao voltarem, como não poderia deixar de ser, Globru aproveitou para apresentar o primo a todos pelo caminho. Alguns – os mais velhos – se lembravam daquele menino que atraia os aventureiros e sonhava com missões perigosas. Por fim, chegam ao Bar de Uah.

Mais alguns param para ver aquele aventureiro importante, que é conterrâneo desse povo. A festa para com a chegada de um grupo de viajantes afobados.

- Vimos de Awra. Chegaram navios recentemente e a coisa por lá não está boa.

- Navios? Que navios?

- Navios de Noak.

Zand congela frente à notícia. Parte com Globru de volta para casa o quanto antes e, lá chegando, sem esperar, vai até a Lira de Knova.

Após uma melodia que seu primo e família acham estranha, Zand para surpreso e apenas fala.

- Eve... Tenho que partir para Beniw.

24 mar 2012

Amanhecer de uma Era

Submitted by bardo

“No alvorecer de mais um dia, uma figura espantosa chama a atenção de milhares de mortais. Uma figura magnífica. Um homem alado é visto vindo do horizonte. A Terra treme sob sua sombra e o homem receia perante seu esplendor. E teme. Teme que finalmente tenham vindo quitar seus pecados.”

Jornais de todo o planeta tentam registrar o momento. Padres e cristãos choram em desespero. Jamais se viu algo que afetasse todo a Terra dessa forma. Hoje os pecadores, que há tanto buscavam consolo, não conseguem acreditar no que ouvem, no que vêem. Não conseguem acreditar que os céus finalmente enviaram seu carrasco.

A Terra jamais foi a mesma depois daquele dia. A visão de um ser sobrenatural por toda a população do mundo com certeza o muda para sempre. Alguns tentaram contestar o que parecia óbvio para todos. Diziam que essa entidade não era divina. Uns afirmavam se tratar de um humano com órgãos extra. Esses sempre entravam em conflito com os anatomistas. Outros diziam que, como um organismo aparentemente tão frágil quanto um humano, seriam seres como nós, porém de outro planeta. A igreja e muitos outros mais se digladiavam com os detentores dessa idéia.

Esse anjo logo mostrou-se mais real que um anjo de nossos sonhos. Não parecia ser imortal ou invencível. Outro detalhe muito importante: ele não sabia falar nenhum dos nossos idiomas, mas outro totalmente diferente e desconhecido dos maiores lingüísticos do mundo. Ao contrário de Gabriel que, segundo a Bíblia, comunicava-se sem problemas com os mortais a que aparecia. Um ponto para a teoria do extraterrestre.

Ele não teve dificuldades para aprender a se comunicar através do inglês, mas depois de aprender algumas palavras, uma nova revelação foi feita: ele tinha amnésia. Não sabia de onde veio nem aonde ia. Após isso o mundo formado a seu redor caiu. A esperança de saber como é o céu, de que houvesse justiça. Tudo foi por água abaixo. O mundo voltou ao seu funcionamento normal. Seguindo sempre cada um por si e deus por todos. E o pior, o caso logo foi esquecido pela população ou, pelo menos, fingiram tê-lo esquecido.

Em um complexo seguro e cercado por militares dos mais poderosos, aquele ser não sabia o que o destino lhe reservava. Nas salas de acesso restrito, possuidores da ciência se reuniam. Recebiam naquele momento uma missão. Uma missão de importância primordial: uma autópsia precisava ser feita. Eles, totalmente convicto de que o ser tratado era extraterrestre, precisavam saber como exatamente funcionava. Como podia ter asas. Como elas se ligavam. Precisavam saber disso, para o bem da humanidade, pensando em um futuro próspero.

Pelos corredores corriam boatos de que o anjo havia vindo à Terra em uma espécie de espaçonave. E que ela havia sido tomada pela NASA. Mas isso agora não importava. Além da amnésia, o anjo tinha os dias contados. Exatamente três dias após ocorreria seu assassinato e sua dissecação.

Impossibilitado de manter minha posição de impassividade, agi. Faltando dois dias para a execução do projeto, tentei sabotar todos os equipamentos. Claro que, como uma pessoa prudente, não podia deixar isso para a véspera. Mas mesmo agindo com antecedência, não consegui terminar meu trabalho. Uma última idéia me veio minutos antes da hora combinada. Como havia posto minhas mãos em tudo, poderia forçar uma passagem aérea e atordoar a equipe enquanto o anjo escapava. Não parecia um bom plano, mas foi o único que me surgiu de última hora com alguma chance de funcionar. Coloquei-o em ação. O anjo percebeu o que tramavam para ele quando a equipe chegou levando um equipamento pesado, com um olhar frio. Após libertá-lo e atordoar quase todo o grupo, o anjo finalmente conseguiu fugir.

Como em débito, resolveu me levar junto. E agora que saímos tudo simplificou. Se consegui vencer cientistas, por que não conseguirei lutar contra todas as forças armadas estadunidenses?

23 mar 2012

União Livre (de quem?)

Submitted by bardo

"O objetivo desse projeto é descontinuar as atuais distribuições Linux do Brasil." É com essas palavras que o site do projeto União Livre começa a anunciar sua intenção: que o Brasil tenha uma distribuição GNU/Linux só.

Essa ideia de que existe um excesso de distribuições e que uma distribuição única seria a solução parece genial a um novato na área, mas se você analisar bem o cenário percebe facilmente o quanto é falha.

O grande problema dessa ideia é que o fato de haver muitas distribuições não é o problema. O problema acontece quando uma distribuição é criada e se mantém sem uma razão sólida. São duas situações distintas e que devem ser separadas.

Uma ideia de "unificar" ignora que distribuições tem seus motivos de existirem, não se resumem a "juntar usuários". Há distribuição que existe para atender a necessidades de certo perfil de usuários, outras que focam a divulgação de certas ferramentas ou ideais e por aí vai. É também frequente que os motivos de uma conflitem diretamente com os motivos de outra. Um exemplo simples? Uma distribuição quer facilitar ao máximo para os usuários enquanto outra quer se alinhar ao máximo com os conceitos de Software Livre. O que temos? "Facilitar ao máximo" exige abrir mão de certas liberdades, levando a equipe a embutir Adobe Flash, drivers fechados, dentre outras "facilidades". Isso não é conciliável com a outra meta.

Foi apenas um exemplo. Se considerarmos outras guerras como KDE versus GNOME (versus Unity versus GNOME 2 versus MATE versus...), por si só já justificaria divisões. Não adianta argumentar que elas podem entrar em concenso, pois as razões muitas vezes são complexas. Um dirá que adora a API do GTK+ e de todo o GNOME, enquanto outro dirá que a identidade visual do KDE é mais sólida; outro dirá que prefere o GNOME antigo, enquanto outro entende e aceita as vantagens que a Canonical defende para justificar seu Unity. Entendem? Geralmente não é só uma questão estética (só no caso de algumas ditas distribuições, que não passam de seleção de pacotes e criação de papéis de parede).

Você pode dizer: "Beleza, então faz uma distribuição que junte tudo num pacote só e fica todo mundo feliz." Será? O tamanho da distribuição resultante também pode ser um objetivo de algumas distribuições. Outras podem estar muito presas a certas distribuições internacionais específicas. Se uma distribuição quer "a melhor performance possível", não vai abrir mão de ser derivada do seu Arch Linux (suposição).

A despeito disso, "uma distribuição única" costuma ser algo pedido pelos usuários, por terem a percepção de que há desperdício de forças em um cenário tão amplo. Há mesmo? Muitas vezes sim, mas há outras soluções para isso. Os projetos podem se ajudar mais, trocar informações e ferramentas menores entre si, publicar mais o que é feito (muitas vezes ferramentas interessantes são criadas por pequenas distribuições e mantidas como "diferencial" ao invés de serem amplamente divulgadas como ferramentas para serem incorporadas por outros projetos).

Percebem como a multiplicidade de distribuições é algo complexo? Se ainda quiserem ver mais sobre a ideia de unificar distribuições, leiam uma discussão antiga minha com Sergio Tucano. Pois bem, vamos voltar ao caso específico da União Livre. O que vemos aqui? Um chamado anônimo aos mantenedores das milhares (?) de distribuições nacionais. Ao invés de assinar embaixo (identificando-se o/os autor/es da proposta perante a sociedade), ele(s) cria(m) um abaixo-assinado.

Por que não, ao invés de querer unificar, fazer uma consulta a cada distribuição, fazendo um levantamento das razões de sua existência? E a partir daí se tentar um MMC das distribuições (o que provavelmente não significaria uma distribuição única)? Não é preciso uma fundação para isso, nem é preciso unificar todas em uma só (e uma nova, ainda mais).

O que vejo é uma distribuição relativamente antiga no Brasil e uma mais nova: respectivamente, Big Linux e SimbiOS. As duas parecem ter os mesmos objetivos de agradar usuários leigos, agregando facilidades, de modo que não duvido que a ideia tenha surgido entre eles. E é uma boa ideia as duas integrarem esforços (mudando ou não de nome), só acho que não havia necessidade desse auê todo. Toda prepotência.

E ainda adotando o pomposo nome de União Livre (que adota drivers, browsers e outros aplicativos privativos). Quem vai entrar nessa canoa?

23 mar 2012

Se você não tem nada a ver com programação, nem tem interesse no assunto, simplesmente ignore este artigo.


Mike Driscoll tem um blog dedicado a Python chamado The Mouse vs. the Python e eventualmente há excelentes artigos por lá.

Esta é uma tradução livre do artigo Reportlab: Converting Hundreds of Images Into PDFs e modifiquei sutilmente algumas coisas, incluindo os exemplos. Agradeço ao Mike pelos excelentes artigos e me desculpo pelas liberdades que tomei na tradução (incluindo a mudança no nome do artigo). Vamos a ele!


Recentemente me pediram para converter algumas centenas de imagens em páginas de um PDF. Um amigo meu desenha comics e meu irmão queria poder lê-lo em um tablet. Acontece que se você tem um monte de arquivos nomeados assim:

'Jia_01.Jpg', 'Jia_02.Jpg', 'Jia_09.Jpg', 'Jia_10.Jpg', 'Jia_11.Jpg', 'Jia_101.Jpg'

o tablet Android vai reordená-los mais ou menos assim:

'Jia_01.Jpg', 'Jia_02.Jpg', 'Jia_09.Jpg', 'Jia_10.Jpg', 'Jia_101.Jpg', 'Jia_11.Jpg'

E se torna muito confuso ler com os arquivos fora de ordem desse jeito. Infelizmente, até mesmo o Python ordena os arquivos desse modo. Tentei usar o módulo glob diretamente e então ordenar o resultado e resultou no mesmo problema. Assim a primeira coisa que eu tinha que fazer era achar algum tipo de ordenação que organizasse os arquivos corretamente. Deve ser notado que o Windows 7 pode ordenar os arquivos corretamente no sistema de arquivos, mas o Python não.

Depois de uma pequena busca no Google, encontrei o seguinte script no StackOverflow:

import re
 
#----------------------------------------------------------------------
def sorted_nicely( l ):
    """
    Sort the given iterable in the way that humans expect.
    """
    convert = lambda text: int(text) if text.isdigit() else text
    alphanum_key = lambda key: [ convert(c) for c in re.split('([0-9]+)', key) ]
    return sorted(l, key = alphanum_key)

Funcionou perfeitamente! Agora eu só tinha que arrumar um jeito de colocar cada página da HQ em sua própria página dentro do arquivo PDF. Felizmente, a biblioteca reportlab torna essa tarefa muito fácil de realizar. Você só precisa percorrer as imagens e inserí-las uma a uma em uma página. É mais fácil dar uma olhada no código, assim vejamos:

import glob
import os
import re
 
from reportlab.lib.pagesizes import letter
from reportlab.platypus import SimpleDocTemplate, Paragraph, Image, PageBreak
from reportlab.lib.units import inch
 
#----------------------------------------------------------------------
def sorted_nicely( l ):
    """
    # http://stackoverflow.com/questions/2669059/how-to-sort-alpha-numeric-set-in-python
 
    Sort the given iterable in the way that humans expect.
    """
    convert = lambda text: int(text) if text.isdigit() else text
    alphanum_key = lambda key: [ convert(c) for c in re.split('([0-9]+)', key) ]
    return sorted(l, key = alphanum_key)
 
#----------------------------------------------------------------------
def create_comic(fname, front_cover, back_cover, path):
    """"""
    filename = os.path.join(path, fname + ".pdf")
    doc = SimpleDocTemplate(filename,pagesize=letter,
                            rightMargin=72,leftMargin=72,
                            topMargin=72,bottomMargin=18)
    Story=[]
    width = 7.5*inch
    height = 9.5*inch
 
    pictures = sorted_nicely(glob.glob(path + "\\%s*" % fname))
 
    Story.append(Image(front_cover, width, height))
    Story.append(PageBreak())
 
    x = 0
    page_nums = {100:'%s_101-200.pdf', 200:'%s_201-300.pdf',
                 300:'%s_301-400.pdf', 400:'%s_401-500.pdf',
                 500:'%s_end.pdf'}
    for pic in pictures:
        parts = pic.split("\\")
        p = parts[-1].split("%s" % fname)
        page_num = int(p[-1].split(".")[0])
        print "page_num => ", page_num
 
        im = Image(pic, width, height)
        Story.append(im)
        Story.append(PageBreak())
 
        if page_num in page_nums.keys():
            print "%s created" % filename
            doc.build(Story)
            filename = os.path.join(path, page_nums[page_num] % fname)
            doc = SimpleDocTemplate(filename,
                                    pagesize=letter,
                                    rightMargin=72,leftMargin=72,
                                    topMargin=72,bottomMargin=18)
            Story=[]
        print pic
        x += 1
 
    Story.append(Image(back_cover, width, height))
    doc.build(Story)
    print "%s created" % filename
 
#----------------------------------------------------------------------
if __name__ == "__main__":
    path = r"C:\Users\Mike\Desktop\Sam's Comics"
    front_cover = os.path.join(path, "FrontCover.jpg")
    back_cover = os.path.join(path, "BackCover2.jpg")
    create_comic("Jia_", front_cover, back_cover, path)

Vamos detalhar isso um pouco. Como sempre ocorre, você tem alguns imports necessários que são exigidos para que o código funcione. Você vai notar que nós também temos dentro do código a função sorted_nicely de que falamos anteriormente. A função principal se chama create_comic e recebe quatro parâmetros: fname, front_cover, back_cover, path. Se você já usou o reportlab antes, deve ter reconhecido o SimpleDocTemplate e o Story, que são mostrados no referido tutorial

De qualquer forma, você faz um laço (loop) nas imagens ordenadas e vai adicionando as imagens ao Story, sempre com um objeto PageBreak. A razão de haver um condicional dentro do laço é que eu descobri que se eu tentar construir o PDF com todas as 400+ imagens, termina ocorrendo um erro de memória. Assim eu quebrei o trabalho em uma série de documentos onde cada um tem 100 páginas ou menos. Ao final do documento, você tem que chamar o método build do objeto doc para criar o documento PDF propriamente.

Agora você sabe como eu converti um monte de imagens em alguns documentos PDF. Teoricamente, você pode usar o PyPdf para juntar todos os PDFs resultantes em um PDF único, mas eu não tentei fazer isso. Pode ser que apareça um outro erro de memória. Deixo esse teste como um exercício para o leitor.

P. S.: A foto deste post é de NobMouse.

Special: 
22 mar 2012

Os Índios e o Monstro do Espaço

Os índios olhavam o céu
O céu sempre esteve por lá
Mas a noite trouxe ao lugar
Espanto que ninguém sonhou
Brilhando à luz do luar
Viram um navio baixar
Na floresta o barco atracou

Peri, corajoso, saltou
Correu, galopou para o "cais"
Correu o coração ainda mais
O barco era mesmo tamanho
Junto a força dos ancestrais
Correu com seu povo atrás
O barco tinha um brilho estranho

"Que barco gigante! Medonho!"
Peri via o barco dormir
Logo que chegaram ali
O suor corria da testa
Juntou seus irmãos o Peri
"Como veio o barco até aqui?
Do céu no meio da floresta?"

E o barco mostrou que não presta
Barulho calou seus ouvidos
Pancadas, fumaça, rugidos
"E agora o que será de nós?!"
Os índios olhavam aturdidos
Desacreditando os sentidos:
O barco era um monstro feroz

E o barco gritou logo após
A forma não era de barco
A ilusão passou, viram o casco
De uma tartaruga de aço
E Peri se sentiu tão fraco
Diante do barco - que barco? -
Diante do monstro do espaço

Num giro de pata, um pedaço
Da floresta foi pelos ares
Os índios rolavam aos pares
Fugindo dos golpes da fera
"São fortes as bestas lunares"
Logo não houve mais lugares
Protegidos dessa quimera

Depois do cansaço a espera
Do golpe que finda essa vida
Os índios viram em despedida
Com dor e tristeza no olhar
A fera ainda enlouquecida
Olhando com a pata erguida
Foi quando ele quis chegar

Chegando de qualquer lugar
Disparou com o canhão do braço
Bolas de luz no ser do espaço
Era um ser de aço também
Tiros deixam o monstro em pedaços
E o menino azul dá um passo
E diz se chamar Megaman

E a criança volta pro além
E a tribo respira em paz
Mas essa noite foi demais
Louca demais pra um ser humano
A noite em que seres fatais
Corrompem as regras normais
Com aço animado profano!

Pois viram debaixo do pano
Que o mundo é muito maior
Como podem dormir sem dor?
Como será a noite que vem?
Essa noite um monstro chegou
Na noite que um robô salvou
Quem não esperava ninguém

-- Cárlisson Galdino

Special: 

Páginas

Subscribe to Cordeis.com RSS