- From: Rik Cabanier <cabanier@gmail.com>
- Date: Wed, 29 May 2013 16:19:27 -0700
- To: Dirk Schulze <dschulze@adobe.com>
- Cc: "public-fx@w3.org" <public-fx@w3.org>, www-svg <www-svg@w3.org>
- Message-ID: <CAGN7qDCNupB4otgm729PNeq48ezRiT0nV__HVjHk-kexh8=CFg@mail.gmail.com>
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