[cairo] Color space API

Kai-Uwe Behrmann ku.b at gmx.de
Mon Oct 15 10:14:46 PDT 2012

Am 28.07.12, 00:25 +0930 schrieb Adrian Johnson:
> time no one progressed it any further. Recently I've had some time to
> start looking at this. I'm interested in working out what would be the
> minimum API required to support the color space requirements of SVG
> and PDF.

Glad to see that topic is cared by someone. Your email must have been lost 
in the holyday streams of far too many email lists, which get usually 
lesser attention. And on the OpenICC email list it would have beed big 
news ;-)

> These two functions allow creating a color space from a given ICC
> file. Both SVG and PDF both support ICC profiles.
>  cairo_color_space_t *
>  cairo_color_space_create_icc_from_file (const char *filename);
>  cairo_color_space_t *
>  cairo_color_space_create_icc_from_memory (const char *data,
>                                            int length);

> The device_rgb color space is based on the PDF DeviceRGB color
> space. When both source and destination are in the device_rgb color
> space no color conversion is performed.
>  cairo_color_space_t *
>  cairo_color_space_create_device_rgb (void);
> The following two color spaces are used by SVG. There is an sRGB color
> space and a linear color space with the same primaries as sRGB but a
> linear gamma.
>  cairo_color_space_t *
>  cairo_color_space_create_srgb (void);
>  cairo_color_space_t *
>  cairo_color_space_create_linear_srgb (void);

> The standard cairo functions for referencing, destroying and obtaining
> the status and type.
>  cairo_color_space_t *
>  cairo_color_space_reference (cairo_color_space_t *color_space);
>  void
>  cairo_color_space_destroy (cairo_color_space_t *color_space);
>  unsigned int
>  cairo_color_space_get_reference_count (
>                             cairo_color_space_t *color_space);
>  cairo_status_t
>  cairo_color_space_status (cairo_color_space_t *color_space);
>  typedef enum _cairo_color_space_type {
>  } cairo_color_space_type_t;
>  cairo_color_space_type_t
>  cairo_color_space_get_type (cairo_color_space_t *color_space);

Looks like this API allows to detect if a ICC profile is internaly
You will have to extent this enum, in case future internal spaces shall 
be added. That would not be so nice from a API POV.

> ICC color spaces may contain different types of color spaces. It is
> useful be able to find the type of an ICC color space.
>  typedef enum _cairo_color_space_class {
>  } cairo_color_space_class_t;
>  cairo_color_space_class_t
>  cairo_color_space_get_class (cairo_color_space_t *color_space);

It is more handy to obtain the ICC profile memory. That allows to further 
analyse ICC profiles including the above colour space class query.

> We also need to know the number of components.
>  unsigned int
>  cairo_color_space_get_number_of_components (
>                               cairo_color_space_t *color_space);
> While patching poppler and inkscape to use this API I found the need
> to compare color space objects.
>  cairo_bool_t
>  cairo_color_space_equal (const cairo_color_space_t *cs_a,
>                           const cairo_color_space_t *cs_b);

Out of curiosity, is comparing cairo_color_space_t pointers not enough?

> To avoid adding solid color pattern create functions for every color
> space I've created one generic solid color constructor that supports
> multiple color spaces. The number of components must match the number
> of components in the color space.
>  cairo_pattern_t *
>  cairo_pattern_create_color (cairo_color_space_t *color_space,
>                              double *components, double alpha);
>  cairo_set_source_color (cairo_t *cr, cairo_color_space_t *color_space,
>                          double *components, double alpha);

Ah the equivalents to the existing functions, and in this case to 
cairo_set_source_rgba() .

> And a function for getting the color space of patterns. Patterns
> created with the existing API have device_rgb color space.
>  cairo_color_space_t *
>  cairo_pattern_get_color_space (cairo_pattern_t *pattern);
> The following functions create gradients with a color space. Like PDF,
> the color space of a gradient is both the color space of the source
> pattern and the interpolating color space for the gradient.
>  cairo_pattern_t *
>  cairo_pattern_create_linear_with_color_space (
>                                   cairo_color_space_t *color_space,
>                                                double x0, double y0,
>                                                double x1, double y1);
>  cairo_pattern_t *
>  cairo_pattern_create_radial_with_color_space (
>                               cairo_color_space_t *color_space,
>                               double cx0, double cy0, double radius0,
>                               double cx1, double cy1, double radius1);
>  cairo_pattern_t *
>  cairo_pattern_create_mesh_with_color_space (
>                                    cairo_color_space_t *color_space);
> These functions allow adding color stops when the gradient color space
> is not RGB.
>  void
>  cairo_pattern_add_color_stop (cairo_pattern_t *pattern, double offset,
>                                double *components,  double alpha);
>  void
>  cairo_mesh_pattern_set_corner_color (cairo_pattern_t *pattern,
>                                     unsigned int corner_num,
>                                     double *components, double alpha);
> The cairo_surface_set_color_space function allows setting a color space
> of a surface (for use as either a source or destination). The default
> surface color space is device_rgb but if it is to be changed it must
> be done before any drawing operations. The PDF surface also allows
> each page to have a different color space.
>  void
>  cairo_surface_set_color_space (cairo_surface_t *surface,
>                                 cairo_color_space_t *color_space);
>  cairo_color_space_t *
>  cairo_surface_get_color_space (cairo_surface_t *surface);
> cairo_push_group and cairo_surface_create_similar create a surface with
> the same color space as the existing surface. The following two functions
> allow the similar surface to be created with a different color space.
>  void
>  cairo_push_group_with_color_space (cairo_t *cr,
>                                     cairo_content_t content,
>                                     cairo_color_space_t *color_space);
>  cairo_surface_t *
>  cairo_surface_create_similar_with_color_space (cairo_surface_t *other,
>                                      cairo_content_t content,
>                                      cairo_color_space_t *color_space,
>                                      int width, int height);

Is that the prefered mechanism for colour space conversion of surfaces?

> Some other ideas I have not yet implemented:
> Spot colors could be implemented with a color space constructor that
> takes the name of the spot color and returns a 1 component color
> space. The one component selects the tint value. The constructor also
> specifies an alternative color space and color to use for surfaces
> that do not support spot colors. When falling back to using the
> alternate color the tint value can be used as the alpha of the
> alternate color.
>  cairo_color_space_t *
>  cairo_color_space_create_spot_color (const char *name,
>                                    cairo_color_space_t *alternate_cs,
>                                    double *alt_components);
> Antti Lankila has created a pixman patch for linear color space
> processing[4]. In this case the source and destination are converted
> from sRGB to linear rgb, composited, then converted back to sRGB
> before writing to the destination. This could possibly be implemented
> with a function like cairo_set_compositing_color_space() or
> cairo_set_blending_color_space().

What is the difference of the compositing_color_space to a surface 
colour space?

Overall the API looks sane. All the best for it.

kind regards
Kai-Uwe Behrmann
developing for colour management 
www.behrmann.name + www.oyranos.org

> [1] http://lists.cairographics.org/archives/cairo/2009-December/018717.html
> [2] http://cgit.freedesktop.org/~ajohnson/  (in the color-space branches)
> [3] http://cgit.freedesktop.org/~ranma42/cairo/log/?h=wip/cs11
> [4] http://lists.freedesktop.org/archives/pixman/2012-June/002036.html

More information about the cairo mailing list