iText PDF: заменить / преобразовать цвета - PullRequest
6 голосов
/ 11 января 2011

Я использую iText в Java, чтобы выбрать несколько страниц из большого PDF-документа и сохранить как новый, меньший PDF-файл. В то же время я хотел бы изменить их цвета.

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


Марк Сторер спрашивает:

Что именно вы пытаетесь достичь?

Преврати это ... в это:

gray pagegreen page

У меня есть некоторых документов , для которых я уже использую iText для выбора меньшего набора страниц из документа на основе пользовательского ввода - сокращая более 100 страниц до примерно 5. В то же время время, когда я хочу выпустить зеленый, синий, желтый, розовый и т. д. их версии. Не каждая страница в оттенках серого, но все те, которые имеют значение, поэтому я могу принудительно настроить их цветовое пространство в случае необходимости.


Обновление:

Следуя совету Марка Сторера о режимах наложения, вот что у меня есть:

    val reader = new PdfReader(file.toURL)
    val document = new Document
    val writer = PdfWriter.getInstance(document, outputStream)
    document.open()

    /* draw a white background behind the page, so the
       blend always has something to transform, otherwise
       it just fills. */
    val canvas = writer.getDirectContent
    canvas.setColorFill(new CMYKColor(0.0f, 0.0f, 0.0f, 0.0f))
    canvas.rectangle(10f, 0f, 100f, 100f)
    canvas.fill

    /* Put the imported page on top of that */
    val page = writer.getImportedPage(reader, 1)
    canvas.addTemplate(page, 0, 0)

    /* Fill a box with colour and a blending mode */
    canvas.setColorFill(new CMYKColor(0.6f,0.1f,0.0f,0.5f))
    val gstate = new PdfGState
    gstate.setBlendMode(PdfGState.BM_SCREEN)
    canvas.setGState(gstate)
    canvas.rectangle(0f, 0f, 100f, 100f)
    canvas.fill

    document.close()

(это в Scala, но библиотека iText точно такая же, как в Java)

Проблема в том, что все режимы наложения, которые предлагает iText, являются «разделимыми» режимами: они работают на каждом цветовом канале независимо друг от друга. Это означает, что я могу отдельно настроить значения голубого, пурпурного, желтого или черного, но я не могу превратить серый в зеленый.

Чтобы сделать это, мне нужно использовать режим смешивания цветов, который является «неразделимым», то есть цветовые каналы влияют друг на друга. Насколько я могу судить, iText этого не предлагает - ни один из неразделенных режимов наложения не указан среди констант в PdfGState. Я использую iText 5.0.5, последнюю версию на момент написания этой статьи.

Есть ли способ получить доступ к этим режимам наложения в iText или даже взломать их? Есть ли другой способ достижения результата?


Обновление:

Даже установка режима наложения на Color не работала. Я сделал это в коде, чтобы заставить его:

    val gstate = new PdfGState
    gstate.put(PdfName.BM, new PdfName("Color"))
    canvas.setGState(gstate)

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


Марк Сторер спрашивает:

"Цвет" не работал? Фанки. Можем ли мы увидеть PDF?

Вот PDF .

Выложив его в Интернете, теперь я вижу, что режим «Цвет» работает правильно в Chrome, но не работает в Acrobat 9 Pro (CS4). Так что техника верна, но Adobe не справляется с рендерингом!

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

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

Как? Я не уверен, что GState применяется для добавления шаблона?

Кроме того, импортированная страница должна сначала добавить белый фон, или она просто зальется цветом там, где нет объекта, а не смешивается.

Я пытался сделать это:

    val canvas = writer.getDirectContent
    canvas.setColorFill(new CMYKColor(0.6f,0.1f,0.0f,0.0f))
    canvas.rectangle(10f, 0f, 500f, 500f)
    canvas.fill

    val template = canvas.createTemplate(500f, 500f)
    template.setColorFill(new CMYKColor(0f, 0f, 0f, 0f))
    template.rectangle(0f, 0f, 500f, 500f)
    template.fill

    val page = writer.getImportedPage(reader, 1)
    template.addTemplate(page, 0, 0)

    val gstate = new PdfGState
    gstate.put(PdfName.BM, new PdfName("Color"))
    canvas.setGState(gstate)
    canvas.addTemplate(template, 0, 0)

И вот PDF, который он создал . Не совсем верно, либо в Chrome, либо в Acrobat:)

Редактировать : Глупый я. Я изменил режим на «Luminosity», производя этот файл . Как и прежде, это выглядит правильно в Chrome, но не в Acrobat.


Я только что проверил, и даже Adobe Reader X не отображает его должным образом. Что, вероятно, означает, что то, о чем я прошу, невозможно. (


Решение

Леонард Розенталь из Adobe вернулся ко мне и прояснил проблему: режим наложения «Цвет» работает только тогда, когда пространство преобразования RGB, а не CMYK. В моем PDF-файле не указывалось пространство, поэтому для продуктов Adobe установлено значение CMYK, а для других - RGB.

Решение в iText состояло в том, чтобы добавить эту строку вверху:

    writer.setRgbTransparencyBlending(true)

Конечно, ради точности цвета вам не нужно больше преобразований цветового пространства, чем это абсолютно необходимо, поэтому используйте эту строку, только если вам действительно нужно использовать режимы наложения RGB.

Цветные страницы выглядят немного странно с точки зрения пользователя Photoshop: похоже, светлые оттенки серого были более насыщенными, чем темные. Я исследую способы объединения фильтров для настройки этого вывода.

Вот результат!

Большое спасибо Марку Стореру за помощь в достижении этого решения.

1 Ответ

5 голосов
/ 28 января 2011

Если вы постоянно хотите перейти от «оттенков серого» к «оттенкам цвета X», вы можете использовать прозрачность в каком-то режиме смешного смешивания.

Если вы хотите пройти через всеконтентные потоки и редактирование существующих цветовых команд, это довольно высокий порядок.Вы должны принять во внимание большое разнообразие пространств colo (u) r.DeviceGray, DeviceRGB, DeviceCMYK, профили ICC, откалиброванные RGB и CMYK, плашечные цвета и т. Д.

Что именно вы пытаетесь достичь?


«Цвет» не сделалРабота?Фанки.Можем ли мы увидеть PDF?


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


Еще одна попытка.Вместо смешивания используйте функцию переноса.Вам нужно построить словарь функций.Вы придерживаетесь CMYK, поэтому объединить любые входные данные в конкретный вывод должно быть довольно просто.

примерно так:

C: [0 1] -> [0 0,6]
M: [0 1] -> [0 0,1]
Y: [01] -> [0 0]
K: [0 1] -> [0 0]

(я проверил 0,6 0,1 0 0 из вашего PDF)

Ург ..только ваша существующая страница - все deviceGray, верно?Нет ... CMYK, а также только K.Вам понадобится передаточная функция, которая будет принимать значения K и отображать их в CMYK на основе требуемого цветового вывода.

А потом я посмотрел, как вы определяете функцию в PDF.Так много для простого.Домены и диапазоны и образцы о мой!Не совсем тривиально.

Тем не менее, это может просто сработать.

(хотя я все еще думаю, что вы должны найти смешанный PDF, который работает в Acrobat, и посмотреть, в чем различия)


Последнее усилие в канаве: премьер-министр Леонард Розентол.У него есть аккаунт здесь на SO.Он парень по связям с разработчиками Acrobat для Adobe.Скажите ему, что Марк Сторер в тупике.Это должно привлечь его внимание.;)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...