Альтернативные формулы преобразования CMYK в RGB для отображения на экране

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

Когда PDF-файл содержит цвета CMYK, в данный момент я использую простую формулу, широко распространенную в Интернете (например, здесь ), а именно:

R = 255 × (1-C) × (1-K)

И аналогично для других цветов.

Однако это дает плохие результаты. Например, один образец, который у меня есть, указан в PDF-документе с помощью команды «0,62 0 0,05 0 k» (т.е. это компоненты CMYK в масштабе 0-1). Приведенная выше формула преобразует это в RGB #60fff2. Однако Adobe Reader отображает этот текст с использованием RGB #3dc6ea. Мало того, что они выглядят очень по-разному, мой цвет настолько яркий, что текст трудно прочитать. Я пробовал это на нескольких мониторах, и хотя цвета различаются, общий результат один и тот же: программа чтения PDF показывает светло-пастельный или небесно-голубой цвет, тогда как вышеприведенное преобразование дает ярко-голубой.

Чтобы убедиться, что это не произошло из-за того, что что-то упущено в PDF, я попробовал тот же цвет в Illustrator: введя CMYK (62%, 0%, 5%, 0%), отображаемый на экране как # 3ec6ea. Изменение поля редактирования цвета на RGB показало значения #40c4e8; и это также было отображено, если я изменил настройки цвета на «Цветной монитор». Это 3 разных результата от Adobe, но различия крошечные и должны быть незаметны.

Итак, существуют ли какие-либо возможные альтернативные преобразования, которые дали бы результаты, более близкие к преобразованиям Adobe? Я знаю, что преобразование между RGB и CMYK проблематично, но в этом случае это несколько помогло:

  • преобразование предназначено только для отображения на экране. Выводы не будут распечатаны.

  • Различия между мониторами не очень существенны. Если цвет отображается плохо на определенном мониторе (например) в Adobe Reader, я не ожидаю хорошего результата.

  • Точное совпадение для меня не имеет значения: мне просто нужно преобразование, которое выглядит похоже и читаемо.

Какой язык программирования вы используете? Возможно, существует библиотека, которая может выполнить HardWork™️ за вас.
Мы используем С#, но я думаю, что мы достаточно хорошо решили эту проблему. Я опубликую то, что мы сейчас делаем, в качестве ответа
Привет Стюарт! Рад видеть вас здесь. Мы случайно не работали вместе в последнее время? :)
@Vincent - если бы вы создавали для нас логотипы, которые мне были нужны в более старой версии Illustrator, то да :)

Ответы (4)

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

Либо вы прибегаете к легким приемам, либо вам нужно проделать полную работу.

Нет одной формулы

Вам нужна система управления цветом, без вариантов. Что вам нужно сделать, так это получить цветовой профиль и цель рендеринга рассматриваемого элемента. Затем выполните преобразование профиля в профиль в профиль вашего монитора.*

См. PDF-файл, содержащий половину информации о том, как выполнять экранную симуляцию ваших цветов. Однако эта информация представлена ​​в виде профиля ICC, а профили ICC в основном представляют собой мини-язык программирования для преобразования цвета. Таким образом, реализация вашего собственного потребует гораздо больше работы, чем, как я ожидаю, придется потратить большинству людей.

Теперь ваша ОС, скорее всего, имеет систему управления цветом, вы можете использовать ее или использовать что-то вроде крошечной CMS для преобразования. Создание специальной системы не сделает вас счастливым, но использование готовой CMS не так уж и сложно, вы просто просите CMS сделать преобразование для вас.

* Если вам нужен точный цвет, вам необходимо периодически измерять ваш монитор и условия фонового освещения вашей комнаты. И да, цвет RGB на каждом мониторе разный!

Спасибо за крошечную ссылку на CMS - я вернусь к ней, если выяснится, что нам нужно лучшее решение. На данный момент ситуация из вашего последнего абзаца: «Если вам нужен точный цвет ...» - нам не нужен точный, просто читаемый. Так что, надеюсь, мы справимся с быстрым решением
Проблема @StuartWhitehouse заключается в том, что вы можете не требовать, но ваши пользователи наверняка ожидают, что то, что они видят, будет правильным. Обезьяна видит обезьяна делает...

Быстрым решением для удобочитаемости может быть уменьшение красочности. Для уменьшения на 25% пусть G=0,25.

Рассчитайте среднее значение ваших чисел RGB слишком яркого результата преобразования. Пусть это будет А.

Для каждого RGB-числа X рассчитайте новый с уменьшенной красочностью, назовем его Y.

Используйте формулу Y=(1-G)X+GA

ДОБАВИТЬ из-за комментария:

Можно взять другое специальное число, коэффициент снижения яркости =F. Пусть F=0,8, чтобы уменьшить яркость до 80%. Умножьте на него все числа RGB.

Будьте уверены, что это не замена реальной математике управления цветом.

Интересное предложение; Я быстро попробовал, и это в некоторой степени улучшило его; но все же оставляет текст очень светлым - одно из отличий между RGB, который Adobe визуализирует, и простой формулой, которую дает мне, заключается в том, что Adobe темнее во всех 3 каналах RGB.
@StuartWhitehouse, вы не можете одновременно получать такие же простые результаты, как полноценная CMS. Это либо достаточно хорошо, либо, если вы более педантичны, вам нужно полностью управлять цветом.
Я принял это как ответ, потому что похоже, что предложение уменьшить красочность, вероятно , для нас достаточно хорошо. Я уже думал об уменьшении яркости в соответствии с дополнением - хотя это рискованно, если текст светлый на темном фоне. Если позже выяснится, что этого бреда недостаточно, нам придется пройти долгий путь и сделать ColorSpaces правильно.

R = 255 × (1-К) × (1-К)

Я понятия не имею, что вы только что сказали... :о)

Вероятно, вам нужно понимать, что CMYK или RGB не являются абсолютными значениями.

Мой классический пример — голубой маркер. Используйте его на журнальной бумаге и на газете. Это тот же голубой оттенок, те же чернила... другой цвет.

Чтобы отобразить цвет CMYK на экране RGB, вам нужно взять один цветовой профиль для того, что должны означать значения CMYK (глянцевая бумага? Газета? Немелованная бумага?), а затем отобразить его на экране RGB.

Обычно предполагается, что этот экран RGB имеет профиль sRGB, но он также может иметь дополнительный профиль, специфичный для экрана.

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


Отредактировано на основе комментария.

Весь вывод здесь только на экране

Нет. Значение CMYK C100, как в моем предыдущем примере, равно 100% в обоих случаях, но это не один и тот же цвет.

Выход RGB — это не выход RGB, это имитация условий, которые должны иметь место при печати CMYK. Вот почему вам нужно определить, какой будет эта печать CMYK, чтобы смоделировать ее.


Было сказано, что вы, вероятно, захотите придерживаться наиболее оптимального качества печати, которое вы можете иметь, возможно, используя бумагу с покрытием, чтобы сузить его, изучите, как работает Fogra 39.


И да, R = 255 × (1-C) × (1-K) означает, что вы не используете голубой или (K) черный, следовательно, вы фактически используете два других левых компонента в 4-красочной системе печати, Желтый и пурпурный. Но забавно, как это подразумевает упоминание того, что вы не используете, вместо определения того, что вы на самом деле используете.

Это может быть проблематично, особенно если ваша система фактически использует более 4 чернил. Была система Hexachrome, в которой использовалось 6. CMYK+GO.


Отредактировано 2.

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

Красный - это отсутствие циана. Но это отбрасывает всю черную информацию.

Цветовые профили не являются линейными или имеют плавную кривую.

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

Вся эта информация присутствует в цветовом профиле.


Также взгляните на это. Есть некоторые пояснения. Значения CMYK продолжают изменяться в цветовом режиме RGB/8, CS6

Приведенная вами формула предназначена для красного канала RGB на основе C и K из цвета CMYK. Что касается журнальной бумаги и газеты ... Я понимаю, что цвета дают разные результаты в разных контекстах, однако весь вывод здесь только на экране - действительно на одном и том же мониторе (мониторах). Это другое программное обеспечение, дающее совершенно разные результаты.

Ответ пользователя 287001 действительно дал некоторое улучшение, но во многих случаях все еще был проблематичным. Я публикую наше возможное решение на случай, если оно поможет другим.

Отказ от ответственности: это никоим образом не "правильно". Ниже приведены коэффициенты, которые мы составили. (На самом деле мы составили таблицу желаемых входных и выходных данных и просто решили для них) Как уже отмечали другие, преобразование зависит от использования CMYK. Однако в некоторых случаях у нас есть только информация ColorSpace = "DeviceCMYK", компоненты = c,m,y,k. Никакая другая информация недоступна, и ее необходимо отобразить на экране. В какой конкретной ситуации у нас работает следующий код С#...

// inputs are c,m,y,k components on a 0-1 scale
// work with INVERSE of CMYK values, on a 0-255 scale
float C = 255 * (1 - c);
float M = 255 * (1 - m);
float Y = 255 * (1 - y);
float K = 255 * (1 - k);

float r = 80 + 0.5882f * C - 0.3529f * M - 0.1373f * Y + 0.00185f * C * M + 0.00046f * Y * C; // no YM
float g = 66 - 0.1961f * C + 0.2745f * M - 0.0627f * Y + 0.00215f * C * M + 0.00008f * Y * C + 0.00062f * Y * M;
float b = 86 - 0.3255f * C - 0.1569f * M + 0.1647f * Y + 0.00046f * C * M + 0.00123f * Y * C + 0.00215f * Y * M;
// (for non c# readers, the 'f' suffix on the numbers just indicates the precision of the data type to hold the value)
r = r * K / 255;
g = g * K / 255;
b = b * K / 255;
// b,g,r are now the RGB components on a 0-255 scale, but will be out of bounds sometimes and need to be truncated to 0 and 255
Color RGB = Color.FromArgb(255, ((int)r).LimitTo(0, 255), ((int)g).LimitTo(0, 255), ((int)b).LimitTo(0, 255));
// LimitTo is an extension defined elsewhere - the usage should be obvious!

Это дает результаты, которые неотличимы от стандартных программ чтения PDF для наших тестовых случаев.