All formats

ofdrw

LanguageJava 8+
LicenseMIT
Repositorygithub.com/ofdrw/ofdrw (mirror: gitee.com/ofdrw/ofdrw)
DocumentationREADME and module docs in the repository (Chinese), e.g. export and conversion to OFD
Depends ondom4j, Bouncy Castle, Apache PDFBox (converter), others per module
Read / writeyes / yes, including signatures, seals and encryption

ofdrw implements GB/T 33190 in Java and is the most complete open-source OFD library. It covers the whole document model, a layout engine that flows paragraphs, tables and images onto pages, text extraction, merging and splitting, attachments, annotations and watermarks, digital signatures and electronic seals with Chinese national cryptography (SM2, SM3), GM/T 0099 encryption, OFD-A archive checks, and conversion between OFD and PDF, images, SVG, HTML and text.

The project keeps its public API backward compatible. Documentation and comments are in Chinese, and the test classes in each module are the best examples. The authors recommend the separate ofdrw-viewer (JavaScript) for displaying OFD, and the converter only for format migration.

Installation#

Maven, all modules:

XML
<dependency>
  <groupId>org.ofdrw</groupId>
  <artifactId>ofdrw-full</artifactId>
  <version>2.5.1</version>
</dependency>

Gradle:

Kotlin
implementation("org.ofdrw:ofdrw-full:2.5.1")

To keep dependencies small, use only the modules you need, e.g. ofdrw-reader for reading or ofdrw-converter for conversion.

Basic usage: create an OFD document#

OFDDoc lays out content on A4 pages and writes the file when closed:

Java
import org.ofdrw.layout.OFDDoc;
import org.ofdrw.layout.element.Paragraph;

import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;

public class HelloOfd {
    public static void main(String[] args) throws IOException {
        Path path = Paths.get("hello.ofd");
        try (OFDDoc doc = new OFDDoc(path)) {
            doc.add(new Paragraph("你好,OFD! Hello, OFD!", 5d)); // font size in mm
        }
        System.out.println("written " + path.toAbsolutePath());
    }
}

How to extract text from an OFD file#

ContentExtractor returns the text of each text object; page numbers start at 1:

Java
import org.ofdrw.reader.ContentExtractor;
import org.ofdrw.reader.OFDReader;

import java.io.IOException;
import java.nio.file.Paths;
import java.util.List;

public class ExtractText {
    public static void main(String[] args) throws IOException {
        try (OFDReader reader = new OFDReader(Paths.get("invoice.ofd"))) {
            System.out.println(reader.getNumberOfPages() + " pages");
            ContentExtractor extractor = new ContentExtractor(reader);
            for (int page = 1; page <= reader.getNumberOfPages(); page++) {
                List<String> lines = extractor.getPageContent(page);
                System.out.println("--- page " + page + " ---");
                lines.forEach(System.out::println);
            }
        }
    }
}

extractor.extractAll() returns the text of all pages. To read only part of a page, pass a RegionTextExtractorFilter(new java.awt.Rectangle(x, y, w, h)) (millimeters) to the ContentExtractor constructor.

How to convert OFD to PDF#

PDFExporter writes the PDF when it’s closed, so always use try-with-resources. export() without arguments exports all pages; page indexes passed to it start at 0:

Java
import org.ofdrw.converter.export.OFDExporter;
import org.ofdrw.converter.export.PDFExporter;

import java.nio.file.Path;
import java.nio.file.Paths;

public class OfdToPdf {
    public static void main(String[] args) throws Exception {
        Path ofd = Paths.get("invoice.ofd");
        Path pdf = Paths.get("invoice.pdf");
        try (OFDExporter exporter = new PDFExporter(ofd, pdf)) {
            exporter.export();        // or export(0, 2) for pages 1 and 3
        }
    }
}

Encrypted OFD files throw an exception. Missing fonts are replaced by similar fonts and logged as warnings. TextExporter, SVGExporter and HTMLExporter work the same way.

How to convert OFD pages to PNG#

Java
import org.ofdrw.converter.export.CanvasImageExporter;

import java.nio.file.Path;
import java.nio.file.Paths;

public class OfdToPng {
    public static void main(String[] args) throws Exception {
        // 15 pixels per millimeter is about 380 dpi
        try (CanvasImageExporter exporter =
                 new CanvasImageExporter(Paths.get("invoice.ofd"), Paths.get("out"), "PNG", 15d)) {
            exporter.export();
            for (Path img : exporter.getImgFilePaths()) {
                System.out.println(img);   // out/page-0.png, out/page-1.png, ...
            }
        }
    }
}

How to convert PDF to OFD#

PDFConverter keeps PDF text as OFD text objects:

Java
import org.ofdrw.converter.ofdconverter.PDFConverter;

import java.nio.file.Paths;

public class PdfToOfd {
    public static void main(String[] args) throws Exception {
        try (PDFConverter converter = new PDFConverter(Paths.get("out.ofd"))) {
            converter.convert(Paths.get("in.pdf"));   // or convert(path, 0, 1) for some pages
        }
    }
}

How to get page size and check for signatures#

Java
try (OFDReader reader = new OFDReader("invoice.ofd")) {
    org.ofdrw.core.basicType.ST_Box box = reader.getPageSize(1);   // 1-based
    System.out.println(box.getWidth() + " x " + box.getHeight() + " mm");
    System.out.println("signed: " + reader.hasSignature());
}

Tips#