2012-04-13 3 views
23

Ich verwende , um Daten zu kodieren und com.google.zxing.client.j2se.MatrixToImageWriter, um das QR-Code Bild zu erzeugen. Bei einem 400x400-Bild ist der Code um einen 52 Pixel breiten Rand herum angeordnet. Ich möchte, dass dieser Rahmen schmaler wird, vielleicht 15 Pixel, aber ich sehe dafür in der API nichts. Fehle ich etwas in der Dokumentation? Oder müsste ich das Bild selbst bearbeiten?Randbreite bei QR-Codes reduzieren, die von ZXing generiert wurden?

Als Referenz ist hier ein Beispiel 400x400 QR-Code mit der ZXing Bibliothek hergestellt:

An example QR Code

Antwort

50

Die QR-spec erfordert eine vier Modulruhezone und das ist, was zxing creates. (Siehe QUIET_ZONE_SIZE in QRCodeWriter.renderResult.)

Neuere Versionen von ZXing können Sie die Größe der Ruhezone einzustellen (im Grunde der innere Polsterung des QR-Code) durch einen int-Wert mit dem EncodeHintType.MARGIN Schlüssel liefert. Fügen Sie einfach es in den Hinweisen Map Sie die Writer ‚s encode(...) Verfahren liefern, z.B .:

Map<EncodeHintType, Object> hints = new EnumMap<EncodeHintType, Object>(EncodeHintType.class); 
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8"); 
hints.put(EncodeHintType.MARGIN, 2); /* default = 4 */ 

Wenn Sie dies ändern, riskieren Sie die decode Erfolgsquote zu senken.

+0

Ich nehme an, ich werde mich dann damit befassen. Vielen Dank. –

+0

Ich kann aus Erfahrung bestätigen, dass ein Code ohne Ruhezone meistens nicht gescannt wird. – Nathan

+0

Rechts. Ich kann nicht für andere Decoder sprechen, aber zxing verwendet Heuristiken, um QR-Codes zu erkennen, die davon ausgehen, dass es eine Ruhezone gibt. Die Heuristiken gehen nicht davon aus, dass die Ruhezone vier Module breit ist, was die Spezifikation sagt, aber wenn sie nicht da ist oder zu eng ist, ist es wahrscheinlich, dass die Erfolgsrate der Zxing-Decodierung sehr wahrscheinlich abnehmen wird. – smparkes

6

Sogar durch Setzen von EncodeHintType.MARGIN auf kann der Algorithmus, der die QRCode "Punkt" -Matrix in Pixeldaten umwandelt, einen kleinen Spielraum erzeugen (der Algorithmus erzwingt eine konstante Anzahl von Pixeln pro Punkt, also ist die Randpixelgröße der Rest von die ganzzahlige Teilung der Pixelgröße durch QR-Code Punktgröße).

Sie können diese "Punkt-zu-Pixel" -Erzeugung jedoch vollständig umgehen: Sie berechnen die QRCode-Punktmatrix direkt, indem Sie die öffentliche Klasse com.google.zxing.qrcode.encoder.Encoder aufrufen und das Pixelbild selbst generieren. Code unten:

// Step 1 - generate the QRCode dot array 
Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>(1); 
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8"); 
QRCode qrCode = Encoder.encode(what, ErrorCorrectionLevel.L, hints); 

// Step 2 - create a BufferedImage out of this array 
int width = qrCode.getMatrix().getWidth(); 
int height = qrCode.getMatrix().getHeight(); 
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); 
int[] rgbArray = new int[width * height]; 
int i = 0; 
for (int y = 0; y < height; y++) { 
    for (int x = 0; x < width; x++) { 
    rgbArray[i] = qrCode.getMatrix().get(x, y) > 0 ? 0xFFFFFF : 0x000000; 
    i++; 
} } 
image.setRGB(0, 0, width, height, rgbArray, 0, width); 

Die Umwandlung des BufferedImage zu PNG-Daten werden als Übung dem Leser überlassen. Sie können das Bild auch skalieren, indem Sie eine feste Anzahl von Pixeln pro Punkt festlegen.

Es ist normalerweise so optimiert, dass die generierte Bildgröße so klein wie möglich ist. Wenn Sie sich darauf verlassen, dass der Client das Bild skaliert (ohne Unschärfe), benötigen Sie nicht mehr als 1 Pixel pro Punkt.

+1

Beachten Sie, dass die Farben umgekehrt erscheinen, ich musste 'if (matrix.get (x, y) == 0) {rgbArray [i] = 0xFFFFFF verwenden } i ++; ', um eine ähnliche Ausgabe wie Zxing zu erhalten. –

+0

@RC. Danke für den Hinweis, das habe ich nicht bemerkt. Aber bist du sicher? Der QRCode, den ich mit diesem Code bekomme, scheint zu passen. –

+0

Eine andere Möglichkeit wäre, die Größe des Randes (z. B. Gesamtgröße modulo die Anzahl der Pixel pro Punkt) abzurufen und das Bild unter Verwendung der ImageIO-Transformation zu skalieren. – matthiasbe

2
HashMap hintMap = new HashMap(); 
    hintMap.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.Q); 
    hintMap.put(EncodeHintType.MARGIN, -1); 

kein Spielraum

UPDATE

Abhängigkeiten hinzufügen (von Kommentaren)

<dependency> 
    <groupId>com.google.zxing</groupId> 
    <artifactId>core</artifactId> 
    <version>3.2.0</version> 
    <type>jar</type> 
</dependency> 
<dependency> 
    <groupId>com.google.zxing</groupId> 
    <artifactId>javase</artifactId> 
    <version>3.2.0</version> 
</dependency> 
+0

Dies wirft Ausnahme ( – ruslik

+0

com.google.zxing Kern 3.2.0 jar com.google.zxing 3.2.0 JavaSE Abhängigkeiten hinzufügen – ougalejo

0

In swift können Sie:

let hints = ZXEncodeHints() 
hints!.margin = NSNumber(int: 0) 

let result = try writer.encode(code, format: format, width: Int32(size.width), height: Int32(size.height), hints: hints) 
let cgImage = ZXImage(matrix: result, onColor: UIColor.blackColor().CGColor, offColor: UIColor.clearColor().CGColor).cgimage 
let QRImage = UIImage(CGImage: cgImage)