[cairo] Color space API

Behdad Esfahbod behdad at behdad.org
Mon Oct 15 14:58:55 PDT 2012


On 12-07-27 09:55 AM, Adrian Johnson wrote:
>   cairo_color_space_t *
>   cairo_color_space_create_icc_from_memory (const char *data,
>                                             int length);

Stream constructor please, like other cairo API.


> 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);

Does it make sense to be able to attach color space to cairo_device_t, and let
device_rgb mean "inherit from device"?


> 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);

What's sRGV about linear_srgb?  Sounds to me linear_rgb.  Also, maybe instead
have a generic rgb space that takes a gamma value?


> 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_RGB,
>     CAIRO_COLOR_SPACE_CLASS_CMYK,
>     CAIRO_COLOR_SPACE_CLASS_GRAY,
>   } cairo_color_space_class_t;
> 
>   cairo_color_space_class_t
>   cairo_color_space_get_class (cairo_color_space_t *color_space);
> 
> 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);
> 
> 
> 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);
> 
> 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);
> 
> 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().

As far as I understand, blending should always happen in linear space.  But
reading the thread I see that thi cannot be extracted from ICC profiles.


One thing I see missing in the API is color intents.  Was that intentional?


behdad


> 
> [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