Как добавить черно-белые изображения в виде потоков JBIG2DECODE в PDF через iText
Я работаю над утилитой для замены изображений в PDF на меньшие монохромные (двухцветные черно-белые) версии с целью сокращения отсканированных PDF-файлов. Приведенная ниже программа (и это все) в настоящее время экспортирует все изображения в большие файлы.png в in
каталог, в котором пользователь берет эти файлы, выполняет любые необходимые манипуляции с изображениями и копирует результаты с теми же именами, но теперь с .jb2
расширение, до out
каталог. Повторный запуск этой программы должен скопировать измененные файлы обратно в поток, заменив исходные изображения.
Излишне говорить, что это не работает. Заголовки потока все правильные, но я не думаю, что поток правильно сжат, чтобы соответствовать JBIG2DEOCDE
формат, поэтому ни одно из измененных изображений не отображается в считывателе. Поскольку я заменяю существующий поток, я не могу использовать document.add(Image)
так что я должен делать все эти потоковые вещи вручную. Возможно, мне не хватает средства iText для этого, но как я могу получить эти изображения в поток?
Использование .jb2
формат был продиктован iText, но я также легко могу использовать более распространенный формат, такой как .gif
, Важной частью является то, что я хочу, чтобы изображение с черно-белой 2-цветовой палитрой было помещено в PDF-файл и формат сжатия, подходящий для монохромных текстовых изображений (я бы предпочел JBIG2, но CCITT 3, 4 или RLE будут работать для я тоже). Цель - максимальная экономия места; У меня нет требований к времени обработки.
В качестве альтернативы, если кто-нибудь знает какие-либо хорошие утилиты, которые делают то, что я пытаюсь сделать, это было бы также хорошо. Я хочу заменить все существующие изображения в файле PDF на альтернативные (они должны быть доступны для обработки внешним приложением), и мне нужно контролировать, как сжимаются замены. Это также должно быть сделано способом, подходящим для обработки в пакетном режиме, потому что я имею дело с PDF-файлами с сотнями страниц и одним изображением на странице, как правило. Я пытаюсь уменьшить размер моих PDF-файлов, но мне нужен полный контроль над сжатием, и я хочу сделать все сжатие с потерями самостоятельно. Функция Acrobat "Уменьшить размер PDF" всегда искажает мои изображения.
public class Test {
public static void main(String[] args) throws IOException, DocumentException
{
PdfReader pdf = new PdfReader("data\\in.pdf");
int n = pdf.getXrefSize();
for (int i = 0; i < n; i++) {
PdfObject object = pdf.getPdfObject(i);
if (object == null || !object.isStream()) continue;
PRStream stream = (PRStream)object;
if (!stream.contains(PdfName.WIDTH)) continue;
PdfImageObject image = new PdfImageObject(stream);
BufferedImage bi = image.getBufferedImage();
if (bi == null) continue;
File in = new File("data\\in\\" + i + ".png");
if (!in.exists()) {
ImageIO.write(bi, "png", in);
}
File out = new File("data\\out\\" + i + ".jb2");
if (!out.exists()) continue;
Image img = Image.getInstance("data\\out\\" + i + ".jb2");
byte[] data = new byte[(int)out.length()];
new FileInputStream(out).read(data);
stream.clear();
stream.setData(data, false, PRStream.NO_COMPRESSION);
stream.put(PdfName.TYPE, PdfName.XOBJECT);
stream.put(PdfName.SUBTYPE, PdfName.IMAGE);
stream.put(PdfName.FILTER, PdfName.JBIG2DECODE);
stream.put(PdfName.WIDTH, new PdfNumber((int)img.getWidth()));
stream.put(PdfName.HEIGHT, new PdfNumber((int)img.getHeight()));
stream.put(PdfName.BITSPERCOMPONENT, new PdfNumber(1));
stream.put(PdfName.COLORSPACE, PdfName.DEVICEGRAY);
}
new PdfStamper(pdf, new FileOutputStream("data\\out.pdf")).close();
}
}
1 ответ
Я написал библиотеку на codeplex, которая может вам помочь.
Он используется для распознавания и сжатия отсканированных PDF-файлов с помощью jbig2 и имеет делегата для некоторой обработки изображения перед его добавлением в PDF-файл.