Swatches - colour file format/Propositions
From Create Wiki
This page should be used as a working document to work toward a specification for a Swatches file format to use across different applications.
On a side note, Jon A. Cruz [1] reminds us that swatches are not just about color but about material in general.
Contents |
Swatch Definition
For Inkscape's needs, we'd like to at least have linear and radial gradients. If reasonable, patterns would be very good too. For colors, we need base sRGB values, and icc specified colors. Having an sRGB fallback is needed. --Jon Cruz
Anyway for Krita, it's also color, gradients and patterns (and brush ?). In gradients we currently use the same file format as the Gimp which have more features than SVG gradient (linear, curved, sine, sphere inc., sphere dec. interpolations in RGB and HSV ). About pattern, the annoyance is that is usually a bitmap file, and it's allways a little bit annoying to embed a bitmap file in XML. And having separate file is less convenient when you want to exchange your file. --Cyrille
Propositions for XML layout
This section only address the layout of the XML file, not the values.
Proposition A
<color space="rgb" r="1" g="2" b="3" name="123color" spot="false" registration="false"> <color space="rgb" r="1" g="2" b="3" name="123color" ... <color space="cmyk" c="4" m="5" y="6" k="7" name="4567color" ... <color space="hsv" h="8" s="9" v="10" name="8910color" ...
Weakness
- doesn't allow DTD or RelaxNG checking
Proposition B
<space name="rgb">
<color r="1" b="0.5" c="0.33333" name=... />
<color r="1.0" b="1.0" c="0.33333" name=... />
</space>
Weakness
- doesn't allow DTD or RelaxNG checking
Proposition C
<space name="RGB">
<color name="blue">
<r>0.0</r>
<g>0.0</g>
<b>1.0</b>
</color>
</space>
Weakness
- doesn't allow DTD or RelaxNG checking
Proposition D
<color>
<rgb r="0.23" g="0.42" b="1.0" />
</color>
Weakness
- doesn't allow cutom color spaces
Proposition E
<space name="RGB">
<color name="blue">
<component name="R" value="0" />
<component name="G" value="0" />
<component name="B" value="1" />
<color>
</space>
Weakness
- doesn't allow DTD or RelaxNG checking
- very verbose (it means bigger file)
Proposition F
<color-profile name="sRGB">
<color>
<rgb r="1.6" g="1.2" b="0.8">
<extra a="0.9173" Z="30592.4" u="0.6029" v="-0.3982">
<name="Evening Wall 2">
</color>
</color-profile>
Proposition G
<color name="blue">
<label lang="en">Blue</label>
<label lang="es">Azul</label>
<label lang="en_US_SoCal">glassy</label>
<icc-color space="2ndFloorCMYK" val="0, 0.75, 0, 1"/>
<sRGB r='0' g='0' b='1.0'/>
</color>
<colorspace name="2ndFloorCMYK" xlink:href="2nd_floor.icm"/>
Proposition H
Incorporating feedback to get a more "XML-friendly" form, we get to
<colors xmlns:xlink="http://www.w3.org/1999/xlink"> <color name="blue"> <label lang="en">Blue</label> <label lang="es">Azul</label> <label lang="en_US_SoCal">glassy</label> <CMYK space="2ndFloorCMYK" c="0.8703" m="0.6172" y="0" k="0"/> <Lab space="mine" L="34.67" a="54.1289" b="-103.3359"/> <HSV space="prof01" h="240" s="1" v="1"/> <HLS space="prof02" h="240" l="0.5" s="1"/> <Luv space="prof03" L="34.6701" u="-15.0121" v="-124.7986"/> <XYZ space="prof04" x="0.1566" y="0.0833" z="0.7196"/> <Yxy space="prof05" Y="0.0833" x="0.1632" y="0.0869"/> <Gray space="prof06" g="0.2515"/> <sRGB r="0" g="0" b="1.0"/> <RGB space="lcd" r="0.1608" g="-0.1518" b="1.0753"/> </color> <color name="red"> <label lang="en">Red</label> <CMYK space="2ndFloorCMYK" c="0.0011" m="0.7992" y="0.9405" k="0.0038"/> <sRGB r="1.0" g="0" b="0"/> </color> <colorspace name="2ndFloorCMYK" xlink:href="2nd_floor.icm"/> <colorspace name="mine" xlink:href="sample.icm"/> <colorspace name="lcd" xlink:href="generic_lcd.icm"/> </colors>
Questions:
- Are <HSL> and <HSV> defined in terms of <RGB> or of <sRGB ?
- More generally, should provide a reference to the meaning of each of these colour elements.
- What is the precedence when, as in the above example, many specifications are given, some conflicting with each other?
- What is the behaviour for out-of-bounds values? (It may vary between attributes; e.g. hue is often taken modulo 360°, whereas most other values are often clamped to within bounds.) What's the behaviour for NaN, or the behaviour for ±inf for fields that are defined in terms of modulo? (xsd:float allows NaN and ±inf, unlike the number formats in e.g. CSS and SVG.)
Other comments/notes:
- The above makes special provision for (apparently, in absence of a specification of their meaning) device-specific tuples RGB and CMYK, but doesn't generalize to allow for printing with a different set of inks. (Cf. the device-color proposal in SVGPrint12.)
- name attribute: If http://lists.freedesktop.org/archives/create/2008-April/001165.html accurately describes the nature/purpose of the name attribute (e.g. that it is optional and intended to be human-readable text), then it appears to be superceded by the <label> element(s), and should be removed. (Otherwise, its purpose/use should be specified.)
- From the RelaxNG schema, it appears that colour specification is optional. Cf. SVG, where a fallback sRGB specification is mandatory when specifying ICC- or device colours.
RelaxNG Compact
namespace xlink = "http://www.w3.org/1999/xlink" grammar { start = element colors { color+, colorSpace* } color = element color { attribute name { text }, label *, (RGB ? & sRGB ? & CMYK ? & Lab ? & HSV ? & HLS ? & Luv ? & XYZ ? & Yxy ? & Gray ? & YCbCr ?) } label = element label { attribute lang { text } ?, text } spaceAttribute = attribute space { text } RGBAttributes = attribute r { xsd:float }, attribute g { xsd:float }, attribute b { xsd:float } RGB = element RGB { spaceAttribute, RGBAttributes } sRGB = element sRGB { RGBAttributes } CMYK = element CMYK { spaceAttribute, attribute c { xsd:float }, attribute m { xsd:float }, attribute y { xsd:float }, attribute k { xsd:float } } Lab = element Lab { spaceAttribute, attribute L { xsd:float }, attribute a { xsd:float }, attribute b { xsd:float } } HSV = element HSV { spaceAttribute, attribute h { xsd:float }, attribute s { xsd:float }, attribute v { xsd:float } } HLS = element HLS { spaceAttribute, attribute h { xsd:float }, attribute l { xsd:float }, attribute s { xsd:float } } Luv = element Luv { spaceAttribute, attribute L { xsd:float }, attribute u { xsd:float }, attribute v { xsd:float } } XYZ = element XYZ { spaceAttribute, attribute x { xsd:float }, attribute y { xsd:float }, attribute z { xsd:float } } Yxy = element Yxy { spaceAttribute, attribute Y { xsd:float }, attribute x { xsd:float }, attribute y { xsd:float } } YCbCr = element YCbCr { spaceAttribute, attribute Y { xsd:float }, attribute Cb { xsd:float }, attribute Cr { xsd:float } } Gray = element Gray { spaceAttribute, attribute g { xsd:float } } colorSpace = element colorspace { attribute name { text }, attribute xlink:href { xsd:anyURI } } }
Using for validating
To use the above RelaxNG schema to validate a swatch you can use:
trang -I rnc -O rng colors.rnc colors.rng xmllint --relaxng colors.rng colors.xml
Proposition(-family) I: SVG-based
The motivations for using an SVG-based format are:
- Has an obvious extension to swatches other than solid colours: e.g. gradients, patterns, symbols.
- (More generally, developing an SVG-based importer for swatches may facilitate sharing of image data between apps, e.g. in the clipboard.)
- Interoperability: Has the most chance of being usable in applications that either don't follow FreeDesktop standards or that haven't yet developed swatch-handling facilities (but can read SVG files).
- Using an existing w3c standard may allow benefiting from the knowledge of those contributing to that spec; conversely, if we find any problems in that spec and report them, then we help to improve SVG.
- Knowledge of one format transfers to knowledge of the other.
- Shared work in defining the specification, e.g. the exact format allowed for numbers, whether HSL is defined in terms of sRGB or the current device's RGB space, etc.
- Avoid gratuitous incompatibilities with SVG, a format used to some degree or other by most programs wanting to implement this swatchbook specification.
- Possibly being able to use (some) pre-existing SVG files as a source of swatches.
A lot of SVG's color support is still in draft form, which is a mixed blessing: it allows us to influence the spec, but the flip side of being able to change the spec is that the spec may change :) .
A (solid colour) swatch is specified with the <solidColor> element.
Here's the "base" specification of the solidColor element, for SVG 1.2 Tiny: http://www.w3.org/TR/SVGMobile12/painting.html#SolidColorElement . Note that, being the "tiny" version of SVG, the text there is a restricted set of how colours may be specified in non-tiny SVG. See http://www.w3.org/TR/SVGPrint/#ColorIntroduction in SVGPrint for more advanced stuff, including icc-color, named colours, and device colours.
Translation of labels: We can either copy from one of the existing proposals (add a non-svg element like <label>, but in a non-SVG namespace), or use SVG's existing, syntactically-heavyweight solution of <name> and/or <desc> elements inside a <switch> element, with systemLanguage attributes. What's an appropriate namespace to use? The current proposal is to use <cfo:label lang="es-mx"> etc., i.e. same as proposal H's mechanism but with added namespace prefix. A writer can always use the SVG mechanism as well if the writer thinks it will be useful.
It is proposed that all swatches considered part of the swatchbook are in the first <defs> descendent of the first <svg> element of the document. The intent of this rule is so that readers can avoid reading the whole document for the use case of using existing large SVG documents as a source of swatches. The cost of this rule is restricting the number of swatches that might be extracted from a document. (Though most SVG documents aren't affected by this restriction: most SVG documents have only one <svg> element and no more than one <defs> element, and have all/any swatchable elements within that <defs>.)
Recursing into elements within the <defs>: The set of things to consider in deciding which elements readers should be recurse (descend) into in order to find swatches are future expansion, implementation simplicity, and extracting the desired set of swatches from existing SVG documents. Readers definitely should recurse into SVG's grouping element <g>, because someone has said [todo: add link] that it would be useful to allow grouping within a swatchbook, and <g> looks like a reasonable way of doing that. Readers should not recurse into elements in (non-SVG) namespaces, because of [SVG rules on foreign namespaces]. The <switch> element isn't special for our purposes: it only controls what gets displayed, it doesn't affect what swatches are defined (ref: [§5.8.1]). As yet there are no known strong arguments as to whether or not readers should descend into elements other than <g> and foreign-namespace elements. It is believed rare for existing documents to contain swatchable elements nested inside anything but <g>. There is a small CPU-time advantage in not descending elements. Based on these (weak) arguments (and one or two weak unwritten ones), the current proposal is not to descend into any element but <g>.
Restrictions on SVG syntax allowed
It is proposed that writers use XML attributes [other than style] to set properties, not CSS.
Furthermore, it is tentatively proposed that writers not make use of inheritance for specifying properties. A quick look doesn't reveal any properties that are at all useful to inherit for solid colour swatches (please update this sentence if appropriate). Implementing inheritance is easy, so this proposal could be changed; but not implementing inheritance is (slightly) easier still.
Error processing
Considerations/arguments for this matter are:
- Having tight error-handling rules means that all software extracts the same set of swatches from a given document, so one only needs to test one conformant program to know whether the swatchbook is error-free in all conformant programs.
- On the other hand, not all swatches are meaningful to all programs. In contexts where alpha or hue is meaningless, software might deliberately ignore non-fully-opaque or non-greyscale swatches, thus weakening the above argument. (This point would become stronger if/when the proposal is expanded to include gradients or patterns or the like. Certainly there are contexts where only solid colour swatches are meaningful, even if the suggestion of ignoring non-fully-opaque or non-greyscale swatches seems questionable.)
- For software that already implements SVG (and in particular the parts that this proposal excludes, such as CSS and inheritance), it is easier to continue to honour those parts of SVG than to have separate processing for swatch-extraction purposes.
- We'd like to honour [SVG error-processing rules] of ignoring anything after the first SVG error; but we don't want readers to need full knowledge of SVG correctness rules.
- Most existing Free Software that reads SVG does not follow said error-processing rules very closely.
- We want to allow for future expansion of the format in a backwards-compatible way.
It is suggested that all error handling be at a "should" or "may" level rather than a "must" level: i.e. that one may claim conformance to the swatchbook spec even if one does not implement the error processing specified here.
Given the above suggestion, nothing further is yet proposed for error processing, beyond suggesting that implementors consider the arguments/considerations listed above.
Proposition J
I haven't been active enough in the discussions and this was developed in relative isolation, so I don't necessarily want to push this specific solution. But I thought I should post it to provide some contrast to proposal H (they are really very similar except in certain key respects).
This is what I sketched out after a series of frustrating experiences with swatches and spot colors. It is a very simple format, designed for simplicity of implementation. It very deliberately focuses only on solid colors, ignoring tints, transparency, gradients, or patterns (in this respect, it is comparable to Adobe's ASE format). Importantly, it distinguishes between spot and process colors, permits the specification of rendering intent when performing color space conversions, and allows for ICC profiles to be directly embedded in the swatch file.
The format permits un-calibrated colorspaces because many legacy palettes do not specify an ICC profile. It also permits exact representation of legacy palettes whose colors were originally originally specified using values in the range 0-255 or as percentage values, by providing a per-colorspace scaling factor. Out-of-range values are permitted, but may be clamped by implementations.
The Schema permits foreign elements and attributes to be included. Additional functionality, such as alternate color representations for the same color and internationalized color names, are intended to be addressed by extensions.
As a matter of practice, implementations are probably best off treating uncalibrated RGB as sRGB, uncalibrated CMYK as SWOP CMYK, and so on.
Examples
The overall format consists of optional ICC profiles, followed by at least one colorspace specification, followed by zero or more colors. It is designed for in-order processing, facilitating streaming.
Each color has a name and a list of components in the color model of its associated colorspace. Spot colors are specially distinguished by the use of a spot-color (versus color) tag.
Two colorspaces, one of them calibrated
<?xml version="1.0"?> <colors version="0.9" xmlns="http://www.inkscape.org/namespaces/colors"> <icc-profile xml:id="my_printer_profile"> Base64omittedforbrevity= </icc-profile> <colorspace xml:id="my_printer" model="CMYK" icc-profile="my_printer_profile" rendering-intent="absolute-colorimetric" /> <colorspace xml:id="generic" model="CMYK" /> <color name="Blue" cs="my_printer" c="1 0.25 0 0" /> <color name="Yellow" cs="my_printer" c="0 0 1 0" /> <color name="Blah" cs="generic" c="0.8 0.25 0.25 0.2" /> </colors>
External ICC Profile
If the rendering intent for colors in a calibrated color space is omitted, it is assumed to be relative-colorimetric.
<?xml version="1.0"?> <colors version="0.9" xmlns="http://www.inkscape.org/namespaces/colors" xmlns:xlink="http://www.w3.org/1999/xlink"> <icc-profile xml:id="my_profile" xlink:href="my_profile.icm" /> <colorspace xml:id="my_colorspace" model="RGB" icc-profile="my_profile" /> <color name="Foo" cs="my_colorspace" c="0.0 0.2 0.25" /> </colors>
Default Color Space
When a color does not explicitly select a color space using the cs= attribute, the first colorspace in the file is used.
<?xml version="1.0"?> <colors version="0.9" xmlns="http://www.inkscape.org/namespaces/colors"> <colorspace xml:id="RGB_space" model="RGB" /> <colorspace xml:id="CMYK_space" model="CMYK" /> <color name="Bar" c="1.0 1.0 0.5" /> </colors>
Spot Colors
<?xml version="1.0"?> <colors version="0.9" xmlns="http://www.inkscape.org/namespaces/colors"> <colorspace model="CMYK" /> <spot-color name="RANTONE 100 PC" c="0 0 0.58 0" /> <spot-color name="RANTONE 101 PC" c="0 0 0.7 0" /> <spot-color name="RANTONE 102 PC" c="0 0 0.95 0" /> <spot-color name="RANTONE 103 PC" c="0.05 0.1 1 0.15" /> </colors>
Scaled Color Values
A color space can specify a scaling factor for its values (to losslessly support legacy palette data).
<?xml version="1.0"?> <colors version="0.9" xmlns="http://www.inkscape.org/namespaces/colors"> <colorspace model="RGB" scale="255" /> <color name="Red" c="255 0 0" /> <color name="Green" c="0 255 0" /> <color name="Blue" c="0 0 255" /> </colors>
sRGB
The sRGB tag is a variant of the colorspace tag which assumes the RGB color model, in sRGB space.
<?xml version="1.0"?> <colors version="0.9" xmlns="http://www.inkscape.org/namespaces/colors"> <sRGB scale="255" /> <color name="Red" c="255 0 0" /> <color name="Green" c="0 255 0" /> <color name="Blue" c="0 0 255" /> </colors>
Relax NG Schema
<?xml version="1.0" encoding="UTF-8"?> <grammar xmlns="http://relaxng.org/ns/structure/1.0" ns="http://www.inkscape.org/namespaces/colors" xmlns:xlink="http://www.w3.org/1999/xlink" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes"> <start><ref name="colors"/></start> <define name="colors"><element name="colors"> <ref name="any_foreign_attrs"/> <attribute name="version"><value>0.9</value></attribute> <optional><ref name="id.attr"/></optional> <optional><ref name="name.attr"/></optional> <ref name="any_foreign_elements"/> <zeroOrMore><ref name="icc_profile"/></zeroOrMore> <ref name="any_foreign_elements"/> <oneOrMore><ref name="colorspace"/></oneOrMore> <ref name="any_foreign_elements"/> <zeroOrMore><ref name="color"/></zeroOrMore> <ref name="any_foreign_elements"/> </element></define> <define name="colorspace"> <choice> <element name="colorspace"> <ref name="colorspace.attrs"/> <ref name="model.attr"/> <optional><ref name="icc_profile.attr"/></optional> <ref name="any_foreign_elements"/> </element> <element name="sRGB"> <ref name="colorspace.attrs"/> <ref name="any_foreign_elements"/> </element> </choice> </define> <define name="colorspace.attrs"> <ref name="any_foreign_attrs"/> <optional><ref name="id.attr"/></optional> <optional><ref name="scale.attr"/></optional> <optional><ref name="rendering_intent.attr"/></optional> </define> <define name="color"> <choice> <element name="color"> <ref name="color.attrs"/> <ref name="any_foreign_elements"/> </element> <element name="spot-color"> <ref name="color.attrs"/> <ref name="any_foreign_elements"/> </element> </choice> </define> <define name="color.attrs"> <ref name="any_foreign_attrs"/> <optional><ref name="id.attr"/></optional> <ref name="name.attr"/> <optional><ref name="cs.attr"/></optional> <ref name="c.attr"/> </define> <define name="icc_profile"><element name="icc-profile"> <ref name="any_foreign_attrs"/> <optional><ref name="id.attr"/></optional> <optional><ref name="name.attr"/></optional> <choice> <ref name="href.attr"/> <data type="base64Binary"><param name="minLength">1</param></data> </choice> </element></define> <define name="id.attr"><attribute name="xml:id"> <data type="ID"/> </attribute></define> <define name="href.attr"><attribute name="xlink:href"> <data type="anyURI"/> </attribute></define> <define name="name.attr"><attribute name="name"/></define> <define name="scale.attr"><attribute name="scale"> <data type="decimal"/> </attribute></define> <define name="model.attr"><attribute name="model"> <ref name="model_name"/> </attribute></define> <define name="cs.attr"><attribute name="cs"> <data type="IDREF"/> </attribute></define> <define name="rendering_intent.attr"><attribute name="rendering-intent"> <ref name="rendering_intent"/> </attribute></define> <define name="icc_profile.attr"><attribute name="icc-profile"> <data type="IDREF"/> </attribute></define> <define name="c.attr"><attribute name="c"> <list><oneOrMore><data type="decimal"/></oneOrMore></list> </attribute></define> <define name="model_name"> <choice> <value>XYZ</value> <value>Lab</value> <value>Luv</value> <value>YCbr</value> <value>RGB</value> <value>GRAY</value> <value>HSV</value> <value>HLS</value> <value>CMYK</value> <value>CMY</value> <value>2CLR</value> <value>3CLR</value> <value>4CLR</value> <value>5CLR</value> <value>6CLR</value> <value>7CLR</value> <value>8CLR</value> <value>9CLR</value> <value>ACLR</value> <value>BCLR</value> <value>CCLR</value> <value>DCLR</value> <value>ECLR</value> <value>FCLR</value> </choice> </define> <define name="rendering_intent"> <choice> <value>perceptual</value> <value>relative-colorimetric</value> <value>absolute-colorimetric</value> <value>saturation</value> </choice> </define> <define name="any_foreign_elements"> <zeroOrMore> <element> <anyName><except> <nsName/> </except></anyName> <ref name="any_attrs"/> <ref name="any_content"/> </element> </zeroOrMore> </define> <define name="any_foreign_attrs"> <zeroOrMore> <attribute> <anyName><except> <nsName/> <nsName ns=""/> <nsName ns="http://www.w3.org/1999/xlink"/> <name>xml:id</name> </except></anyName> </attribute> </zeroOrMore> </define> <define name="any_content"> <zeroOrMore> <choice> <text/> <element> <anyName/> <ref name="any_attrs"/> <ref name="any_content"/> </element> </choice> </zeroOrMore> </define> <define name="any_attrs"> <zeroOrMore><attribute><anyName/></attribute></zeroOrMore> </define> </grammar>
Strengths
- Implementation simplicity due to factors like streaming document order and the use of simpler types like xsd:decimal instead of xsd:float
- Allows embedding ICC profiles directly in swatches
- Lossless representation of common ranges like 0-1, 0-255, and 0-100
- Allows specification of suggested rendering intent for conversions to other color spaces
Weaknesses
- Internationalized names and alternate color specifications for a swatch entry must be provided by format extensions
- Treatment of spot colors does not correspond well to established models like device-color
Propositions for numbers
- integer (it needs to specify a range)
- float (encoding ?)
- both
Issues
color management
A colour needs a proper metric. Otherwise it is diffuse. RGB, CMYK, HLS can be everything and nothing.
- either refer to a known colour space like sRGB, Lab, XYZ or
- provide a ICC profile reference, by file name, possibly as a URI
As a common request, sRGB should always be present.

