Преобразование RGB PDF в CMYK с обычным черным цветом с помощью ghostscripts sOutputICCProfile

В настоящее время я генерирую pdf с помощью weasyprint версии 52.5. Созданный pdf имеет формат RGB, но для печати мне нужен CMYK. Теперь я попробовал конвертировать его с помощью ghostscript версии 9.50, который работает просто отлично, но мой сгенерированный PDF всегда состоит из текстов насыщенного черного цвета.

Я нашел решение, как преобразовать RGB(0,0,0) в обычный черный (K=100%). Я попробовал хак, описанный в этом выпуске: Преобразование (любого) PDF в черный (K)-только CMYK. Но это сработало только если мой PDF не состоит из прозрачных объектов, которые у меня есть, иначе ghostscript преобразует мой PDF в растровое изображение, чего я не хочу.

Теперь вместо использования хака, поддержка ghostscript рекомендовала использовать профили ICC для достижения того же результата: https://bugs.ghostscript.com/show_bug.cgi?id=704872.

Поэтому мне пришлось обратиться к своему принтеру, чтобы он предоставил мне icc-профили, которые я должен использовать вместо хака. И вот в чем проблема, я не могу заставить ghostscript использовать и внедрить ICC профиль в pdf. Похоже, что ghostscript конвертирует pdf в cmyk, но я думаю, что он использует профиль defaul_cmyk.icc, а не мой указанный профиль icc.

Кроме того, я не думаю, что ICC-профиль моего принтера является правильным. Я попробовал просмотреть свой PDF, и сгенерированный черный цвет CMYK никогда не был простым K. Рекомендуемый профиль был: PS0coated_v3.icc

Вот моя команда ghostscript:

gs -q -o weasyprint_rgb.pdf -sDEVICE=pdfwrite -dNOPAUSE -dBATCH -sProcessColorModel=DeviceCMYK -sColorConversionStrategy=CMYK -sColorConversionStrategyForImages=CMYK -dOverrideICC=true -dEncodeColorImages=true -sOutputICCProfile=PS0coated_v3.icc converted_cmyk.pdf

Также вот моя функция, реализованная в python (django)

def convert_pdf_to_cmyk(pdf_bytes: bytes) -> bytes:
    if pdf_bytes is not None:
        with NamedTemporaryFile(prefix="weasyprint_rgb", suffix=".pdf") as rgb_pdf_file:
            rgb_pdf_file.write(pdf_bytes)
            rgb_pdf_file.seek(0)
            # Converting pdf from RGB to CMYK
            # https://stackoverflow.com/questions/6241282/converting-pdf-to-cmyk-with-identify-recognizing-cmyk
            # HACK to convert rich black to plain CMYK black we need to convert it to ghostscript than to pdf
            # using a colour conversion script.
            # By default RGB->CMYK will create rich black instead plain K black
            # https://stackoverflow.com/questions/6248563/converting-any-pdf-to-black-k-only-cmyk/9024346#9024346).
            # with NamedTemporaryFile(prefix="ghostscript_", suffix=".ps") as ghostscript_file:
            #     command = [
            #         "gs",
            #         "-q",
            #         "-o",
            #         ghostscript_file.name,
            #         "-dNOPAUSE",
            #         "-dBATCH",
            #         "-sDEVICE=ps2write",
            #         rgb_pdf_file.name,
            #     ]
            #     subprocess.check_call(command)
            with NamedTemporaryFile(prefix="converted_cmyk", suffix=".pdf") as converted_pdf_file:
                command = [
                    "gs",
                    "-q",
                    "-o",
                    converted_pdf_file.name,
                    "-sDEVICE=pdfwrite",
                    "-dNOPAUSE",
                    "-dBATCH",
                    "-sProcessColorModel=DeviceCMYK",
                    "-sColorConversionStrategy=CMYK",
                    "-sColorConversionStrategyForImages=CMYK",
                    "-dOverrideICC=true",
                    "-dEncodeColorImages=true",
                    f"-sDefaultCMYKProfile = {os.path.join(DOCUMENT_DATA_DIR, 'PSOcoated_v3.icc')}",
                    f"-sOutputICCProfile = {os.path.join(DOCUMENT_DATA_DIR, 'PS0coated_v3.icc')}",
                    #os.path.join(DOCUMENT_DATA_DIR, "rgb_to_plain_cmyk_black.ps"),
                    rgb_pdf_file.name #ghostscript_file.name,
                ]
                subprocess.check_call(command)
                pdf_bytes = converted_pdf_file.read()
    return pdf_bytes

Буду признателен за любые идеи, как это решить :)

Используйте ICC-профиль DeviceLink, созданный инструментом collink из argyll, привязав исходный RGB icc к целевому CMYK icc с параметром -f, чтобы заставить нейтральный и черный цвета кодироваться только на пластине K.

Если результирующий DeviceLink ICC имеет имя "sRGB_to_eciCMYK_v2.icc (я использовал sRGB в качестве источника и FOGRA59/eciCMYK_v2 в качестве назначения)", добавьте строки, такие как

Image_RGB   sRGB_to_eciCMYK_v2.icc  0   1   0
Graphic_RGB sRGB_to_eciCMYK_v2.icc  0   1   0
Text_RGB    sRGB_to_eciCMYK_v2.icc  0   1   0

в файл control.txt

и использовать Ghostscript с параметрами

-sDEVICE=pdfwrite \
-sColorConversionStrategy=CMYK \
-sSourceObjectICC=control.txt \

где sSourceObjectICC - это txt-файл, определяющий, какой ICC-профиль и намерение должны использоваться для изображений, графики и текстовых RGB-объектов. Для более качественных изображений, где принудительное использование нейтральных цветов только для K не часто желательно, создайте другой ICC профиль DeviceLink с помощью collink, но без параметра -f, и пусть этот профиль вместо этого используется для строки Image_RGB в файле control.txt.

Вернуться на верх