3

My requirements ask for generating pdf documents that contain both arbitrary text and barcodes. I have related question that addresses pdf generation part, but here I'd like to know about how to incorporate barcode in pdf in Java.

So far, I've found clear explanation on how barcode4j does it with Apache FOP: Instructions for the Apache FOP extension

But it looks that XSL-FO is not primary option for my requirements as I prefer to go with pdf forms (using iText or PDFBox or similar). Again, this is not final yet.

Do you use images or fonts for barcode in pdf? What dependencies besides pdf API should I expect (fonts, libraries)?

Community
  • 1
  • 1
topchef
  • 19,091
  • 9
  • 63
  • 102

4 Answers4

5

I succeeded in adding barcodes to PDFs using PDFBox and Barbecue. Barbecue offers the Output interface to draw barcodes yourself. I implemented this interface in a such a way that drawBar() translates to calls to PDPageContentStream.fillRect().

Adding a barcode to the PDF now comes down to:

Barcode barcode = BarcodeFactory.createCode128(text);
barcode.output(new PDFBoxOutput(pageContentStream, startX, startY, height));

The PDFBoxOutput class looks like this:

import java.awt.Color;
import java.io.IOException;

import net.sourceforge.barbecue.output.LabelLayout;
import net.sourceforge.barbecue.output.Output;
import net.sourceforge.barbecue.output.OutputException;

import org.apache.pdfbox.pdmodel.edit.PDPageContentStream;

public class PDFBoxOutput implements Output {

    /** The widths and heights from Barbecue are multipplied with this scalar to get the widths and heights for PDFBox. */
    public final static float SCALAR = 0.5f;

    private final PDPageContentStream stream;
    private final float startX;
    private final float startY;
    private final float height;
    private boolean toggleDrawingColor;

    PDFBoxOutput(PDPageContentStream stream, float startX, float startY, float height) {
        this.stream = stream;
        this.startX = startX;
        this.startY = startY;
        this.height = height;
    }

    @Override
    public void beginDraw() throws OutputException {}

    @Override
    public int drawBar(int x, int y, int width, int height, boolean paintWithForegroundColor) throws OutputException {
        if (paintWithForegroundColor == !toggleDrawingColor) {
            try {
                stream.setLineWidth(0.0f);
                stream.setStrokingColor(Color.BLACK);
                stream.fillRect(startX + SCALAR * x, startY - SCALAR * y, SCALAR * width, this.height);
                stream.stroke();
            } catch (IOException e) {
                throw new OutputException(e);
            }
        }
        return width;
    }

    @Override
    public int drawText(String text, LabelLayout layout) throws OutputException {
        return 0;
    }

    @Override
    public void endDraw(int width, int height) throws OutputException {}

    @Override
    public void paintBackground(int x, int y, int width, int height) {}

    @Override
    public void toggleDrawingColor() {
        toggleDrawingColor = !toggleDrawingColor;
    }

}
gogognome
  • 727
  • 8
  • 24
  • It works. At first, the barcode was generated, but it would not scan. There are 2 possible fixes: 1) Change SCALAR to 1, but the barcodes are HUGE (and ugly), or 2) Change the DPI in Adobe settings (or equivalent): Edit -> Preferences -> Page Display -> Resolution -> Custom resolution at 300 pixels/inch). Mine was at 96. – Simon Arsenault Aug 20 '14 at 14:50
  • I know this isn't the purpose of comments but thank you so much for this, this worked so perfectly for me. – UpAllNight Jul 24 '15 at 17:05
2

For generating barcodes in a pdf i would strongly recommend iText to you. If you use maven you can add these dependencies and you can start:

    <dependency>
        <groupId>com.lowagie</groupId>
        <artifactId>itext</artifactId>
        <version>2.0.7</version>
    </dependency>
    <dependency>
        <groupId>bouncycastle</groupId>
        <artifactId>bcmail-jdk14</artifactId>
        <version>136</version>
    </dependency>
    <dependency>
        <groupId>bouncycastle</groupId>
        <artifactId>bcprov-jdk14</artifactId>
        <version>136</version>
    </dependency>

To generate a barcode only a few lines of code are needed:

    Barcode128 code128 = new Barcode128();
    code128.setCodeType(Barcode128.CODE128);
    code128.setCode(new Long(1234559690234234);
    Chunk chunk = new Chunk(code128.createImageWithBarcode(cb, null, null),
            200, -30);
    Paragraph p = new Paragraph(chunk);

Add the paragraph to the document and voila, there you go. A good tutorial can be found here:

IText Example

Florian
  • 53
  • 2
  • 10
1

I'd use a barcode image generator, then embed that in an HTML documetn I converted to PDF.

Check out this library for rendering XHTML as a PDF. Use barcode4j to render barcodes as images, as you originally planned.

Stefan Kendall
  • 66,414
  • 68
  • 253
  • 406
1

If you are prepared to relax your PDF generation requirements to using a non-Java tool, you might find the following useful:

  1. Layout your page templates using HTML/CSS/JS with placeholders for the barcodes.
  2. Use Barcode4J to output SVG and then put that into the template.
  3. Render the page using the wkhtmltopdf command-line tool. wkhtmltopdf uses WebKit under the hood so it gives you good control of the PDF layout using HTML/CSS.
cwb
  • 925
  • 5
  • 6