Você está na página 1de 16

ZXing: Como ler cdigos de

barras em Java
Veja neste artigo como usar a biblioteca Zxing em Java para
fazer leitura de cdigo de barras em imagens.
(1) (0)

Neste artigo veremos o uso prtico de uma biblioteca chamada


de Zxing, que tem por objetivo trabalhar com cdigo de barras 1D e
2D. Mas, primeiro, devemos entender o que um cdigo de barras e
como ele funciona.
O Cdigo de Barras uma representao grfica de dados numricos
ou alfanumricos, estes esto presentes com muita frequncia no
nosso dia a dia e tem a representao como na Figura 1.

Figura 1. Ilustrao de um Cdigo de Barras


A decodificao ou leitura da Figura 1 realizada da seguinte forma:
um scanner (leitor de cdigo de barras) emite um raio vermelho que

percorre todas as barras e onde a barra for escura, a luz absorvida,


e onde for branca (espaos em branco) a luz refletida para o
scanner e no computador feita a converso para nmeros ou letras.
Existem diversos formatos de cdigo de barras, por exemplo: Cdigo
39, EAN-13, GS1-128, DUN-14 e etc. Cada um destes tem sua
especificidade, por exemplo: o cdigo 39 ou Code 39 possibilita a
codificao de letras e nmeros e mais alguns smbolos especiais.
Obviamente que o conceito apresentado aqui foi apenas introdutrio
em relao ao funcionamento do cdigo de barras para que voc leitor
possa continuar lendo o restante do artigo com mais confiana no
assunto tratado. Existem muitas mais caractersticas em relao a
cada formatao e como elas so feitas, mas no foco do nosso
artigo apresentar tais conceitos e sim o funcionamento na prtica
da biblioteca Zxing.

Zxing
Nem sempre temos o leitor de cdigo de barras (scanner) em mos ou
temos situaes em que precisamos dispensar o seu uso e aqui que
entra a API Zxing. Para entender melhor, vamos a um cenrio real: O
seu sistema deve possuir um mdulo onde o usurio far o upload de
contratos assinados pelo seu cliente (imagens) e o sistema deve
associar automaticamente estas imagens com o cliente correto sem
nenhuma interveno humana. Na capa do contrato, que pode possuir
N folhas, h um cdigo de barras que identifica a numerao do

contrato (a numerao do contrato possui o cdigo do cliente em sua


composio)."
Sendo assim, ns podemos usar o Zxing para ler a capa do contrato
e extrair a numerao contida no cdigo de barras e aps extrao da
numerao ns podemos buscar o cliente correspondente. Dado o
cenrio exposto, ns podemos perceber que o Zxing muito til
quando precisamos ler as informaes contidas no cdigo de barras e
no temos a disponibilidade de um leitor de cdigo de barras ou
mesmo no podemos utilizar, como mostrado no cenrio. Neste artigo
veremos apenas como fazer a leitura de um cdigo de barras atravs
de uma imagem que contenha tal cdigo, mas vale ressaltar que
o Zxing tambm realiza a criao de cdigo de barras a partir do valor
informado.
O primeiro passo para usar a API Zxing no nosso projeto fazer a
importao das bibliotecas necessrias (o link de download est no
final do artigo). Coloque estas no classpath do seu projeto para que
possa usar as classes que veremos mais a frente.
Vejamos agora como ficar a interface da nossa aplicao na Figura
2.

Figura 2. Interface da nossa aplicao


A nossa aplicao contm quatro componentes que sero de grande
utilidade: o primeiro o campo de texto onde ser mostrado o
caminho da imagem que selecionamos, o segundo o resultado do
valor extrado do cdigo de barras, o terceiro o boto 'Selecionar
Imagem' que nos possibilita selecionar uma imagem do nosso
computador e o quarto boto 'Processar' inicia o processamento
do Zxing que far a leitura do cdigo de barras e extrao dos valores
necessrios.
Agora vejamos como ficou nosso arquivo .form para quem desejar
criar a interface apresentada naFigura 2, no Netbeans.
Listagem 1. Fzxing.form
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.3"
type="org.netbeans.modules.form.forminfo.JFrameFormInfo">
<Properties>
<Property name="defaultCloseOperation" type="int" value="3"/>
</Properties>
<SyntheticProperties>
<SyntheticProperty name="formSizePolicy" type="int" value="1"/>
</SyntheticProperties>

<AuxValues>
<AuxValue name="FormSettings_generateMnemonicsCode"
type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_layoutCodeTarget"
type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle"
type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal"
type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier"
type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jLabel1" alignment="0" min="-2"
max="-2" attributes="0"/>
<Component id="jLabel2" alignment="0" min="-2"
max="-2" attributes="0"/>
<Component id="jTextFieldImagem" alignment="0"
min="-2" pref="329" max="-2" attributes="0"/>
<Component id="jTextFieldResultado" alignment="0"
min="-2" pref="329" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="jButtonSelecionar" min="-2"
max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jButtonProcessar" min="-2"
max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace pref="25" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>

<Component id="jLabel1" min="-2" max="-2"


attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jTextFieldImagem" min="-2" max="-2"
attributes="0"/>
<EmptySpace min="-2" pref="25" max="-2"
attributes="0"/>
<Component id="jLabel2" min="-2" max="-2"
attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jTextFieldResultado" min="-2" max="-2"
attributes="0"/>
<EmptySpace min="-2" pref="20" max="-2"
attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jButtonSelecionar" alignment="3"
min="-2" max="-2" attributes="0"/>
<Component id="jButtonProcessar" alignment="3"
min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="jLabel1">
<Properties>
<Property name="text" type="java.lang.String"
value="Imagem"/>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabel2">
<Properties>
<Property name="text" type="java.lang.String"
value="Resultado"/>
</Properties>
</Component>
<Component class="javax.swing.JTextField"
name="jTextFieldImagem">
<Properties>
<Property name="enabled" type="boolean" value="false"/>
</Properties>

</Component>
<Component class="javax.swing.JTextField"
name="jTextFieldResultado">
</Component>
<Component class="javax.swing.JButton" name="jButtonSelecionar">
<Properties>
<Property name="text" type="java.lang.String"
value="Selecionar Imagem"/>
</Properties>
<Events>
<EventHandler event="actionPerformed"
listener="java.awt.event.ActionListener"
parameters="java.awt.event.ActionEvent"
handler="jButtonSelecionarActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="jButtonProcessar">
<Properties>
<Property name="text" type="java.lang.String"
value="Processar"/>
</Properties>
<Events>
<EventHandler event="actionPerformed"
listener="java.awt.event.ActionListener"
parameters="java.awt.event.ActionEvent"
handler="jButtonProcessarActionPerformed"/>
</Events>
</Component>
</SubComponents>
</Form>

O cdigo acima dispensa comentrio, pois ele servir apenas para


que voc possa reproduzir a mesma interface no seu ambiente de
desenvolvimento, caso seja o Netbeans.
Enfim comearemos a construir os mtodos de cada boto acima e
depois mostraremos como ficou nossa classe Fzxing por completo.
Listagem 2. Mtodo do boto 'Selecionar Imagem'

private void
jButtonSelecionarActionPerformed(java.awt.event.ActionEvent evt)
{//GEN-FIRST:event_jButtonSelecionarActionPerformed
JFileChooser fChooser = new JFileChooser();
fChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
if (fChooser.showSaveDialog(this) != 1){
File fImage = fChooser.getSelectedFile();
try {
buffImage = ImageIO.read(fImage);
jTextFieldImagem.setText(fImage.getAbsolutePath());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}//GEN-LAST:event_jButtonSelecionarActionPerformed

O nosso boto jButtonSelecionar possui um listener que dispara o


mtodo jButtonSelecionarActionPerformed(), que chamado toda vez
que o usurio clicar no boto. NaListagem 2 temos exatamente a
demonstrao do mtodo que possibilita a seleo da imagem. Logo
na primeira e segunda linhas temos a criao de um objeto
JfileChooser e a configurao do modo de seleo para FILES_ONLY,
assim, restringimos a escolha do usurio apenas para arquivos e no
diretrios. Continuando a codificao, ns temos uma condio que
abre um dilogo do tipo 'saveDialog' e, caso o usurio escolha um
arquivo, em vez de clicar em cancelar, o resultado ser diferente de 1
e entramos na condio proposta.
Dentro da condio proposta ns capturamos o arquivo escolhido
atravs do fchooser.getSelectedFile() e logo depois transformamos o
arquivo, que deve ser uma imagem, em um BufferedImage, no
esquecendo de mostrar o caminho da imagem no campo

jTextFieldImagem. Todo esse processo faz com que armazenemos a


imagem selecionada em um objeto do tipo BufferedImage que est
declarado no incio da nossa classe Fzxing, ou seja, um atributo de
instncia.
Listagem 3. Mtodo do boto processar
private void
jButtonProcessarActionPerformed(java.awt.event.ActionEvent evt)
{//GEN-FIRST:event_jButtonProcessarActionPerformed
try {
if (buffImage == null){
JOptionPane.showMessageDialog(this, "Voc deve
escolher a imagem !!");
return;
}

//1
LuminanceSource source = new
BufferedImageLuminanceSource(buffImage);
//2
BinaryBitmap bitmap = new BinaryBitmap(new
HybridBinarizer(source));
//3
Reader reader = new MultiFormatReader();
//4
Result result = reader.decode(bitmap);
jTextFieldResultado.setText(result.getText());
} catch (NotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ChecksumException e) {
// TODO Auto-generated catch block

e.printStackTrace();
} catch (FormatException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}//GEN-LAST:event_jButtonProcessarActionPerformed

Ns s podemos processar a imagem caso haja alguma, e sendo


assim, a primeira checagem daListagem 3 conferir se o objeto
'buffImage' no nulo. As prximas linhas so dedicadas a funes
exclusivas do Zxing que esto numeradas com linhas para facilitar a
explicao:

As linhas 1 e 2 fazem o tratamento necessrio na imagem para


s ento process-la em um 'Reader' especfico do Zxing. No
nosso caso, na linha 3 ns criamos um MultiFormatReader que
possibilita a leitura de cdigo de barras em diversos formatos
(Code 39, EAN-13 ), mas voc pode criar um tipo especfico
de Reader caso ache necessrio.
Na linha 4 ns usamos o Reader criado na linha 3 para chamar
o mtodo 'decode()' que retorna os dados encontrados no
cdigo de barras, O retorno deste mtodo um Result que
contm diversos mtodo como o getText(), que retorna o dado
em forma de string, e o getBarcodeFormat() que retorna o
formato do cdigo de barras e etc.

Para finalizar o artigo, iremos mostrar na Listagem 4 o cdigo


completo da classe Fzxing com todos os detalhes e implementaes
explicados anteriormente, para que voc leitor possa utiliz-la como
meio de estudo.
Listagem 4. Fzxing.java completa
package br.com.dev.gui;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.ChecksumException;
import com.google.zxing.FormatException;
import com.google.zxing.LuminanceSource;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.NotFoundException;
import com.google.zxing.Reader;
import com.google.zxing.Result;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.HybridBinarizer;
public class FZxing extends javax.swing.JFrame {
private BufferedImage buffImage;
/** Creates new form FZxing */
public FZxing() {
initComponents();
}

/** This method is called from within the constructor to


* initialize the form.
* WARNING: Do NOT modify this code. The content of this method
is
* always regenerated by the Form Editor.
*/
// <editor-fold defaultstate="collapsed" desc=" Cdigo Gerado
">//GEN-BEGIN:initComponents
private void initComponents() {
jLabel1 = new javax.swing.JLabel();
jLabel2 = new javax.swing.JLabel();
jTextFieldImagem = new javax.swing.JTextField();
jTextFieldResultado = new javax.swing.JTextField();
jButtonSelecionar = new javax.swing.JButton();
jButtonProcessar = new javax.swing.JButton();

setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
jLabel1.setText("Imagem");
jLabel2.setText("Resultado");
jTextFieldImagem.setEnabled(false);
jButtonSelecionar.setText("Selecionar Imagem");
jButtonSelecionar.addActionListener(new
java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent
evt) {
jButtonSelecionarActionPerformed(evt);
}
});
jButtonProcessar.setText("Processar");
jButtonProcessar.addActionListener(new
java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent
evt) {
jButtonProcessarActionPerformed(evt);
}
});

javax.swing.GroupLayout layout = new


javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment
.LEADING)
.addComponent(jLabel1)
.addComponent(jLabel2)
.addComponent(jTextFieldImagem,
javax.swing.GroupLayout.PREFERRED_SIZE, 329,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(jTextFieldResultado,
javax.swing.GroupLayout.PREFERRED_SIZE, 329,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(layout.createSequentialGroup()
.addComponent(jButtonSelecionar)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jButtonProcessar)))
.addContainerGap(25, Short.MAX_VALUE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(jLabel1)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jTextFieldImagem,
javax.swing.GroupLayout.PREFERRED_SIZE,
javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(25, 25, 25)
.addComponent(jLabel2)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)

.addComponent(jTextFieldResultado,
javax.swing.GroupLayout.PREFERRED_SIZE,
javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(20, 20, 20)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment
.BASELINE)
.addComponent(jButtonSelecionar)
.addComponent(jButtonProcessar))
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE,
Short.MAX_VALUE))
);
pack();
}// </editor-fold>//GEN-END:initComponents
private void
jButtonProcessarActionPerformed(java.awt.event.ActionEvent evt)
{//GEN-FIRST:event_jButtonProcessarActionPerformed
try {
if (buffImage == null){
JOptionPane.showMessageDialog(this, "Voc deve
escolher a imagem !!");
return;
}

LuminanceSource source = new


BufferedImageLuminanceSource(buffImage);
BinaryBitmap bitmap = new BinaryBitmap(new
HybridBinarizer(source));
Reader reader = new MultiFormatReader();
Result result = reader.decode(bitmap);
jTextFieldResultado.setText(result.getText());
} catch (NotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ChecksumException e) {

// TODO Auto-generated catch block


e.printStackTrace();
} catch (FormatException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}//GEN-LAST:event_jButtonProcessarActionPerformed

private void
jButtonSelecionarActionPerformed(java.awt.event.ActionEvent evt)
{//GEN-FIRST:event_jButtonSelecionarActionPerformed
JFileChooser fChooser = new JFileChooser();
fChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
if (fChooser.showSaveDialog(this) != 1){
File fImage = fChooser.getSelectedFile();
try {
buffImage = ImageIO.read(fImage);
jTextFieldImagem.setText(fImage.getAbsolutePath());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}//GEN-LAST:event_jButtonSelecionarActionPerformed
/**
* @param args the command line arguments
*/
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new FZxing().setVisible(true);
}
});
}
// Declarao de variveis - no modifique//GEN-BEGIN:variables
private javax.swing.JButton jButtonProcessar;
private javax.swing.JButton jButtonSelecionar;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel2;
private javax.swing.JTextField jTextFieldImagem;

private javax.swing.JTextField jTextFieldResultado;


// Fim da declarao de variveis//GEN-END:variables
}

Este artigo teve como principal objetivo demonstrar o uso da API


Zxing de forma prtica, rpida e eficaz. Assim, voc caro leitor, poder
usar tal biblioteca em seus projetos que precisam realizar leitura ou
escrita de cdigo de barras em Java.

Você também pode gostar