Sometimes, converting CUBE to XMP is a workaround, not a solution. If you find the accuracy lacking, consider these alternatives:
convert-cube-to-xmp is a tool/script designed to convert color lookup tables (LUTs) from the common .cube format (used by DaVinci Resolve, OpenColorIO, etc.) into Adobe’s XMP structure for LUTs — specifically LUT1 or LUT2 profiles used in Adobe Camera Raw (ACR), Lightroom, and Photoshop. convert-cube-to-xmp
This conversion enables colorists, photographers, and developers to take creative LUTs (film emulations, technical transforms) and apply them within Adobe’s non-destructive raw processing pipeline. Sometimes, converting CUBE to XMP is a workaround,
Here’s a reusable convert_cube_to_xmp(cube_dict) function using xml.etree.ElementTree. # Root
xmpmeta = ET
import xml.etree.ElementTree as ET
from datetime import datetime
def convert_cube_to_xmp(cube):
NS =
"x": "adobe:ns:meta/",
"rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
"dc": "http://purl.org/dc/elements/1.1/",
"cube": "http://example.com/cube/1.0/"
# Root
xmpmeta = ET.Element(f"NS['x']xmpmeta")
rdf = ET.SubElement(xmpmeta, f"NS['rdf']RDF")
desc = ET.SubElement(rdf, f"NS['rdf']Description",
attrib=f"NS['rdf']about": "")
# Cube title
title = ET.SubElement(desc, f"NS['dc']title")
title.text = cube.get("cubeName", "UnnamedCube")
# Dimensions
dims = ET.SubElement(desc, f"NS['cube']dimensions")
seq = ET.SubElement(dims, f"NS['rdf']Seq")
for dim in cube.get("dimensions", []):
li = ET.SubElement(seq, f"NS['rdf']li")
li.text = dim
# Measures
meas = ET.SubElement(desc, f"NS['cube']measures")
seq_m = ET.SubElement(meas, f"NS['rdf']Seq")
for m in cube.get("measures", []):
li = ET.SubElement(seq_m, f"NS['rdf']li")
li.text = m
# Time range
if "timeRange" in cube:
ts = ET.SubElement(desc, f"NS['cube']timeStart")
ts.text = cube["timeRange"]["start"]
te = ET.SubElement(desc, f"NS['cube']timeEnd")
te.text = cube["timeRange"]["end"]
# Serialize
xpacket_start = '<?xpacket begin="\xef\xbb\xbf" id="W5M0MpCehiHzreSzNTczkc9d"?>'
xpacket_end = '<?xpacket end="w"?>'
rough_xml = ET.tostring(xmpmeta, encoding="unicode")
return f"xpacket_start\nrough_xml\nxpacket_end"
| Cube Element | XMP Equivalent |
|--------------------|------------------------------------|
| Dimensions | XMP structured properties (bags, sequences) |
| Measures | Numeric XMP tags with custom schemas |
| Hierarchies | Nested XMP structures |
| Cube name | Dublin Core title or custom schema |
| Time range | XMP CreateDate, MetadataDate |
Typical use cases: