Я хочу объединить файлы PDF/A 1b.
Я использую itext PdfACopy.getImportedPage
, и ошибки нет. Проверки соответствия Itext в порядке.
Я получаю файл PDF/A 1b, который выглядит нормально.
Когда я проверяю соответствие PDF/A с помощью pdfbox, я получаю много ошибок :
2.4.3 : Invalid Color space, DestOutputProfile is missing 2.4.3 : Invalid Color space, The operator "g" can't be used without Color Profile 2.4.3 : Invalid Color space, The operator "f" can't be used without Color Profile 2.4.1 : Invalid Color space, The operator "rg" can't be used with CMYK Profile 2.4.3 : Invalid Color space, DestOutputProfile is missing
NB: все входные PDF-файлы действительны в формате PDF/A 1b.
Вот пример кода, который я использовал для получения PDF/A, который не соответствует PDF/A 1b.
Document document = new Document();
PdfACopy copy = new PdfACopy(document, new FileOutputStream(outFile), pdfAConformanceLevel);
document.open();
PdfReader reader;
int n;
for (int i = 0; i < args.length - 1; i++)
{
reader = new PdfReader(args[i]);
n = reader.getNumberOfPages();
for (int page = 0; page < n;)
{
copy.addPage(copy.getImportedPage(reader, ++page));
}
}
copy.createXmpMetadata();
document.close();
Так что я разозлился и решил разобраться.
Используя этот пример выгрузить профиль ICC из PDF Я вижу, что действительно ни один профиль ICC не был включен в мой сгенерированный PDF/A.
Посмотрев этот учебник, я, наконец, использовал код в PdfWriter.setOutputIntents(final PdfReader reader, final boolean checkExistence)
, чтобы получить намерения вывода. во входном PDF/A и вернуть его в выходной PDF/A.
И это работает...
Сначала я создал публичный метод
public static void copyOutputIntents(PdfReader reader, PdfACopy copy) throws IOException {
PdfDictionary catalog = reader.getCatalog();
PdfArray outs = catalog.getAsArray(PdfName.OUTPUTINTENTS);
if (outs == null)
{
Logger.err("Reggie Watts gonna get you !!!");
}
else
{
if (outs.isEmpty())
{
Logger.err("Reggie Watts gonna get you !!!");
}
PdfDictionary out = outs.getAsDict(0);
PRStream stream = (PRStream) PdfReader.getPdfObject(out.get(PdfName.DESTOUTPUTPROFILE));
byte destProfile[] = null;
if (stream != null)
{
destProfile = PdfReader.getStreamBytes(stream);
}
copy.setOutputIntents(getNameString(out, PdfName.OUTPUTCONDITIONIDENTIFIER), getNameString(out, PdfName.OUTPUTCONDITION), getNameString(out, PdfName.REGISTRYNAME), getNameString(out, PdfName.INFO), destProfile);
}
}
пришлось также добавить метод getNameString
, который я просто скопировал.
Итак, теперь мой код создает действительный PDF/A:
Document document = new Document();
PdfACopy copy = new PdfACopy(document, new FileOutputStream(outFile), pdfAConformanceLevel);
document.open();
PdfReader reader;
int n;
for (int i = 0; i < args.length - 1; i++)
{
reader = new PdfReader(args[i]);
n = reader.getNumberOfPages();
for (int page = 0; page < n;)
{
copy.addPage(copy.getImportedPage(reader, ++page));
}
// get last PDF's intent and put it into the output one
Stamper.copyOutputIntents(reader, copy);
}
copy.createXmpMetadata();
document.close();
Разве PdfACopy.addPage
не следует сохранять намерение вывода добавленной страницы или каким-либо образом обрабатывать его?
Я не вижу смысла в классе высокого уровня, который не может создать действительный файл PDF/A.
Я что-то упускаю ? Я сошел с ума?
Простите за длинный пост.
writer.setOutputIntents("Custom", "", "http://www.color.org", "sRGB IEC61966-2.1", icc);
С помощьюPdfACopy
вы создаете новыйwriter
(PdfACopy
расширяетPdfWriter
). Вам нужно добавить эти намерения в свой код, потому чтоPdfACopy
не может решить, что использовать. - person Bruno Lowagie   schedule 24.04.2015"Extension of PdfCopy that will attempt to keep a file in conformance with the PDF/A standard."
, я думал, что он получит необходимые объекты из скопированной страницы, но вы правы, мне нужно работать на уровне документа, например, для метаданных XMP. - person EricMas   schedule 28.04.2015