java Barcode4j生成條形碼並添加至pdf打印


需求

公司產品需要生成條形碼並可以使用打印機清晰打印產品標簽。最終效果類似下圖

測試過程中使用的為TSC打印機。

遇到問題

起初查找了一些java條形碼生成方案。畢竟常見的有Barcode4j、zxing等。由於都能達到目的且Barcode4j條形碼相關內容代碼更方便查找故選擇了Barcode4j。下圖為官網提供的demo。(注:不同的條碼規格所對應的bean不同,圖中為Code39,其中還有Code128等等。只需使用正確的Bean即可。)

起初測試使用hp打印機(平常打印紙張的打印機)並沒有什么問題,內容也較為清楚。后來更換為TSC打印機(更為專業的條碼打印機)后發現條碼內容彎彎曲曲,掃碼槍根本無法識別。

排查問題

首先排除打印機問題,因為打印機打印其它網站生成的條形碼並沒有問題(例如菜鳥打印、lodop等)。
最終打開菜鳥打印所生成的pdf查看發現條碼內容為矢量圖。而我們項目中生成的條形碼為png格式圖片,再將png條形碼圖片添加至itext pdf中,再將pdf輸出值打印機中。
那么使用Barcode4j生成svg條形碼並再將svg加入itext中是否能夠解決問題?
經調試是可行的。

相關代碼

Barcode4j生成svg條形碼文件。

    /**
     * 繪制條形碼生成到流(code128)
     *
     * @param msg 條形碼內容
     */
    @SneakyThrows
    public static void generateAtCode128(String msg, String tempFilePath, Double width, Double height, Double dpi, Double fontSize) {
        if (StringUtils.isEmpty(msg)) {
            return;
        }
        Code128Bean code128Bean = new Code128Bean();
        // moduleWidth影響條碼寬度,正常來說條碼內容越長條碼越長,若想要減小條碼寬度可調整下面的值。
        // 條碼越密集對打印機精度要求越高!內容多還想要條碼短,需dpi更高的打印機支持。    
        code128Bean.setModuleWidth(UnitConv.in2mm(1.5f / dpi));
        code128Bean.setBarHeight(height);
        code128Bean.doQuietZone(false);
        code128Bean.setFontSize(fontSize);
        // 輸出到流
        SVGCanvasProvider canvas = new SVGCanvasProvider(false, 0);
        // 生成條形碼
        code128Bean.generateBarcode(canvas, msg);
        DocumentFragment frag = canvas.getDOMFragment();
        TransformerFactory factory = TransformerFactory.newInstance();
        Transformer trans = factory.newTransformer();
        Source src = new DOMSource(frag);
        Result res = new StreamResult(tempFilePath);
        trans.transform(src, res);
    }

itext添加svg文件(如果使用的是itext7 簡單更代碼7.0版本提供了方法,這里為itext5)

    /**
     * svg添加至pdf 中
     *
     * @param svgFilePath 
     * @param width
     * @param height
     */
    @SneakyThrows
    private void pdfWriterSvg(String svgFilePath, double width, double height, float x, float y) {
        final String parser = XMLResourceDescriptor.getXMLParserClassName();
        SAXSVGDocumentFactory factory = new SAXSVGDocumentFactory(parser);
        UserAgent userAgent = new UserAgentAdapter();
        DocumentLoader loader = new DocumentLoader(userAgent);
        BridgeContext ctx = new BridgeContext(userAgent, loader);
        ctx.setDynamicState(BridgeContext.STATIC);
        GVTBuilder builder = new GVTBuilder();
        PdfContentByte cb = pdfWriter.getDirectContent();
        PdfTemplate svgTemplate = cb.createTemplate((float) width * PAG_PROPORTION, (float) height * PAG_PROPORTION);
        PdfGraphics2D g2d = new PdfGraphics2D(svgTemplate, (float) width * PAG_PROPORTION, (float) height * PAG_PROPORTION);
        SVGDocument city = factory.createSVGDocument("file:///" + svgFilePath);
        GraphicsNode mapGraphics = builder.build(ctx, city);
        mapGraphics.paint(g2d);
        g2d.dispose();
        cb.addTemplate(svgTemplate, x, y);
    }

后續:上線后部分用戶反映條碼有概率打印不出來。由於我們測試使用的是200dpi精度的打印機也存在同樣問題,后續讓客戶使用600dpi精度的打印機后就無問題。
要想在更小的紙張,打印更多的內容,打印機的精度更加關鍵。由於600dpi的打印機太貴(某東最便宜的看了下也要7000多),我這邊也無法進行調試。
總之有條件的買工業級的打印機效果肯定會更好。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM