Vet aquí el que en diu la Viquipèdia dels codis QR:
"El codi QR (en anglès QR Code) és un codi de barres en 2 dimensions (codi matriu) que pot emmagatzemar fins a 7089 caràcters numèrics, 4296 caràcters alfanumèrics (contràriament al codi de barres "tradicional" que només pot emmagatzemar de 10 a 13 caràcters) o 2953 octets .
Per accedir a la informació continguda o encriptada en un qr-code, és necessari un dispositiu digital de captura d'imatges ( Ex: càmera de fotos d'un mòbil, webcam...) i un software específic lector de qr-codes.
Té l'avantatge de poder emmagatzemar moltes informacions tot i ser petit i ràpid d'escanejar. Així, les sigles «QR» deriven de «Quick Response» ja que el contingut pot ser desxifrat ràpidament.
La informació oculta en el codi pot estar en forma de:
TEXT
URL (ens permetrà visitar una pàgina web concreta amb un sol clic)
SMS ( podrem enviar un sms predeterminat a un número de predeterminat amb un sol clic)
VCARD (targes de presentació)
Les possibilitats i aplicacions d'aquests codis en gestió i màrqueting (especialment en opt-in màrqueting i promocions) són novedoses i interessants ja que mitjançant els codis qr es poden unir dos suports històricament aïllats: paper i internet o tinta i bits.
El codi QR ha estat creat per l'empresa japonesa Denso-Wave el 1994. El codi QR és molt emprat al Japó, on actualment és el codi de dues dimensions més popular.
L'estàndard japonès per als codis QR, JIS X 0510, ha estat publicat el 1999, i la norma ISO corresponent, ISO/IEC 18004, ha estat aprovada el juny de 2000.
Un detall important sobre el codi QR, seria que es tracta de codi obert i els seus drets de patent (propietat de Denso Wave) no són exercits."
Que els codis QR siguin d'alguna manera codi open source tampoc deu ser aliè al seu èxit.
Però, i com es poden crear codis QQ? i com descodificar-los? Més concretament, com crear o llegir codis QR amb Java ( o amb JVM)? Una cerca ràpida amb Google ens mostra diverses llibreries. Em crida l'atenció la llibreria ZXing.
ZXing és una llibreria per al processat d'imatges de codis de barres de 1D/2D per a clients Android i Java.
Dit i fet, descarrego la llibreria (versió 1.7) d'aquí: http://code.google.com/p/zxing/downloads/detail?name=ZXing-1.7.zip, i la descomprimeixo.
El paquet té la següent estructura:
albert@athena:~/zxing$ ls
actionscript androidtest build.properties COPYING csharp javase README zxing.appspot.com
android AUTHORS build.xml core iphone jruby rim zxingorg
android-integration bug CHANGES cpp javame objc symbian
albert@athena:~/zxing$
Observem que no hi han jars. Cal compilar-los. És tan senzill com, en un terminal, moure's primrer a la carpeta core i executar ant, i després a la carpeta javase i tornar a excutar ant. Cal, evidentment, tenir ant instal·lat.
De moment, seguiré les instruccions que posen al lloc web de ZXing.
albert@athena:~/zxing$ cd core
albert@athena:~/zxing/core$ ls
build build.xml lib pom.xml src test
albert@athena:~/zxing/core$ ant
Buildfile: /home/albert/zxing/core/build.xml
clean:
[delete] Deleting directory /home/albert/zxing/core/build
build:
init:
compile:
[mkdir] Created dir: /home/albert/zxing/core/build
[javac] Compiling 177 source files to /home/albert/zxing/core/build
[javac] warning: [options] bootstrap class path not set in conjunction with -source 1.3
[javac] 1 warning
[jar] Building jar: /home/albert/zxing/core/core.jar
BUILD SUCCESSFUL
Total time: 34 seconds
albert@athena:~/zxing/core$ cd ../javase
albert@athena:~/zxing/javase$ ls
build build.xml pom.xml src
albert@athena:~/zxing/javase$ ant
Buildfile: /home/albert/zxing/javase/build.xml
init:
build:
[jar] Building jar: /home/albert/zxing/javase/javase.jar
BUILD SUCCESSFUL
Total time: 6 seconds
albert@athena:~/zxing/javase$
Si examinem de nou les carpetes core i javase trobarem core.jar i javase.jar a les carpetes de mateix nom:
albert@athena:~/zxing/javase$ ls
build build.xml javase.jar pom.xml src
albert@athena:~/zxing/javase$ cd ../core
albert@athena:~/zxing/core$ ls
build build.xml core.jar lib pom.xml src test
albert@athena:~/zxing/core$
En aquest moment es pot fer una prova. Faré servir la següent imatge:
I ara, fem la prova executant la classe CommandLineRunner que permet descodificar una imatge:
albert@athena:~/zxing$ java -cp javase/javase.jar:core/core.jar com.google.zxing.client.j2se.CommandLineRunner ./sticipl.png
file:/home/albert/zxing/./sticipl.png (format: QR_CODE, type: TEXT):
Raw result:
Serveis TIC i Programari Lliure
Parsed result:
Serveis TIC i Programari Lliure
Found 4 result points.
Point 0: (14.0,102.0)
Point 1: (14.0,14.0)
Point 2: (102.0,14.0)
Point 3: (90.0,90.0)
albert@athena:~/zxing$
Pel que fa a la documentació, el javadoc de ZXing el podem trobar a http://zxing.org/w/docs/javadoc/index.html
També ens pot ajudar la pàgina de les DeveloperNotes (http://code.google.com/p/zxing/wiki/DeveloperNotes)
El que faré serà un parell de programes d'exemple, un per a crear codis de barra QR i un altre per a descodificar-los. Un coder i un decoder d'exemple.
Primer de tot, el decoder. L'aplicaré al següent QR:
Primer de tot, el decoder. L'aplicaré al següent QR:
Vet aquí el codi:
package com.sticipl.prova.zxing;
import com.google.zxing.Reader;
import com.google.zxing.qrcode.QRCodeReader;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.LuminanceSource;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.ResultPoint;
import com.google.zxing.Result;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
public class ProvaZxing {
public ProvaZxing() {
try {
Reader reader = new QRCodeReader();
BufferedImage myImage = ImageIO.read(
new File("/home/albert/Workspace/wk-java/prova-zxing/img/albert.png")
);
LuminanceSource source = new BufferedImageLuminanceSource(myImage);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
Result result = reader.decode(bitmap);
String text = result.getText();
System.out.println("Text llegit: " + text);
byte[] rawBytes = result.getRawBytes();
for (byte byteElem : rawBytes) {
System.out.println("Byte: " + byteElem);
}
BarcodeFormat format = result.getBarcodeFormat();
System.out.println("Format del codi: " + format);
ResultPoint[] punts = result.getResultPoints();
for (ResultPoint punt : punts) {
System.out.println("Punt.x: " + punt.getX() + "; Punt.y: " + punt.getY());
}
} catch(Exception e) {
System.out.println("Error: " + e.toString());
}
}
public static void main(String args[]) {
new ProvaZxing();
}
}
El programa és directe: instancia un reader del tipus QRCodeReader, crea una BufferedImage a partir de la imatge del QR. El reader s'aplica al QRReder i, senzillament, el descodifica. El resultat s'obté en diferents formats.
L'aplicació del programa sobre la darrera imatge proporciona la sortida:
Text llegit: Albert Baranguer Codina
Byte: 65
Byte: 116
Byte: 22
Byte: -58
Byte: 38
Byte: 87
Byte: 39
Byte: 66
Byte: 4
Byte: 38
Byte: 23
Byte: 38
Byte: 22
Byte: -26
Byte: 119
Byte: 86
Byte: 87
Byte: 34
Byte: 4
Byte: 54
Byte: -10
Byte: 70
Byte: -106
Byte: -26
Byte: 16
Byte: -20
Byte: 17
Byte: -20
Format del codi: QR_CODE
Punt.x: 14.0; Punt.y: 86.0
Punt.x: 14.0; Punt.y: 14.0
Punt.x: 86.0; Punt.y: 14.0
Punt.x: 74.0; Punt.y: 74.0
La creació de codis QR no té dificultat i segueix un procediment similar al de la descodificació: primer de tot, cal instanciar un QRCodeWriter i amb aquesta instància, directament es codifica la informació. El resultat és una matriu de bits que es fa servir per a crear una BufferedImage. Vet aquí el mètode codifica(String sText), que rep com a argument el text a codificar
// genera un codi QR per al text passat
public void codifica(String sCadena) {
try {
Writer writer = new QRCodeWriter();
BitMatrix bitmat = writer.encode(sCadena, BarcodeFormat.QR_CODE, 200, 200);
// genera la imatge.
// Obté ample i alt
int width = bitmat.getWidth();
int height = bitmat.getHeight();
// crea BufferedImage
BufferedImage imatge = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// estableix els bits de la imatge (true, negre; false, blanc)
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
boolean boolPunt = bitmat.get(x,y);
imatge.setRGB(x, y, (boolPunt ? 0 : 0xFFFFFF));
}
}
// genera el fitxer d'imatge a partir de la BufferedImage
File file = new File("/home/albert/Workspace/wk-java/prova-zxing/img/generat.png");
FileOutputStream fos = new FileOutputStream(file);
ImageIO.write(imatge, "png", fos);
fos.flush();
fos.close();
} catch(Exception e) {
System.out.println("Error: " + e.toString());
}
}
Aplicant el mètode amb els argument mostrats:
public static void main(String args[]) {
ProvaZxing prova = new ProvaZxing();
// prova.decode();
prova.codifica("Generat amb Zxing - Serveis TIC i Programari Lliure - Albert Baranguer Codina - accents: àèò éíóú ç ñ ...");
}
obtinc la imatge:
Per acabar, una altre imatge generada amb el mètode codifica(). Endevineu quin és el text que amaga?
package com.sticipl.prova.zxing;
import com.google.zxing.Reader;
import com.google.zxing.qrcode.QRCodeReader;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.LuminanceSource;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.ResultPoint;
import com.google.zxing.Result;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
public class ProvaZxing {
public ProvaZxing() {
try {
Reader reader = new QRCodeReader();
BufferedImage myImage = ImageIO.read(
new File("/home/albert/Workspace/wk-java/prova-zxing/img/albert.png")
);
LuminanceSource source = new BufferedImageLuminanceSource(myImage);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
Result result = reader.decode(bitmap);
String text = result.getText();
System.out.println("Text llegit: " + text);
byte[] rawBytes = result.getRawBytes();
for (byte byteElem : rawBytes) {
System.out.println("Byte: " + byteElem);
}
BarcodeFormat format = result.getBarcodeFormat();
System.out.println("Format del codi: " + format);
ResultPoint[] punts = result.getResultPoints();
for (ResultPoint punt : punts) {
System.out.println("Punt.x: " + punt.getX() + "; Punt.y: " + punt.getY());
}
} catch(Exception e) {
System.out.println("Error: " + e.toString());
}
}
public static void main(String args[]) {
new ProvaZxing();
}
}
El programa és directe: instancia un reader del tipus QRCodeReader, crea una BufferedImage a partir de la imatge del QR. El reader s'aplica al QRReder i, senzillament, el descodifica. El resultat s'obté en diferents formats.
L'aplicació del programa sobre la darrera imatge proporciona la sortida:
Text llegit: Albert Baranguer Codina
Byte: 65
Byte: 116
Byte: 22
Byte: -58
Byte: 38
Byte: 87
Byte: 39
Byte: 66
Byte: 4
Byte: 38
Byte: 23
Byte: 38
Byte: 22
Byte: -26
Byte: 119
Byte: 86
Byte: 87
Byte: 34
Byte: 4
Byte: 54
Byte: -10
Byte: 70
Byte: -106
Byte: -26
Byte: 16
Byte: -20
Byte: 17
Byte: -20
Format del codi: QR_CODE
Punt.x: 14.0; Punt.y: 86.0
Punt.x: 14.0; Punt.y: 14.0
Punt.x: 86.0; Punt.y: 14.0
Punt.x: 74.0; Punt.y: 74.0
// genera un codi QR per al text passat
public void codifica(String sCadena) {
try {
Writer writer = new QRCodeWriter();
BitMatrix bitmat = writer.encode(sCadena, BarcodeFormat.QR_CODE, 200, 200);
// genera la imatge.
// Obté ample i alt
int width = bitmat.getWidth();
int height = bitmat.getHeight();
// crea BufferedImage
BufferedImage imatge = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// estableix els bits de la imatge (true, negre; false, blanc)
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
boolean boolPunt = bitmat.get(x,y);
imatge.setRGB(x, y, (boolPunt ? 0 : 0xFFFFFF));
}
}
// genera el fitxer d'imatge a partir de la BufferedImage
File file = new File("/home/albert/Workspace/wk-java/prova-zxing/img/generat.png");
FileOutputStream fos = new FileOutputStream(file);
ImageIO.write(imatge, "png", fos);
fos.flush();
fos.close();
} catch(Exception e) {
System.out.println("Error: " + e.toString());
}
}
Aplicant el mètode amb els argument mostrats:
public static void main(String args[]) {
ProvaZxing prova = new ProvaZxing();
// prova.decode();
prova.codifica("Generat amb Zxing - Serveis TIC i Programari Lliure - Albert Baranguer Codina - accents: àèò éíóú ç ñ ...");
}
obtinc la imatge:
Per acabar, una altre imatge generada amb el mètode codifica(). Endevineu quin és el text que amaga?
Cap comentari:
Publica un comentari a l'entrada