Преобразование оттенка PDFBox содержимого страницы PDF (цвета)

Я использую преобразование оттенка для изображений PNG и JPG, которые принимают цвет RGB (tintR, tintG, tintB, tintAlpha), а затем я зацикливаюсь на пикселях прикрепленного изображения и изменяю значение каждого пикселя на

новыйR = пиксельR * (tintR/255)

то же самое для newG, newB и newAlpha

Он работает правильно, есть ли способ выполнить ту же операцию с содержимым (цветами) PDF-страницы?

Спасибо


person Bashar    schedule 11.01.2021    source источник
comment
Возможно, вы захотите использовать PDF функции передачи, ср. ИСО 32000-1, раздел 10.4.   -  person mkl    schedule 11.01.2021
comment
Не могли бы вы предоставить мне пример или код, который может мне помочь?   -  person Bashar    schedule 11.01.2021


Ответы (1)


Вы можете попытаться добиться чего-то подобного с помощью передаточных функций (см. ISO 32000-1, раздел 10.4).

Результирующие эффекты могут быть, например, такими (слева вверху — исходный контент):

снимок экрана

Это было создано с использованием следующего кода

try (PDDocument pdDocument = new PDDocument()) {
    PDPage pdPage = new PDPage();
    pdDocument.addPage(pdPage);

    PDImageXObject pdImage = [... create  image XObject ...];

    try (PDPageContentStream canvas = new PDPageContentStream(pdDocument, pdPage)) {
        canvas.drawImage(pdImage, 0, 600, 150, 150);
        canvas.setGraphicsStateParameters(createTransferedState("{ neg 1 add }"));
        canvas.drawImage(pdImage, 150, 600, 150, 150);
        canvas.setGraphicsStateParameters(createTransferedState("{ 90 mul cos }"));
        canvas.drawImage(pdImage, 300, 600, 150, 150);
        canvas.setGraphicsStateParameters(createTransferedState("{ 90 mul sin neg 1 add }"));
        canvas.drawImage(pdImage, 450, 600, 150, 150);
        canvas.setGraphicsStateParameters(createTransferedState("{ .5 mul }"));
        canvas.drawImage(pdImage, 0, 450, 150, 150);
        canvas.setGraphicsStateParameters(createTransferedState("{ 90 mul cos neg 1 add }"));
        canvas.drawImage(pdImage, 150, 450, 150, 150);
        canvas.setGraphicsStateParameters(createTransferedState("{ 90 mul sin }"));
        canvas.drawImage(pdImage, 300, 450, 150, 150);
        canvas.setGraphicsStateParameters(createTransferedState("{ .5 mul .5 add }"));
        canvas.drawImage(pdImage, 450, 450, 150, 150);
        canvas.setGraphicsStateParameters(createTransferedState("{ }", "{ pop 1 }", "{ pop 1 }", "{ pop 1 }"));
        canvas.drawImage(pdImage, 0, 300, 150, 150);
        canvas.setGraphicsStateParameters(createTransferedState("{ pop 1 }", "{ }", "{ pop 1 }", "{ pop 1 }"));
        canvas.drawImage(pdImage, 150, 300, 150, 150);
        canvas.setGraphicsStateParameters(createTransferedState("{ pop 1 }", "{ pop 1 }", "{ }", "{ pop 1 }"));
        canvas.drawImage(pdImage, 300, 300, 150, 150);
        canvas.setGraphicsStateParameters(createTransferedState("{ pop 1 }", "{ pop 1 }", "{ pop 1 }", "{ }"));
        canvas.drawImage(pdImage, 450, 300, 150, 150);
    }

    pdDocument.save("SimpleTransferExample.pdf");
}

(ApplyTransferFunction тест testSimpleTransferExample)

используя эти вспомогательные методы:

PDExtendedGraphicsState createTransferedState(String function) throws IOException {
    PDExtendedGraphicsState transferedState = new PDExtendedGraphicsState();
    transferedState.setTransfer(createTransferFunction(function).getCOSObject());
    return transferedState;
}

PDExtendedGraphicsState createTransferedState(String function1, String function2, String function3, String function4) throws IOException {
    COSArray array = new COSArray();
    array.add(createTransferFunction(function1).getCOSObject());
    array.add(createTransferFunction(function2).getCOSObject());
    array.add(createTransferFunction(function3).getCOSObject());
    array.add(createTransferFunction(function4).getCOSObject());
    PDExtendedGraphicsState transferedState = new PDExtendedGraphicsState();
    transferedState.setTransfer(array);
    return transferedState;
}

PDFunctionType4 createTransferFunction(String function) throws IOException {
    return createFunction(function, new float[] {0f, 1.0f}, new float[] {0f, 1.0f});
}

/** @see org.apache.pdfbox.pdmodel.common.function.TestPDFunctionType4 */
PDFunctionType4 createFunction(String function, float[] domain, float[] range) throws IOException {
    COSStream stream = new COSStream();
    stream.setInt("FunctionType", 4);
    COSArray domainArray = new COSArray();
    domainArray.setFloatArray(domain);
    stream.setItem("Domain", domainArray);
    COSArray rangeArray = new COSArray();
    rangeArray.setFloatArray(range);
    stream.setItem("Range", rangeArray);
    
    try (OutputStream out = stream.createOutputStream()) {
        byte[] data = function.getBytes(StandardCharsets.US_ASCII);
        out.write(data, 0, data.length);
    }

    return new PDFunctionType4(stream);
}

(вспомогательные методы из ApplyTransferFunction)

Таким образом,

Есть ли способ сделать ту же операцию с содержимым (цветами) PDF-страницы?

да, просто примените функцию передачи по вашему выбору в начале содержимого страницы, то есть добавьте ее в PDPageContentStream, который вы создаете для страницы с помощью AppendMode.PREPEND.

person mkl    schedule 11.01.2021