I bought a new OLED monitor, which worked great with my Windows machine, but when I connected it to my MacBook Air and MacBook Pro via a USB-C to HDMI* adapter the colours all looked very wrong.
Blacks were tinted pink/fuchsia/magenta, whites were tinted yellow/green, all colours look wrong, yet the macOS UI is still legible. Turns out the issue is that macOS thinks the monitor is a TV and encodes colours as YCrCb (or YPbPr) instead of RGB.


Solution
There appear to be distinct fixes for Intel versus Apple Silicon machines.
Intel macs
For Intel macs, the solution is to override the EDID information via a plist, with a base64-encoded EDID payload. I originally tried using patch-edid.rb
† to generate one, but ended up following this procedure instead:
- Dump the EDID data using
ioreg -l -d0 -cr -c AppleDisplay
. Find the “IODisplayEDID” key for my external monitor. For me, I could exclude the built-in monitor using its IOClass of “AppleBacklightDisplay”. ioreg prints the EDID data as a hex string, which I copied into its own text file. You’ll also want to note the values of “DisplayProductID” and “DisplayVendorID”. - Convert the hex EDID payload to a binary file, e.g.
cat edid.txt | xxd -r -p > edid.bin
. - Open the binary EDID file with AW EDID Editor. Disable any toggles that mention YCrCb or YCC (there were several of these in the CEA extension block). Slightly confusingly, for me there were also some disabled controls in the EDID Base block under “Color Encoding Formats” (but it turns out it didn’t matter that YCrCb 4:4:4 was still enabled there). Save the EDID file.
- Fill out the $VARS in the property list template below with the DisplayProductID (as decimal), DisplayVendorID (as decimal) and an arbitrary name string (which will show up in System Settings and such).
- Encode the vendor ID and product ID into the override path as hex, e.g.:
printf /Library/Displays/Contents/Resources/Overrides/DisplayVendorID-%x/DisplayProductID-%x $VENDORID $PRODUCTID
. Move the plist there.
Convert the revised binary EDID file to base64 using base64 -i edid.bin
.
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>DisplayProductName</key> <string>$NAME can be whatever</string> <key>IODisplayEDID</key> <data>$EDID as base64</data> <key>DisplayVendorID</key> <integer>$VENDORID as decimal</integer> <key>DisplayProductID</key> <integer>$PRODUCTID as decimal</integer> </dict> </plist>
Apple Silicon (M1, M2, etc.)
For Apple Silicon, the solution is to override the LinkDescription
in /Library/Preferences/com.apple.windowserver.displays.plist
. See Force-RGB-color-on-M1-Mac for a great description of this method.
Process
Figuring out the fix was a bit of a process for me: my first few searches suggested it could be a cable problem, but I verified the cables worked just fine with the same monitor and other computers. It also didn’t look like the typical colour aberrations when you’re just “missing” a colour channel. Then I thought it was a problem with the USB-C to HDMI adapter I was using. When I stumbled on old (2013) blog and forum posts I was initially skeptical that it was the same issue or that the workarounds would still work. But it turns out that it is a macOS bug that’s been around for 10+ years, and the old workarounds still work!
* I know DisplayPort would be better, but I want to leave the monitor’s DisplayPort socket permanently plugged into my PC.
† I previously recommended patch-edid.rb for overriding the EDID information, but it drops critical resolution information, making it impossible for macOS to use the native resolution on my 2560×1440 monitor, leaving everything blurry.