How to Create Dynamic Wallpapers for macOS That Support Automatic Light and Dark Mode

I found surprisingly little information on how to manually create dynamic wallpapers for macOS that support automatic light and dark mode. There are some apps and some websites but I prefer a command line tool.

Besides some deleted medium posts and a GitHub repo that go into a lot of detail, I could not find the basic steps how to do this. So here we go, this is the summary how to do it yourself:

Assuming you have Homebrew then libheif and exiv2 are all you need:

brew install libheif exiv2

Step 1: Attach XMP Metadata to the First Image

For macOS to recognize that a wallpaper is supporting light and dark mode the image needs to have this structure:

HEIF container
├─┬─ image 0 (light mode)
│ ├── HEVC image data
│ └┬─ XMP metadata
│  └┬─ base64
│   └┬─ plist
│    └── {"l": 0, "d": 1}
└─┬─ image 1 (dark mode)
  └── HEVC image data

Two images are wrapped in a HEIF container (HEIC is HEVC in HEIF). The 0th image has some XMP metadata which embeds a plist which tells macOS the 0th image is for "light" mode and the 1st image is for "dark" mode. There are some fancier options to insert solar altitude/azimuth into the plist (see here) but for a basic light/dark wallpaper this XMP is enough:

<?xpacket?>
<x:xmpmeta xmlns:x="adobe:ns:meta">
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns">
<rdf:Description xmlns:apple_desktop="http://ns.apple.com/namespace/1.0"
apple_desktop:apr=
"YnBsaXN0MDDSAQMCBFFsEAFRZBAACA0TEQ/REMOVE/8BAQAAAAAAAAAFAAAAAAAAAAAAAAAAAAAAFQ=="/>
</rdf:RDF>
</x:xmpmeta>

To attach the XMP to the first image, make sure that the .xmp file has the same basename as the image file.

If your light mode image is called light_mode.png then save the XMP data as light_mode.xmp. Then use exiv2 with the "insert XMP" option to update the file in-place:

pbpaste > light_mode.xmp
exiv2 -i X in light_mode.png

Step 2: Combine Two Images Into a Single HEIC

The final step is to use heif-enc to combine the two images into a single HEIC image.

heif-enc -L light_mode.png dark_mode.png -o dynamic.heic

For PNGs -L (lossless mode) is usefull. For JPGs/photos just drop -L.

That's it. The combined image can now be used in macOS System Settings and will automatically switch in light and dark mode.