[cairo] Blend modes take 3

Soeren Sandmann sandmann at daimi.au.dk
Sat Oct 18 16:54:17 PDT 2008


Below are some observations about blend modes and their relationship
with Porter/Duff. I also have some comments on the code itself, but I
think it's worthwhile first figuring out how blend modes fit in

Benjamin's code is available in the blend-mode branch of this


The cgit page is here:


The new blend modes generally follow the PDF spec - the blend modes in
SVG 1.2 were reverse engineered from Photoshop and therefore different
in some cases, but their intention is to match PDF, so I agree that
following PDF is the way to go.

Relationship to Porter/Duff

For this part of this email to make sense, you will need to have read
the Porter/Duff paper [1].

The PDF modes are all based on a modification of the Porter/Duff OVER
operator. In the Porter/Duff paper alpha is treated as coverage, and
the operators are characterized by the contribution of source and
destination in the four areas "Covered by source only", "Covered by
destination only", "Covered by both" and "Covered by None". Here are
the characterizations of some of the operators:

          SRC            DEST              BOTH            NONE

OVER       S              D                 S               0
OVER_REV   S              D                 D               0
IN         0              0                 S               0
IN_REV     0              0                 D               0

In this framework, the PDF operators all look like this:

PDF_OP     S              D               f(D, S)           0

where f(D, S) depends on the blend mode. For the NORMAL blend mode we
have f(D, S) = S, which is the same as OVER, so Benjamin doesn't add
that one. For the MULTIPLY blend mode, f(D, S) = D * S, etc.

This sort of suggests that instead of adding all the PDF blend modes
as separate operators, they could instead be given as modifiers to an
existing operator. For example, you could then specify IN and
MULTIPLY, and the result would be 

IN, MULT   0              0                D * S            0

All the REV operators would then fall out as just the non-REV operator
plus a "DST" blend mode:


This is substantially more general approach than just adding the
blendmodes alongside the existing operators. If hardlight is useful,
you would think that it's just as useful with the "IN" operator.  It
seems to me that this way of thinking of blend modes would be more in
the spirit of the Render extension and more of a Right Way to do it.

Whether it's useful and/or worth the trouble, is another matter.

It is worth noting that the existing "ADD" operator, which is not
actually one of the original Porter/Duff ones, can almost be thought
of as just a blend mode, one where f(D,S) = D + S. The main difference
is that Render's ADD also adds the alpha channels whereas specifying
it as a blendmode would use the standard a_s + a_d - a_s * a_d
alpha. (This is actually what PLUS in the Porter/Duff paper would call
for if you believe the diagram).

Flash operators

Two new operators, Invert and Subtract, are not in the PDF spec. They
were introduced by Flash and are described here:


"Subtract" subtracts source values from the destination. In Benjamin's
implementation, the destination alpha is always used. Naively it seems
to me that it would make more sense to make Subtract the inverse
operation of Add, which would call for also subtracting the alpha

"Invert", in Benjamin's implementation seems to interpolate between
the destination and the inverse destination according to the alhpa of
the source. This has the effect of completely inversing anywhere the
source has alpha 1 and leaving the destination in place where the
source alpha is 0. 

Neither of these operations are specifiable in the Porter/Duff or the
PDF framework. There is also no specification anywhere that I can
find, not even in the SWF file format spec.

There is some rationale here:


Maybe this one could be done by simply using the blending with white
and using the Difference blend mode? Is there a way that Subtract can
be made more regular?


"Benjamin Otte" <otte at gnome.org> writes:

> Here's an update after yesterday's comments:
> I've investigated the relevant specifications that support blend modes:
> - ISO32000 (PDF standard based on 1.7)
> http://www.adobe.com/devnet/acrobat/pdfs/PDF32000_2008.pdf
> People I've asked agree that this should be the definitive reference
> for how blend modes should work in Cairo.
> - Adobe PDF 1.7 specification
> http://www.adobe.com/devnet/pdf/pdfs/blend_modes.pdf
> This one is identical to the ISO spec (unless I've missed something).
> - SVG 1.2 draft specification
> http://www.w3.org/TR/2004/WD-SVG12-20041027/rendering.html
> The SVG blend modes are based on reverse-engineering the PDF ones,
> before they were published. Slight differences exist. But after asking
> the SVG working group, they claimed that the SVG spec should be
> adapted to match PDF. See
> http://www.w3.org/Graphics/SVG/WG/track/issues/2095 for example.
> THere's also discrepancies in corner cases for color-dodge and
> color-burn.
> I've also looked at applications and libraries to figure out how they
> implement blend modes. I haven't tested their adherance to the specs
> when not having source code, but compared their output to apps where I
> do have source code available:
> - Adobe Reader: Matches the PDF spec
> - Adobe Photoshop CS 2: Matches the PDF spec
> - Adobe Flash: Matches PDF and SVG specs (omits non-matching blend modes)
> - Apple Quartz 2D: Matches the PDF spec (tested using Preview.app and a PDF)
> - Trolltech Qt: (Almost) matches the SVG spec
> - GiMP/GEGL: Matches the SVG spec
> - Poppler's Splash backend: Matches the PDF spec (at least tries)
> - My current patch: Matches the SVG spec
> Looking at the above data and at the opinions of the people I've
> talked to, the obviously best idea is to make Cairo match the PDF
> specification, which is what I will be doing next.
> I've already added the patch from Adrian that implements blend modes
> for the PDF backend, and I'm running modified versions of Poppler,
> librsvg and Swfdec that make use of the blend modes (and for testing).
> What is still missing is the blend mode patch for the Quartz backend.
> This should be relatively simple from looking at the code if one
> changes calls to "CGContextSetCompositeOperation (surface->cgContext,
> _cairo_quartz_cairo_operator_to_quartz (op));" with a "status =
> _cairo_quartz_set_operator (surface->cgContext, op)" which would allow
> returning unsupported for the Flash-only operators. However, I don't
> run OS X, so I can't make this work. I'd love to get the output of the
> extended-blend test from that though, so I can be sure we do the right
> thing on Quartz.
> Cheers,
> Benjamin
> _______________________________________________
> cairo mailing list
> cairo at cairographics.org
> http://lists.cairographics.org/mailman/listinfo/cairo

More information about the cairo mailing list