在矢量图像中创建QR码

Mic*_*oon 6 qr-code vector-graphics zxing

我可以使用ZXing成功创建QR Code PNG图像,但没有简单的方法可以将输出作为SVG或EPS.

如何从QRCodeWriter创建的BitMatrix对象创建矢量图像?

Dav*_*ert 10

我知道这个老问题,但对于那些想要如何做到这一点的人来说......很容易连接ZXingJFreeSVG(http://www.jfree.org/jfreesvg),例如:

package org.jfree.demo;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import java.awt.Color;
import java.io.File;
import java.io.IOException;
import org.jfree.graphics2d.svg.SVGGraphics2D;
import org.jfree.graphics2d.svg.SVGUtils;

public class QRCodes {

    public static void main(String[] args) throws WriterException, IOException {
        QRCodeWriter qrCodeWriter = new QRCodeWriter();
        BitMatrix bitMatrix = qrCodeWriter.encode("http://www.jfree.org/jfreesvg", 
                BarcodeFormat.QR_CODE, 160, 160);
        int w = bitMatrix.getWidth();
        SVGGraphics2D g2 = new SVGGraphics2D(w, w);
        g2.setColor(Color.BLACK);
    for (int xIndex = 0; xIndex < w; xIndex = xIndex + bitMatrix.getRowSize()) {
        for (int yIndex = 0; yIndex < w; yIndex = yIndex + bitMatrix.getRowSize()) {
            if (bitMatrix.get(xIndex, yIndex)) {
                g2.fillRect(xIndex, yIndex, bitMatrix.getRowSize(), bitMatrix.getRowSize());

            }
        }
    }

        SVGUtils.writeToSVG(new File("qrtest.svg"), g2.getSVGElement());
    }

}
Run Code Online (Sandbox Code Playgroud)


sio*_*iom 6

您甚至可以仅使用 zxing 来完成,而无需额外的库:

QRCodeWriter qrCodeWriter = new QRCodeWriter();
Map<EncodeHintType, Object> hints = new HashMap<>();
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
hints.put(EncodeHintType.CHARACTER_SET, StandardCharsets.UTF_8.name());

BitMatrix bitMatrix = qrCodeWriter.encode(payload, BarcodeFormat.QR_CODE, 543, 543, hints);

StringBuilder sbPath = new StringBuilder();
int width = bitMatrix.getWidth();
int height = bitMatrix.getHeight();
int rowSize = bitMatrix.getRowSize();
BitArray row = new BitArray(width);
for(int y = 0; y < height; ++y) {
    row = bitMatrix.getRow(y, row);
    for(int x = 0; x < width; ++x) {
        if (row.get(x)) {
            sbPath.append(" M"+x+","+y+"h1v1h-1z");
        }
    }
}

StringBuilder sb = new StringBuilder();
sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
sb.append("<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" viewBox=\"0 0 ").append(width).append(" ").append(height).append("\" stroke=\"none\">\n");
sb.append("<style type=\"text/css\">\n");
sb.append(".black {fill:#000000;}\n");
sb.append("</style>\n");
sb.append("<path class=\"black\"  d=\"").append(sbPath.toString()).append("\"/>\n");
sb.append("</svg>\n");
Run Code Online (Sandbox Code Playgroud)

请注意,上述解决方案在内存消耗方面比使用 Batik DOM 的解决方案高效得多。


Mic*_*oon 1

我发现最简单的方法是使用 iText 创建 PDF,然后将生成的 PDF 转换为 EPS 或 SVG。以下是创建 PDF 的代码:

\n\n
   @Test\n   public void testQRtoPDF() throws WriterException, FileNotFoundException, DocumentException, UnsupportedEncodingException {\n      final int s = 600;\n      int r = 1;\n\n      Charset charset = Charset.forName( "UTF-8" );\n      CharsetEncoder encoder = charset.newEncoder();\n      byte[] b = null;\n      try {\n         // Convert a string to UTF-8 bytes in a ByteBuffer\n         ByteBuffer bbuf = encoder.encode( CharBuffer.wrap(\n                     "1\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb2\xc3\xaf\xc3\xab\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb2\xc3\xaf\xc3\xab\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb2\xc3\xaf\xc3\xab\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb2\xc3\xaf\xc3\xab\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb2\xc3\xaf\xc3\xab\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb2\xc3\xaf\xc3\xab\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb2\xc3\xaf\xc3\xab\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb2\xc3\xaf\xc3\xab\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb2\xc3\xaf\xc3\xab\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb21" +\n                                 "2\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb2\xc3\xaf\xc3\xab\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb2\xc3\xaf\xc3\xab\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb2\xc3\xaf\xc3\xab\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb2\xc3\xaf\xc3\xab\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb2\xc3\xaf\xc3\xab\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb2\xc3\xaf\xc3\xab\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb2\xc3\xaf\xc3\xab\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb2\xc3\xaf\xc3\xab\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb2\xc3\xaf\xc3\xab\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb22" +\n                                 "3\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb2\xc3\xaf\xc3\xab\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb2\xc3\xaf\xc3\xab\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb2\xc3\xaf\xc3\xab\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb2\xc3\xaf\xc3\xab\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb2\xc3\xaf\xc3\xab\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb2\xc3\xaf\xc3\xab\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb2\xc3\xaf\xc3\xab\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb2\xc3\xaf\xc3\xab\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb2\xc3\xaf\xc3\xab\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb23" +\n                                 "4\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb2\xc3\xaf\xc3\xab\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb2\xc3\xaf\xc3\xab\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb2\xc3\xaf\xc3\xab\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb2\xc3\xaf\xc3\xab\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb2\xc3\xaf\xc3\xab\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb2\xc3\xaf\xc3\xab\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb2\xc3\xaf\xc3\xab\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb2\xc3\xaf\xc3\xab\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb2\xc3\xaf\xc3\xab\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb24" +\n                                 "5\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb2\xc3\xaf\xc3\xab\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb2\xc3\xaf\xc3\xab\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb2\xc3\xaf\xc3\xab\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb2\xc3\xaf\xc3\xab\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb2\xc3\xaf\xc3\xab\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb2\xc3\xaf\xc3\xab\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb2\xc3\xaf\xc3\xab\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb2\xc3\xaf\xc3\xab\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb2\xc3\xaf\xc3\xab\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb25" +\n                                 "6\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb2\xc3\xaf\xc3\xab\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb2\xc3\xaf\xc3\xab\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb2\xc3\xaf\xc3\xab\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb2\xc3\xaf\xc3\xab\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb2\xc3\xaf\xc3\xab\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb2\xc3\xaf\xc3\xab\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb2\xc3\xaf\xc3\xab\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb2\xc3\xaf\xc3\xab\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb2\xc3\xaf\xc3\xab\xc3\xa9\xc3\xb6\xc3\xa0\xc3\xa4\xc3\xa8\xc3\xbc\xc3\xb9\xc3\xb26" ) );\n         b = bbuf.array();\n      } catch ( CharacterCodingException e ) {\n         System.out.println( e.getMessage() );\n      }\n\n      String content = new String( b, "UTF-8" );\n      QRCodeWriter qrCodeWriter = new QRCodeWriter();\n      Hashtable<EncodeHintType, String> hints = new Hashtable<EncodeHintType, String>( 2 );\n      hints.put( EncodeHintType.CHARACTER_SET, "UTF-8" );\n      BitMatrix qrCode = qrCodeWriter.encode( content, BarcodeFormat.QR_CODE, s, s, hints );\n\n      Document doc = new Document( new Rectangle( s, s ) );\n      PdfWriter pdfWriter = PdfWriter.getInstance( doc, new FileOutputStream( "qr-code.pdf" ) );\n      doc.open();\n      PdfContentByte contentByte = pdfWriter.getDirectContent();\n      contentByte.setColorFill( BaseColor.BLACK );\n\n      boolean d = false;\n      for ( int x = 0; x < qrCode.getWidth(); x += r ) {\n         for ( int y = 0; y < qrCode.getHeight(); y += r ) {\n            if ( qrCode.get( x, y ) ) {\n               contentByte.rectangle( x, s - y, r, r );\n               contentByte.fill();\n               contentByte.stroke();\n            }\n         }\n      }\n\n      doc.close();\n   }\n
Run Code Online (Sandbox Code Playgroud)\n\n

然后我使用图像魔法进行转换。就像这样:

\n\n
convert qr-code.pdf qr-code.eps\n
Run Code Online (Sandbox Code Playgroud)\n\n

svg 不能做同样的事情

\n\n
convert qr-code.pdf qr-code.svg\n
Run Code Online (Sandbox Code Playgroud)\n\n

这不起作用

\n\n

我用一些长内容测试了这段代码,它最多可以处理 600 个字符。这可能取决于手机或屏幕上摄像头的精度。

\n\n

我希望这可以帮助别人

\n