Frage

Okay, also werde ich das gut Glück nehmen, dass jemand hier verwendet hat ZXing vor. Ich bin eine Java-Anwendung zu entwickeln, und eines der Dinge, die sie tun muss, ist kodieren ein Byte-Array von Daten in einen QR-Code und dekodieren sie dann zu einem späteren Zeitpunkt.

Hier ist ein Beispiel dafür, was mein Encoder aussieht:

byte[] b = {0x48, 0x45, 0x4C, 0x4C, 0x4F};
//convert the byte array into a UTF-8 string
String data;
try {
    data = new String(b, "UTF8");
}
catch (UnsupportedEncodingException e) {
 //the program shouldn't be able to get here
 return;
}

//get a byte matrix for the data
ByteMatrix matrix;
com.google.zxing.Writer writer = new QRCodeWriter();
try {
 matrix = writer.encode(data, com.google.zxing.BarcodeFormat.QR_CODE, width, height);
}
catch (com.google.zxing.WriterException e) {
 //exit the method
 return;
}

//generate an image from the byte matrix
int width = matrix.getWidth(); 
int height = matrix.getHeight(); 

byte[][] array = matrix.getArray();

//create buffered image to draw to
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

//iterate through the matrix and draw the pixels to the image
for (int y = 0; y < height; y++) { 
 for (int x = 0; x < width; x++) { 
  int grayValue = array[y][x] & 0xff; 
  image.setRGB(x, y, (grayValue == 0 ? 0 : 0xFFFFFF));
 }
}

//write the image to the output stream
ImageIO.write(image, "png", outputStream);

Der Anfang Byte-Array in diesem Code wird nur verwendet, um es zu testen. Die tatsächlichen Byte-Daten werden variiert werden.

Hier ist, was mein Decoder aussieht:

//get the data from the input stream
BufferedImage image = ImageIO.read(inputStream);

//convert the image to a binary bitmap source
LuminanceSource source = new BufferedImageLuminanceSource(image);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));

//decode the barcode
QRCodeReader reader = new QRCodeReader();

Result result;
try {
 result = reader.decode(bitmap, hints);
} catch (ReaderException e) {
 //the data is improperly formatted
 throw new MCCDatabaseMismatchException();
}

byte[] b = result.getRawBytes();
System.out.println(ByteHelper.convertUnsignedBytesToHexString(result.getText().getBytes("UTF8")));
System.out.println(ByteHelper.convertUnsignedBytesToHexString(b));

convertUnsignedBytesToHexString(byte) ist eine Methode, die ein Array von Bytes, die in einer Reihe von hexadezimalen Zeichen umwandelt.

Wenn ich versuche, zusammen diese beiden Blöcke von Code auszuführen, ist dies die Ausgabe:

48454c4c4f
202b0b78cc00ec11ec11ec11ec11ec11ec11ec

Offensichtlich der Text codiert wird, aber die eigentlichen Daten-Bytes sind vollständig ab. Jede mögliche Hilfe würde hier geschätzt werden.

War es hilfreich?

Lösung

Also, für zukünftige Referenz für alle, die nicht wollen, zwei Tage verbringen die Suche im Internet mit diesen, um herauszufinden, wenn Sie Byte-Arrays in QR-Codes kodieren, müssen Sie den ISO-8859-1character Satz verwenden, nicht UTF-8.

Andere Tipps

Das ist mein Arbeitsbeispiel Java-Code QR Code codieren mit ZXing mit UTF-8-Codierung, beachten Sie bitte: Sie werden den Pfad und die UTF-8-Daten auf Ihrem Weg und Sprachzeichen ändern müssen

package com.mypackage.qr;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.util.Hashtable;

import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.*;

public class CreateQR {

public static void main(String[] args)
{
    Charset charset = Charset.forName("UTF-8");
    CharsetEncoder encoder = charset.newEncoder();
    byte[] b = null;
    try {
        // Convert a string to UTF-8 bytes in a ByteBuffer
        ByteBuffer bbuf = encoder.encode(CharBuffer.wrap("utf 8 characters - i used hebrew, but you should write some of your own language characters"));
        b = bbuf.array();
    } catch (CharacterCodingException e) {
        System.out.println(e.getMessage());
    }

    String data;
    try {
        data = new String(b, "UTF-8");
        // get a byte matrix for the data
        BitMatrix matrix = null;
        int h = 100;
        int w = 100;
        com.google.zxing.Writer writer = new MultiFormatWriter();
        try {
            Hashtable<EncodeHintType, String> hints = new Hashtable<EncodeHintType, String>(2);
            hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
            matrix = writer.encode(data,
            com.google.zxing.BarcodeFormat.QR_CODE, w, h, hints);
        } catch (com.google.zxing.WriterException e) {
            System.out.println(e.getMessage());
        }

        // change this path to match yours (this is my mac home folder, you can use: c:\\qr_png.png if you are on windows)
                String filePath = "/Users/shaybc/Desktop/OutlookQR/qr_png.png";
        File file = new File(filePath);
        try {
            MatrixToImageWriter.writeToFile(matrix, "PNG", file);
            System.out.println("printing to " + file.getAbsolutePath());
        } catch (IOException e) {
            System.out.println(e.getMessage());
        }
    } catch (UnsupportedEncodingException e) {
        System.out.println(e.getMessage());
    }
}

}

Für das, was es wert ist, meine groovy Spitze scheint sowohl mit UTF-8 in Arbeit und ISO-8859-1 Zeichenkodierungen. Nicht sicher, was passieren wird, wenn ein nicht ZXing Decoder versucht, das UTF-8 kodierten Bild zu dekodieren obwohl ... wahrscheinlich variiert je nach Gerät.

// ------------------------------------------------------------------------------------
// Requires: groovy-1.7.6, jdk1.6.0_03, ./lib with zxing core-1.7.jar, javase-1.7.jar 
// Javadocs: http://zxing.org/w/docs/javadoc/overview-summary.html
// Run with: groovy -cp "./lib/*" zxing.groovy
// ------------------------------------------------------------------------------------

import com.google.zxing.*
import com.google.zxing.common.*
import com.google.zxing.client.j2se.*

import java.awt.image.BufferedImage
import javax.imageio.ImageIO

def class zxing {
    def static main(def args) {
        def filename = "./qrcode.png"
        def data = "This is a test to see if I can encode and decode this data..."
        def charset = "UTF-8" //"ISO-8859-1" 
        def hints = new Hashtable<EncodeHintType, String>([(EncodeHintType.CHARACTER_SET): charset])

        writeQrCode(filename, data, charset, hints, 100, 100)

        assert data == readQrCode(filename, charset, hints)
    }

    def static writeQrCode(def filename, def data, def charset, def hints, def width, def height) {
        BitMatrix matrix = new MultiFormatWriter().encode(new String(data.getBytes(charset), charset), BarcodeFormat.QR_CODE, width, height, hints)
        MatrixToImageWriter.writeToFile(matrix, filename.substring(filename.lastIndexOf('.')+1), new File(filename))
    }

    def static readQrCode(def filename, def charset, def hints) {
        BinaryBitmap binaryBitmap = new BinaryBitmap(new HybridBinarizer(new BufferedImageLuminanceSource(ImageIO.read(new FileInputStream(filename)))))
        Result result = new MultiFormatReader().decode(binaryBitmap, hints)

        result.getText()        
    }

}

Vielleicht lohnt ein Blick auf QRGen , die oben auf ZXing und unterstützt UTF-8 mit dieser gebaut Art Syntax:

// if using special characters don't forget to supply the encoding
VCard johnSpecial = new VCard("Jöhn Dɵe")
                        .setAdress("ëåäöƞ Sträät 1, 1234 Döestüwn");
QRCode.from(johnSpecial).withCharset("UTF-8").file();

Wenn Sie zu kodieren UTF-8 wirklich, können Sie versuchen, die Unicode-Bytereihenfolgemarkierung vorangestellt wird. Ich habe keine Ahnung, wie weit verbreitet die Unterstützung für diese Methode ist, aber ZXing zumindest scheint es zu unterstützen: http://code.google.com/p/zxing/issues/ Detail? id = 103

Ich habe vor kurzem auf QR-Modus zu lesen, und ich denkt Ich habe die gleiche Praxis gesehen an anderer Stelle erwähnt, aber ich habe nicht die leiseste wo.

Ich habe versucht, unter Verwendung der ISO-8859-1 als in der ersten Antwort gesagt. Alles ging in Ordnung, auf Codierung, aber wenn ich versuchte, auf dem Decodieren den byte [] mit Ergebnis-String zu erhalten, wurden alle negativen Bytes die Zeichen 63 (Fragezeichen). Der folgende Code funktioniert nicht:

// Encoding works great
byte[] contents = new byte[]{-1};
QRCodeWriter codeWriter = new QRCodeWriter();
BitMatrix bitMatrix = codeWriter.encode(new String(contents, Charset.forName("ISO-8859-1")), BarcodeFormat.QR_CODE, w, h);

// Decodes like this fails
LuminanceSource ls = new BufferedImageLuminanceSource(encodedBufferedImage);
Result result = new QRCodeReader().decode(new BinaryBitmap( new HybridBinarizer(ls)));
byte[] resultBytes = result.getText().getBytes(Charset.forName("ISO-8859-1")); // a byte[] with byte 63 is given
return resultBytes;

Es sieht so seltsam, weil die API in einer sehr alten Version (weiß nicht genau) hatte eine Methode Thar gut funktioniert:

Vector byteSegments = result.getByteSegments();

versucht Also ich zu suchen, warum diese Methode entfernt wurde und erkannte, dass es einen Weg gibt ByteSegments zu bekommen, durch Metadaten. Also meine Dekodierungsverfahren sieht aus wie:

// Decodes like this works perfectly
LuminanceSource ls = new BufferedImageLuminanceSource(encodedBufferedImage);
Result result = new QRCodeReader().decode(new BinaryBitmap( new HybridBinarizer(ls)));
Vector byteSegments = (Vector) result.getResultMetadata().get(ResultMetadataType.BYTE_SEGMENTS);  
int i = 0;
int tam = 0;
for (Object o : byteSegments) {
    byte[] bs = (byte[])o;
    tam += bs.length;
}
byte[] resultBytes = new byte[tam];
i = 0;
for (Object o : byteSegments) {
    byte[] bs = (byte[])o;
    for (byte b : bs) {
        resultBytes[i++] = b;
    }
}
return resultBytes;
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top