You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 8 Next »

Color Handling

Introduction

This page shall discuss an approach to represent the various colors supported by upcoming SVG and XSL-FO specifications in Java.

Requirements

Both SVG and XSL-FO allow specification of color in various color spaces (defined by ICC color profiles, with 1, 3, 4 or n components). In both cases, sRGB is the default color space. sRGB also serves as fallback in both cases. With SVG 1.2 and XSL 2.0, additional color specifications will be introduced. Among these are:

  • device-specific (uncalibrated) colors, mainly for specifying CMYK colors, but also for gray, RGB values and N-Component colorspaces (like HP's IndiChrome 6-color printing).
  • CIE Lab and CIE LCHab colors
  • ICC Named Color (for spot colors)

Not all possible output formats for SVG and XSL-FO documents support all of the above color specifications. In all cases, fallback colors in sRGB color space are specified to achieve at least an approximation of the intended color. What's intended here is to find a way to represent these colors as primary color specifications for output formats that support them. In all other case, the sRGB fallback shall be used. There are a few more details in the SVG Color spec:

  • For calibrated colors (ICC color, ICC named color or CIE Lab/LCHab ), the spec says that the user agent shall use these and convert to other color spaces (for interpolation or compositing, for example) using the specific color values rather than the sRGB fallback.
  • For device-specific colors, the color values are to be passed through to the output device but interpolation and compositing shall occur using the sRGB fallback.

Although not clearly specified, yet, it can be assumed that XSL-FO 2.0 will handle this in a similar way. XSL 1.1, at any rate, clearly says that the sRGB fallback is only used for ICC colors, if the associated color profile is unavailable.

So, we're presented with essentially two different way of color handling: Use the calibrated color if supported and the calibration info (color profile) is available. Device-specific colors are only used in the output format if it is supported and not involved in any color calculations. The sRGB fallback has a more important role in the latter case.

FOP-specific requirements

Apache FOP has two XML-based intermediate formats which makes it necessary to generate textual representations from the decoded original color specification. So there is need for a round-trip possibility. That means that we can't simply use the ColorSpace instance but also have to carry a name and a URI for the color profile/space.

Color in the Java class library

java.awt.Color is Java's way to specify color, primarily in the sRGB color space. But it also has constructors taking a [ColorSpace] parameter, so arbitrary colors with n components and color values between 0.0 and 1.0 can be specified. The class uses the float[] [ColorSpace].toRGB(float[]) method to calculate the sRGB fallback value for such a color.

What the class doesn't support is the specification of named colors based on an ICC named color profile (or any other source for named colors). A possible work-around is thinkable: A named color profile is split up into its various named colors and a ColorSpace object is created for each of them with one component each for the tint (see notes below).

java.awt.Color's equals() method has a little problem: it doesn't detect the difference between two different colors using the same sRGB fallback. Example: if there is a plain Color(255, 204, 0) and a Color descendant with additional color information but with the same sRGB values, they may be regarded as equal although they are not.

Current state (2010-06-15)

A ColorExt class was moved from FOP to XGC. It has its own set of RGB replacement values and fields for the name and URI of a color profile. Some code in there seems not to be used anywhere and other code appears to duplicate functionality of the superclass (Color). The ColorExt class is not sufficient to carry named colors, for example.

Apparently, the replacement values in ColorExt were introduced to have access to the original fallback values, since Color calculates the sRGB values using the ColorSpace which may not be the same value as the fallback. And the superclass doesn't allow write access to the sRGB values through the ICC-based constructor.

The member variable colorValues of ColorExt saves the same values as fvalue in the super class, so this seems to be superfluous.

Batik currently only supports sRGB colors and ICC colors with a backing (and loaded) ICC profile. No access is possible to the original ICC profile file (only the loaded data is available) since plain Java classes are used. However, Batik has a class ICCColorSpaceExt which can hold a rendering intent override (an ICC color profile has a rendering intent value, too) and calculates sRGB values by selected rendering intent. That could be useful to FOP, too, so the functionality is also a candidate to be ported to XGC. One current problem in Batik is that ICC colors are converted to sRGB on the input side, rather than the output side (information is lost even when a conversion to sRGB is not necessary or not desired). This will have to be changed so the specific color is preserved as long as possible. Fortunately, the Color class can always return the corresponding sRGB value when needed.

Current state (2010-07-02)

With the XGC 1.4 release, the ColorExt class has been moved back to FOP pending the color redesign discussed on this page.

Ideas

It may make sense to create multiple subclasses of the Color class for the various color specifications, but:

Right now, SVG and XSL define an optional "real" color and a mandatory sRGB fallback. XSL uses single functions which include the sRGB fallback as part of the function. SVG, however, specifies the sRGB fallback in front and the color function after that. The latter has greater flexibility since it would allow to extend the paint specification so it can specify more than 2 colors as a prioritized list. The implementation could then choose the best color that the selected output format supports. Example: PDF supports to specify and use multiple calibrated color spaces. When generating a bitmap, only one color space may be used which means that colors not matching that color space have to be converted via CIE XYZ or CIE LAB color spaces. However, color conversions can be lossy. But this is might go too far. Still, implementations will have to deal with certain color conversions if they don't always want to fallback to the sRGB values since that has a smaller gamut than other color spaces and is using additive colors rather than subtractive ones better suited for printing.

So, another possibility is to attach additional color specifications to the main Color(Ext) instance and the super class' constructor simply receives the fallback sRGB color. The additional color specifications would be held as an ordered list which also represents the prioritized order of the color with the sRGB always being the last in the chain. So the primary color would always be a plain sRGB color value but could optionally contain one or more additional colors which implementations can choose over the fallback. That would avoid the work-around with the various local variables in ColorExt.

For calibrated colors, the specific color could be used as the primary color (since the sRGB color is only to be used if a color profile is unavailable). Additional color specifications could be attached to the ordered list of alternative colors mentioned above.

For device-specific colors, the sRGB fallback is the primary color. The alternative is only used if the output format supports it and no color calculations were necessary.

ColorExt could be relieved of the replacement and original color values and the additional color profile variables. Instead we'd create additional subclasses for ICC-based colors which simply carries the name and URI for the color profile in addition to the stuff inherited from java.awt.Color. For device-specific colors, we could also use the same class but work with specially marked ColorSpace instances (a slightly enhanced CMYKColorSpace, for example) instead of normal ICC profiles.

For each named color, we'd have to provide a new ColorSpace instance with just one component for the tint, so it will probably have to have type ColorSpace.TYPE_GRAY which is the only one with just one component. Maybe the alpha value could actually be used instead but that's not sure. The tricky thing here is probably to calculate the right XYZ coordinate for the various tint values given a specific white point if the color shall be used directly by the Java2D subsystem which is not necessary for just embedding the color spec in the output format. Once support for named color profiles is available, those special color spaces could be linked together with a common parent representing the actual named color profile.

A sketch given the above:

public class ColorWithAlternatives extends Color {

    private List<Color> alternativeColors;

[..]
}

public class ICCColor extends Color {

    private String iccProfileName;
    private String iccProfileSrc;

[..]
}

public class DeviceCMYKColorSpace extends ColorSpace .... //4 components, TYPE_CMYK
public class DeviceRGBColorSpace extends ColorSpace .... //3 components, TYPE_RGB
public class DeviceGrayColorSpace extends ColorSpace .... //1 component, TYPE_GRAY
public class NamedColorSpace extends ColorSpace .... //1 component, TYPE_GRAY
public class CIELabColorSpace extends ColorSpace .... //3 components, TYPE_LAB
public class CIELCHabColorSpace extends ColorSpace .... //3 components, TYPE_LAB

Various notes

ICC Named Color Profiles

The ICC specification provides a way to specify various named spot colors in a color profile. However, this facet is not very well supported by consumers as well as producers of ICC color profiles. So while the use of ICC named colors is not a bad idea per se, without the right tooling, it is rather difficult to handle. Furthermore, many print shops define named colors directly on the RIP/printer. PDF and PostScript allow to specify a "Separation" color space with an abstract named color which is only mapped to the final spot color on the RIP (raster image processor). In this case an ICC named color profile is not involved. This may make it necessary to define pseudo (or virtual) named color profiles which take their color specs from somewhere else (like a proprietary XML file). Furthermore, PDF and PostScript don't allow using an ICC named color profile.

Using named/spot colors

In offset printing spot colors are special inks that are premixed to achieve an exact color instead of having to mix the right color from 4 or more subtractive colors. That way it is, for example, possible to put a layer of gold "ink" on paper.

Often, named (or spot) colors are accompanied with a single tint value that specifies the amount of coverage with the spot color. 0.0 uses no ink while 1.0 specifies the maximum ink usage (complete coverage). For example, PDF's separation color space supports that. It is however interesting that at the moment the SVG and XSL working drafts don't provide means to specify tints on named colors.

Spec references

Color-related information sources

  • No labels