Re: [filter-effects] feBlend filter (was: Re: [css-filters] feBlend filter)

On Wed, May 29, 2013 at 3:47 PM, Dirk Schulze <dschulze@adobe.com> wrote:

> Hi,
>
> See inline comments:
>
> On May 29, 2013, at 1:52 PM, Rik Cabanier <cabanier@gmail.com> wrote:
>
> > All,
> >
> > last week Michael Mullany posted a screenshot of a transformed feBlend
> filter: http://tinypic.com/r/rc3qs0/5 [1]
> > The thing that struck me what that the part of the backdrop was pulled
> into the filter (so a piece of the red rectangle was copied over).
> >
> > After thinking this over a bit, I think that there's a flaw in how the
> feBlend filter currently works.
> > Given the following markup:
> >     <defs>
> >     <filter id="what" >
> >       <feBlend mode="screen" in="SourceGraphic" in2="BackgroundImage"/>
> >     </filter>
> >   </defs>
> >
> >   <g enable-background="new">
> >     <rect width="100" height="100" fill="red"/>
> >     <g filter="url(#what)">
> >       <rect x="50" y="50" width="100" height="100" fill="rgb(0,255,0)"
> opacity=".5"/>
> >     </g>
> >   </g>
> >
> > This snippet of SVG, implies that the content of <g> will be blended
> with the backdrop.
> > The formula of 'feBlend ' with a 'screen' blend mode [2] is:
> > cr = cb + ca - ca * cb
> > This formula is the combination of a screen blend + a source-over
> composite [3]. This seems reasonable.
> > However, the result of this filter is then again composited (because of
> normal alpha compositing) so the blended content is composited twice.
> >
> > You can observe that behavior in the following markup [4]:
> >   <defs>
> >     <filter id="what" >
> >       <feBlend mode="normal" in="SourceGraphic" in2="BackgroundImage"/>
> >     </filter>
> >   </defs>
> >
> >   <g enable-background="new">
> >     <rect width="100" height="100" fill="red"/>
> >     <g filter="url(#what)">
> >       <rect x="50" y="50" width="100" height="100" fill="rgb(0,255,0)"
> opacity=".5"/>
> >     </g>
> >   </g>
> >
> >   <g enable-background="new" transform="translate(0,200)">
> >     <rect width="100" height="100" fill="red"/>
> >     <g>
> >       <rect x="50" y="50" width="100" height="100" fill="rgb(0,255,0)"
> opacity=".5"/>
> >     </g>
> >   </g>
> >
> > See the attached png for a screenshot.
> > The intersection of the 2 rectangles looks different because the one
> with the filter is composited twice.
> >
> > I believe the problem is with the formulas for 'feBlend'. They shouldn't
> also do compositing.
> > Because of this, you can't correctly implement blending with SVG filters.
> >
> > I'm unsure how this can be fixed cleanly since it's probably too late to
> change the blend formulas. Maybe we can introduce a new filter primitive?
> >
>
>
> I think I can see your point. Doesn't the same apply to feComposite?


yes. An 'feComposite' with the backdrop will always be followed with
source-over.


> Also, todays use of feBlend and feComposite is limited to blend and
> composite intermediate filter effects results with each other (due to the
> lack of BackgroundImage support on browsers). I think for these operations
> the compositing step in feBlend makes sense, even so you still have the
> compositing of the filter result to the canvas.


That's true.


> I do not understand how a new filter primitive can solve this problem if
> you still have the compositing step at the end. Can you elaborate more on
> your suggestion?
>

My issue is that the formulas for feBlend always composite, so we need
formulas that don't do this.

These formulas don't composite and are in non premultiplied alpha:
Normal:  Cr = Cs
Multiply: Cr = (1 - áb) x Cs + áb x B(Cb, Cs) = (1 - áb) x Cs + áb x Cb x Cs
Screen:  Cr = (1 - áb) x Cs + áb x B(Cb, Cs) = (1 - áb) x Cs + áb x (Cb +
Cs - (Cb x Cs)) = Cs + áb x (Cb - (Cb x Cs))
Darken:  Cr = (1 - áb) x Cs + áb x B(Cb, Cs) = (1 - áb) x Cs + áb x min(Cb,
Cs)
Lighten:  Cr = (1 - áb) x Cs + áb x B(Cb, Cs) = (1 - áb) x Cs + áb
x max(Cb, Cs)

For premultiplied alpha, they become:
Normal:  cr = cs
Multiply: cr = (1 - áb) x cs + cb x cs
Screen:  cr = (1 - áb) x cs + ás x áb x (Cb + Cs - (Cb x Cs)) = cs + ás x
cb - cb x cs
Darken:  cr = (1 - áb) x cs + ás x áb x min(Cb, Cs) = (1 - áb) x cs +
min(ás x cb, áb x cs)
Lighten:  cr = (1 - áb) x cs + ás x áb x B(Cb, Cs) = (1 - áb) x cs + max(ás
x cb, áb x cs)
*Mu*
These formulas either replace the ones for feBlend, or become the ones for
a new filter primitive.

>
>
> > 1: http://lists.w3.org/Archives/Public/www-style/2013May/0621.html
> > 2:
> https://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html#feBlendElement
> > 3:
> https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blending
> > cr = ás x (1 - áb) x Cs + ás x áb x B(Cb, Cs) + (1 - ás) x áb x Cb
> > = ás x (1 - áb) x Cs + ás x áb x (Cb + Cs -(Cb x Cs)) + (1 - ás) x áb x
> Cb
> > = ás x Cs - ás x áb x Cs + ás x áb x Cb + ás x áb x Cs - ás x áb x  Cb x
> Cs + áb x Cb - ás x áb x Cb
> > = ás x Cs - ás x áb x  Cb x Cs + áb x Cb
> > = cs - cs x cb + bc
> > 4: http://www.codepen.io/seraphzz/pen/jideo (Only IE 10 +)
> >
> > <feblend.png>
>
> Greetings,
> Dirk
>
>

Received on Wednesday, 29 May 2013 23:20:00 UTC