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 Creating QR Codes with Python e modifiquei sutilmente algumas coisas, incluindo os exemplos.
QR Code, para quem não sabe, é um estilo de código de barras bidimensional, podendo conter um fragmento de texto, o endereço de um site, um email ou mesmo uma ficha de informações pessoais básicas (reunindo tudo isso). Veja mais sobre esses códigos na Wikipedia.
Outro dia eu pensei que seria divertido criar em wxPython um pequeno programa que gerasse códigos QR e os mostrasse na tela. Eu queria fazer tudo com Python, assim eu procurei e encontrei 3 candidatos:
Testei o python-qrcode e o pyqrnative uma vez já que ambos funcionam tanto no Windows quanto no Mac e no Linux. Eles também não requerem nada a não ser o Python Imaging Library. O projeto pyqrcode requer vários outros pré-requisitos e não funciona em Windows, assim eu nem quis mexer nele. Terminei pegando algum código antigo baseado na minha aplicação Photo Viewer e o modificando levemente para torná-lo um visualizador de QR Code. Se isso te interessa, então continue lendo!
Começando
Como eu disse no início, você precisará da Python Imaging Library. Usaremos o wxPython para fazer a parte gráfica, assim você precisará deles também. E você vai ter que usar o python-qrcode ou o pyqrnative. A principal diferença que achei é que o python-qrcode é muito mais rápido na geração de imagens e gera o tipo que provavelmente você vai ver por aí. Por alguma razão, pyqrnative leva mais tempo pra executar e gera QR codes de aspecto muito mais denso. Deve haver opções para esses projetos que nos permitam gerar diferentes tipos de códigos, mas a documentação para ambos é abismal. Terminei usando o código e a IDE Wingware para navegar pelo código mais do que qualquer outra coisa.
Gerando QR Codes
De qualquer forma, uma vez que você tenha os pré-requisitos, você pode executar o seguinte código e ver o que o Python pode fazer:
# coding: utf-8
import os
import wx
try:
import qrcode
except ImportError:
qrcode = None
try:
import PyQRNative
except ImportError:
PyQRNative = None
########################################################################
class QRPanel(wx.Panel):
""""""
#----------------------------------------------------------------------
def __init__(self, parent):
"""Constructor"""
wx.Panel.__init__(self, parent=parent)
self.photo_max_size = 240
sp = wx.StandardPaths.Get()
self.defaultLocation = sp.GetDocumentsDir()
img = wx.EmptyImage(240,240)
self.imageCtrl = wx.StaticBitmap(self, wx.ID_ANY,
wx.BitmapFromImage(img))
qrDataLbl = wx.StaticText(self, label="Texto a transformar no QR Code:")
self.qrDataTxt = wx.TextCtrl(self, value="http://www.mousevspython.com", size=(200,-1))
instructions = "Nome do arquivo do QR Code"
instructLbl = wx.StaticText(self, label=instructions)
self.qrPhotoTxt = wx.TextCtrl(self, size=(200,-1))
browseBtn = wx.Button(self, label='Change Save Location')
browseBtn.Bind(wx.EVT_BUTTON, self.onBrowse)
defLbl = "Default save location: " + self.defaultLocation
self.defaultLocationLbl = wx.StaticText(self, label=defLbl)
qrcodeBtn = wx.Button(self, label="Criar QR com qrcode")
qrcodeBtn.Bind(wx.EVT_BUTTON, self.onUseQrcode)
pyQRNativeBtn = wx.Button(self, label="Criar QR com PyQRNative")
pyQRNativeBtn.Bind(wx.EVT_BUTTON, self.onUsePyQR)
# Create sizer
self.mainSizer = wx.BoxSizer(wx.VERTICAL)
qrDataSizer = wx.BoxSizer(wx.HORIZONTAL)
locationSizer = wx.BoxSizer(wx.HORIZONTAL)
qrBtnSizer = wx.BoxSizer(wx.VERTICAL)
qrDataSizer.Add(qrDataLbl, 0, wx.ALL, 5)
qrDataSizer.Add(self.qrDataTxt, 1, wx.ALL|wx.EXPAND, 5)
self.mainSizer.Add(wx.StaticLine(self, wx.ID_ANY),
0, wx.ALL|wx.EXPAND, 5)
self.mainSizer.Add(qrDataSizer, 0, wx.EXPAND)
self.mainSizer.Add(self.imageCtrl, 0, wx.ALL, 5)
locationSizer.Add(instructLbl, 0, wx.ALL, 5)
locationSizer.Add(self.qrPhotoTxt, 0, wx.ALL, 5)
locationSizer.Add(browseBtn, 0, wx.ALL, 5)
self.mainSizer.Add(locationSizer, 0, wx.ALL, 5)
self.mainSizer.Add(self.defaultLocationLbl, 0, wx.ALL, 5)
qrBtnSizer.Add(qrcodeBtn, 0, wx.ALL, 5)
qrBtnSizer.Add(pyQRNativeBtn, 0, wx.ALL, 5)
self.mainSizer.Add(qrBtnSizer, 0, wx.ALL|wx.CENTER, 10)
self.SetSizer(self.mainSizer)
self.Layout()
#----------------------------------------------------------------------
def onBrowse(self, event):
""""""
dlg = wx.DirDialog(self, "Escolher um diretório:",
style=wx.DD_DEFAULT_STYLE)
if dlg.ShowModal() == wx.ID_OK:
path = dlg.GetPath()
self.defaultLocation = path
self.defaultLocationLbl.SetLabel("Local de salvamento: %s" % path)
dlg.Destroy()
#----------------------------------------------------------------------
def onUseQrcode(self, event):
"""
https://github.com/lincolnloop/python-qrcode
"""
qr = qrcode.QRCode(version=1, box_size=10, border=4)
qr.add_data(self.qrDataTxt.GetValue())
qr.make(fit=True)
x = qr.make_image()
qr_file = os.path.join(self.defaultLocation, self.qrPhotoTxt.GetValue() + ".jpg")
img_file = open(qr_file, 'wb')
x.save(img_file, 'JPEG')
img_file.close()
self.showQRCode(qr_file)
#----------------------------------------------------------------------
def onUsePyQR(self, event):
"""
http://code.google.com/p/pyqrnative/
"""
qr = PyQRNative.QRCode(20, PyQRNative.QRErrorCorrectLevel.L)
qr.addData(self.qrDataTxt.GetValue())
qr.make()
im = qr.makeImage()
qr_file = os.path.join(self.defaultLocation, self.qrPhotoTxt.GetValue() + ".jpg")
img_file = open(qr_file, 'wb')
im.save(img_file, 'JPEG')
img_file.close()
self.showQRCode(qr_file)
#----------------------------------------------------------------------
def showQRCode(self, filepath):
""""""
img = wx.Image(filepath, wx.BITMAP_TYPE_ANY)
# redimensionar imagem, preservando proporção
W = img.GetWidth()
H = img.GetHeight()
if W > H:
NewW = self.photo_max_size
NewH = self.photo_max_size * H / W
else:
NewH = self.photo_max_size
NewW = self.photo_max_size * W / H
img = img.Scale(NewW,NewH)
self.imageCtrl.SetBitmap(wx.BitmapFromImage(img))
self.Refresh()
########################################################################
class QRFrame(wx.Frame):
""""""
#----------------------------------------------------------------------
def __init__(self):
"""Constructor"""
wx.Frame.__init__(self, None, title="Visualizador de QR Code", size=(550,500))
panel = QRPanel(self)
if __name__ == "__main__":
app = wx.App(False)
frame = QRFrame()
frame.Show()
app.MainLoop()
O código para modificar e exibir imagens é tratado no artigo anterior que eu escrevi (e com link acima), assim as únicas partes com que você provavelmente terá que se preocupar são dois métodos para gerar códigos QR: onUseQrcode e onUsePyQR. Eu apenas peguei alguns exemplos de seus respectivos sites e os modifiquei para criar as imagens de códigos QR. Eles são muito simples, mas não são bem documentados, de modo que eu não posso realmente lhe dizer o que está acontecendo neles. Infelizmente, no momento em que escrevia este texto, o código desses projetos carece seriamente de comentários, com apenas alguns aqui e ali. Ainda assim, eu estava apto a gerar códigos QR decentes. O código a seguir foi feito usando python-qrcode.
Como vovcê podever, é um código padrão bastante simples. O próximo foi criado com PyQRNative e tem um aspecto muito mais denso:
Tentei escanear ambas as imagens com o aplicativo leitor de códigos debarra do meu celular com android e ambos os códigos QR foram corretamente lidos por ele. Assim, se você precisa gerar códigos QR para o seu projeto, tenho esperanças de que ao menos um dos dois atenda às suas necessidades!
ATUALIZAÇÃO 21/05/2012
Um dos meus leitores (Mike Farmer) me contactou recentemente sobre seus experimentos com PyQRNative e me disse que "o primeiro parâmetro é o tamanho do container e o segundo é a correção de redundância/erro". Eu meio que adivinho o que o primeiro parâmetro quer dizer, mas realmente não entendi isso de correção de erro. Felizmente, Sr. Farmer me explicou isso: Se a correção de erros é menor, manchas e marcas não serão toleradas na leitura. Se aumentar o nível de erro, obviamente o código qr será aumentado, mas o que foi feito foi a duplicação dos dados dentro da etiqueta. Assim, se a etiqueta for manchada ou rasgada, ainda poderá sr possível ler e recuperar os dados restantes. Deste modo, se sua aplicação estiver criando etiquetas que podem ser danificadas, é sábio aumentar a correção de erros. Você também pode fazer coisas legais com isso, como sobrepor imagens ou textos na tag, aumentando a correção de erros, fazendo com que os dados redundantes tolerem o "dano". De qualquer forma, se você mudar o primeiro número, você pode expandir o tamanho do da imagem do código QR. Por que você faria isso? Bem, quanto mais informações você precisar guardar na imagem, maior ela precisará ser. Sr. Farmer veio com um código de testes divertido que nos ajuda a descobrir qual o tamanho mínimo que um código QR deve ter. Estou reproduzindo o código a seguir:
import PyQRNative
def makeQR(data_string,path,level=1):
quality={1: PyQRNative.QRErrorCorrectLevel.L,
2: PyQRNative.QRErrorCorrectLevel.M,
3: PyQRNative.QRErrorCorrectLevel.Q,
4: PyQRNative.QRErrorCorrectLevel.H}
size=3
while 1:
try:
q = PyQRNative.QRCode(size,quality[level])
q.addData(data_string)
q.make()
im=q.makeImage()
im.save(path,format="png")
break
except TypeError:
size+=1
P. S.: foto usada no post: QRCode Piggy Bank, de B3OK.