Недавно купил себе новый монитор и обнаружил неприятную проблему, которая затрагивает всех пользователей macOS. Проблема заключается в том, что если монитор заявляет поддержку цветовых пространств RGB и YCbCr, macOS всегда использует последнее и изменить это поведение в настройках невозможно. На каких-то мониторах эта проблема проявляется сильнее, на каких-то она совсем не заметна. Эта проблема существует и при подключении через HDMI и через DisplayPort.
Как понять что ваш монитор работает в пространстве YCbCr?
Некоторые мониторы в информации в OSD (On-screen display)
прямо указывают в каком цветовом пространстве они работают. Например, DELL делает это в разделе
Color Settings
-> Input Color Format
.
Мой монитор не показывает этой информации, но он автоматически переключает уровень черного в зависимости от используемой цветовой модели. Если ему поступает RGB сигнал, он устанавливает уровень черного в High, если же YCbCr – в Low.
Иногда понять что используется не цветовое пространство RGB можно по качеству картинки. Типичные признаки:
- картинка ощутимо хуже, чем при подключении к Windows машине;
- вокруг букв появляются разноцветные пиксели;
- как бы вы не старались настраивать монитор, цвета получаются блеклыми, а черный либо слишком глубокий, либо слишком выцветший.
Чем плох YCbCr?
Картинка (framebuffer) в вашем компьютере хранится как набор пикселей в формате RGB: три n-битных (чаще всего 8-битных) числа, по одному на красную, зеленую и синюю компоненты. Монитор состоит из пикселей, каждый из которых разделен на три субпикселя: красного, зеленого и синего цвета. Соответственно, монитору для отображения картинки также необходимы данные в формате RGB.
Формат YCbCr заменяет значения яркости красной, зеленой и синей компоненты на три других числа: яркость пикселя и две хроматические компоненты. Это цветовое пространство используется для того, чтобы снизить нагрузку на канал передачи данных, поскольку человеческий глаз гораздо более восприимчив к изменению яркости, чем к изменению цвета, а следовательно, обе хроматические компоненты в YCbCr сигнале можно сжать с потерями, не сильно проиграв в воспринимаемом качестве картинки.
Естественно, эти рассуждения совершенно не подходят для случая, когда мы подключаем дома монитор к макбуку HDMI кабелем с шириной пропускания канала 40 гигабит в секунду. Но macOS это совершенно не интересует, и всегда, когда можно, она использует именно цветовое пространство YCbCr.
Часто это выражается в искаженных и блеклых цветах, выцветшем черном, сложностях с настройкой изображения, цветных пикселях вокруг букв, меньшей четкости картинки. Степень выраженности эффектов, естественно, будет зависеть от монитора – где-то картинка будет сильно хуже, чем в RGB режиме, где-то – почти неотличима.
Так что же делать?
К счастью, в macOS есть механизм, который позволяет исправить это безобразие. Выражается он в возможности переопределить EDID монитора. EDID расшифровывается как Extended Display Identification Data. Это информация, которую монитор передает операционной системе, о поддерживаемых им цветовых пространствах, режимах работы, аудио форматах, цветовых профилях и о многом чём ещё.
Здесь я не буду описывать структуру и спецификацию EDID, она очень хорошо представлена в Википедии, да и я в ней полноценно не разбирался. Я лишь опишу конкретную инструкцию как заставить macOS думать что ваш монитор поддерживает только цветовое пространство RGB.
Итак, существует решение, о котором уже много раз писалось в интернете – скрипт на Ruby за авторством Andrew Daugherity. Скрипт выполняет свою функцию, но удаляет при этом из EDID все блоки кроме основного, что приводит к потере работоспособности многих возможностей монитора.
Например, если я использую этот скрипт без доработок, мой 1440p монитор теряет возможность работать в режимах выше 1080p, что, естественно, неприемлемо.
Поэтому мы начнем с использования этого скрипта и если вдруг результат вас не устроит, пойдем чуть более долгим и сложным путём. Для достижения наилучшего результата желательно иметь машину с Windows, но в теории можно справиться и без неё.
Итак, поехали.
Пошаговая инструкция
1. Скачайте и запустите скрипт
При подключенном внешнем мониторе скачайте и запустите скрипт от Andrew Daugherity (я форкнул его, чтобы удостовериться, что он не изменится).
Скрипт делает четыре вещи:
- Получает EDID внешнего монитора.
- Устанавливает поддерживаемое цветовое пространство в RGB.
- Удаляет все секции кроме основной.
- Сохраняет EDID в понятном macOS формате в виде единственного файла в директории с особым именем.
Имя директории и файла зависят от производителя и модели вашего монитора.
Например в моём случае это DisplayVendorID-1e6d/DisplayProductID-5b80
. Файл – обычный текстовый plist.
<plist version="1.0">
<dict>
<key>DisplayProductName</key>
<string>LG ULTRAGEAR - forced RGB mode (EDID override)</string>
<key>IODisplayEDID</key>
<data>AP///////wAebYBbNtMDAAkeAQOAPCJ44oy1r09DqyYOUFQlSwBxQIGAgcCp
wLMA0cCBANHPWqAAoKCgRlAwIDoAVVAhAAAaAAAA/QAwkB7mPAAKICAgICAg
AAAA/ABMRyBVTFRSQUdFQVIKAAAA/wAwMDlOVFNVN0M2NzgKAO8=
</data>
<key>DisplayVendorID</key>
<integer>7789</integer>
<key>DisplayProductID</key>
<integer>23424</integer>
</dict>
</plist>
Самая важная его часть – data
. Здесь в base64 закодирован модифицированный
EDID.
2. Установите модифицированный EDID
Полученную директорию необходимо скопировать по адресу /Library/Displays/Contents/Resources/Overrides
,
создав промежуточные директории если необходимо.
3. Перезагрузите компьютер
Перезагрузите компьютер, и проверьте результат. Если монитор перешел в режим RGB и ничего не сломалось, поздравляю, больше ничего не требуется, можете спокойно закрывать эту статью.
Если же что-то сломалось, то удалите override, перезагрузите компьютер ещё раз и переходите к следующему шагу.
4. Правим EDID вручную
Дальше придется работать руками. Нам понадобится какой-нибудь редактор EDID. Я использовал Advantiv EDID Editor, так как он единственный среди опробованных мной распознал все дополнительные секции файла, сгенерированного моим монитором. К сожалению, доступен он только для Windows, поэтому пришлось использовать виртуальную машину.
Вы можете использовать любой другой редактор EDID по вашему выбору.
Чтобы EDID можно было открыть в редакторе, его необходимо сохранить в бинарный файл. Я для этого использовал Hex Fiend.
Команда ioreg -l -d0 -w 0 -r -c AppleDisplay
покажет всю доступную информацию о внешних мониторах, полученную от них самих.
В выводе нас интересует строка "IODisplayEDID" = <...>
, где вместо троеточия будет длинная hex последовательность,
которую необходимо вставить в Hex Fiend и сохранить как edid.bin
.
В Advantiv EDID Editor для того, чтобы открыть бинарный файл, необходимо воспользоваться пунктом меню File
-> Import
-> Binary
.
После импорта слева станут видны все находящиеся в файле разделы и подразделы, а справа для каждого подраздела будут доступны для редактирования его поля.
Необходимо поменять значения следующих полей:
- В
EDID
->VESA
->Basic
->Features Supported
->Display Color
выбратьMonochrome
(неRGB
) - В
EDID
->CEA
->Head
->Head
отключитьYCbCr 444
иYCbCr 422
- В
EDID
->CEA
->VSDB
->VSDB (HDMI)
в секцииDeep Color
отключитьY444
Теперь файл можно экспортировать (File
-> Export
-> Binary
), например в edid-edited.bin
.
5. Заменяем EDID в plist
Полученный бинарный файл необходимо перевести в base64 и заменить им содержимое секции <data>
в сгенерированном скриптом
plist файле.
Для перевода файла в base64 я использовал следующий скрипт:
#!/usr/bin/ruby
require 'base64'
File.open(ARGV[0], 'rb') { |f| puts Base64.encode64(f.read) }
6. Заменяем файл и перезагружаемся
Осталось повторить шаги 2 и 3 и надеяться что всё заработает как нужно. Если не заработало, можно попробовать удалять
секции внутри раздела CEA
одну за другой кроме CEA
-> Video
-> SVD
.