1

I'm trying to define an up to date method for converting any PDF into a PDF/A-1b able to pass 3-Heights validation. I came up with this script which uses ghostscript and qpdf:

#! /bin/bash
# transforms input PDF into an optimized PDF/A-1b
# usage: $0 input.pdf output.pdf

gs -sDEVICE=pdfwrite -dBATCH -dNOPAUSE -dSAFER -sColorConversionStrategy=UseDeviceIndependentColor -dEmbedAllFonts=true -dPrinted=true -dPDFA -sProcessColorModel=DeviceRGB -dPDFACompatibilityPolicy=1 -dDetectDuplicateImages -r150 -sOutputFile=$2 $1  
qpdf --linearize $2 $2.optimized
mv $2.optimized $2

Which transforms any PDF into a web optimized PDF/A-1b.

Everything is good, except that ghostscript seems not to add missing EOLs before endstreams, which won't allow the processed document to pass the validation. This is the validation result I get:

Validating file "document.pdf" for conformance level pdfa-1b
  The separator before 'endstream' must be an EOL. (5)
  The document does not conform to the requested standard.
The file format (header, trailer, objects, xref, streams) is corrupted.
Done.

Do you know any way or tool with which these EOL separators can be added?

Valid and up to date alternative suggestions to convert PDF to PDF/A-1b are welcome too.

  • I think your problem may be more with qpdf; see also github.com/qpdf/qpdf/issues/38 from 2014. Not sure if this ever got fixed. – Stephen Harris Aug 8 '16 at 18:41
  • Thanks Stephen, you're right: the problem is qpdf! The issue is still not fixed then, as I'm able to reproduce it with the script above. I gave another look at ghostscript, and found out it was already capable of linearizing PDFs. I'll self-answer to show how. – Luca C Aug 9 '16 at 10:51
0

I was blindly focused on ghostscript, but thanks to Stephen, I found out it seems due to a bug in qpdf. I'll submit a clear report via GitHub.

We can do all the work with ghostscript alone, since from version 9.07 it can linearize PDFs with a simple additional flag, as reported also here.

I want to complete my answer not only providing an up to date method to convert a PDF into the A-1b format with ghostscript, but also reporting how to validate it locally with java and preflight tool from Apache PDFBox library.

Converting any PDF to PDF/A-1b with Ghostscript 9.19

gs -sDEVICE=pdfwrite -dBATCH -dNOPAUSE -dSAFER -sColorConversionStrategy=UseDeviceIndependentColor -dEmbedAllFonts=true -dPrinted=true -dPDFA -sProcessColorModel=DeviceRGB -dPDFACompatibilityPolicy=1 -dDetectDuplicateImages -r150 -dFastWebView=true -sOutputFile=output.pdf input.pdf

Validating your PDF/A-1b locally with Java 8 and Apache PDFBox preflight

All the infos in the code comments. Download latest preflight-app from Apache PDFBox site.

At the time of writing, latest version is 2.0.2.

/**
 * Source:
 * https://pdfbox.apache.org/1.8/cookbook/pdfavalidation.html
 *
 * Compilation:
 * $ javac -cp preflight-app.2.0.2.jar:. Validator.java
 *
 * Usage:
 * $ java -cp preflight-app.2.0.2.jar:. Validator input.pdf
 */

import org.apache.pdfbox.preflight.ValidationResult;
import org.apache.pdfbox.preflight.parser.PreflightParser;
import org.apache.pdfbox.preflight.PreflightDocument;
import org.apache.pdfbox.preflight.exception.SyntaxValidationException;
import org.apache.pdfbox.preflight.ValidationResult.ValidationError;

public class Validator {
    public static void main( String[] args ) throws Exception {
        ValidationResult result = null;
        PreflightParser parser = new PreflightParser(args[0]);

        try {
            parser.parse();
            PreflightDocument document = parser.getPreflightDocument();
            document.validate();
            result = document.getResult();
            document.close();
        } catch (SyntaxValidationException e) {
            result = e.getResult();
        }

        if( result.isValid() )
            System.out.println("The file " + args[0] + " is a valid PDF/A-1b file");
        else {
            System.out.println("The file " + args[0] + " is not valid, error(s) :");
            for( ValidationError error : result.getErrorsList() )
                System.out.println(error.getErrorCode() + " : " + error.getDetails());
        }
    }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.