Постраничное преобразование PDF в TIFF с правильным сжатием - PullRequest
0 голосов
/ 14 февраля 2012

Задача

Внутри есть документы PDF с различными типами объектов. Есть простые тексты. Могут быть отсканированные изображения черно-белого изображения, а также другие изображения истинного цвета. Разрешение может быть довольно высоким для обоих (~ 1789X2711).

Мне нужно конвертировать PDF в набор одностраничных файлов TIFF . Для этого есть неплохие инструменты. Например, Irfanview, ImageMagick. Проблема в том, что мне нужно определить один тип сжатия для всех страниц.

Использование JPG для всех страниц приведет к потере деталей для черно-белых изображений, и они будут огромными по сравнению со сжатием факса без потерь.

Использование факсов без потерь для всех приведет к ухудшению цвета и детализации изображений в истинных цветах.

Идея

Было бы неплохо изучить страницу PDF за страницей . Я мог бы проверить содержание страницы. Какие изображения находятся внутри, и какое сжатие рекомендуется для конкретной страницы. Я думаю, что это можно сделать с помощью IText , но я не знаю точно, , как это должно быть сделано . Во-вторых, я хочу выполнить этот анализ без полного чтения файла PDF . Возможно ли это?

Возможно, самым быстрым решением было бы создать список страниц для каждого типа сжатия с помощью анализа IText, а затем вызвать Irfanview для обработки выбранных страниц с надлежащим сжатием.

Любые идеи и рекомендации приветствуются.

UPDATE: Теперь у меня есть ответ. Он не покрывает все требования и не распространяется бесплатно. Любые идеи с открытым исходным кодом? Может быть, решения на основе Java?

1 Ответ

2 голосов
/ 14 февраля 2012

Это можно сделать с помощью DotImage DotPdf от Atalasoft (см. Обязательное «Я работаю там и работаю над этими продуктами»).Вот как я мог бы выполнить эту задачу в C #:

PdfImageSource source = new PdfImageSource(pdfStream);

while (source.HasMoreImages()) {
    AtalaImage image = source.AcquireNext();
    string fileName = GetNextTiffName();
    using (FileStream outStm = new FileStream(fileName, FileMode.Create)) {
        TiffEncoder encoder = new TiffEncoder();
        encoder.Compression = SelectCompression(image.PixelFormat);
        image.Save(outStm, encoder, null);
    }
    source.Release(image);
}

private TiffCompression SelectCompression(PixelFormat pf)
{
     switch (pf) {
     // 1 bit? use CCITT G4
     case PixelFormat.Pixel1bbIndexed: return TiffCompression.Group4FaxEncoding;
     // 24 bit? use JPEG
     case PixelFormat.Pixel24bppBgr: return TiffCompression.JpegCompression;
     // all else, Lzw
     default: return TiffCompression.Lzw;
     }
}

Вы можете заставить SelectCompression делать практически все, что вы хотите.Если вы выберете недопустимое сжатие для этого пиксельного формата, кодировщик будет использовать вместо него подходящий без потерь (например, если вы выберете CCITT для 24-битного цвета, кодировщик вместо этого будет использовать Lzw).

Наш PDFдекодер знает, когда PDF-страница просто серая, и возвращает серое изображение.Он НЕ делает ничего, чтобы получить 1 бит (это так сглаженный текст выглядит хорошо), однако вы можете пороговое изображение серого и посмотреть на общие различия между ним и серым изображением, чтобы определить, может ли оно перейти на 1 бит).

Вот как вы можете сделать набор страниц:

public void ExtractNPages(Stream pdfStream, params int[] pageIndexes)
{
    PdfImageSource source = new PdfImageSource(pdfStream);
    for (int i in pageIndexes) {
        AtalaImage image = source[i]; // implied Acquire
        string fileName = GetNextTiffName();
        using (FileStream outStm = new FileStream(fileName, FileMode.Create)) {
            TiffEncoder = new TiffEncoder();
            encoder.Compression = SelectCompression(image.PixelFormat);
            image.Save(outStm, encoder, null);
        }
        source.Release(image);
    }
 }

, так что теперь вы можете просто сделать ExtractNPages(stm, 0, 2, 4, 6);

...