- From: Dirk Schulze <dschulze@adobe.com>
- Date: Wed, 29 May 2013 16:43:37 -0700
- To: Rik Cabanier <cabanier@gmail.com>
- CC: "public-fx@w3.org" <public-fx@w3.org>, www-svg <www-svg@w3.org>
On May 29, 2013, at 4:19 PM, Rik Cabanier <cabanier@gmail.com> wrote: > > > 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. If we replace the formulas with the one without compositing, what would it mean for blending two intermediate results? The result would exclude compositing completely. It is unclear how this can be done. Note that feBlend and feComposite is not always the last primitive, so even for BackgroundImage there are problems on the next filter primitive in the chain. Greetings, Dirk > > > > 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:44:07 UTC