New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[filter-effects] Why can't opacity() filter function ever increase opacity? #178

Closed
AmeliaBR opened this Issue May 25, 2017 · 12 comments

Comments

Projects
None yet
6 participants
@AmeliaBR

AmeliaBR commented May 25, 2017

The description of the shorthand opacity() filter function says:

Values of amount over 100% are allowed but UAs must clamp the values to 1.

Was there a practical reason why the function cannot be used to increase opacity? Have browsers implemented the clamping of the input parameter? Or do they only clamp the final value? (Sorry, don't have time to test right now...)

I think it removes much of the usefulness of the function that it can't be used to increase opacity of semi-transparent regions (e.g., of blurred edges created by blur() or drop-shadow() ).

@AmeliaBR AmeliaBR changed the title from [filter-effects] Why can't opacity() filter function every increase opacity to [filter-effects] Why can't opacity() filter function ever increase opacity? May 25, 2017

@tabatkins

This comment has been minimized.

Show comment
Hide comment
@tabatkins

tabatkins May 26, 2017

Member

I think it's kinda weird to do it multiplicatively; in particular, it means that something which is currently 0% opacity can't ever become visible, but something that's 1% can be (with an opacity of 10000%, for example). But opacity() can't do additive modification.

Member

tabatkins commented May 26, 2017

I think it's kinda weird to do it multiplicatively; in particular, it means that something which is currently 0% opacity can't ever become visible, but something that's 1% can be (with an opacity of 10000%, for example). But opacity() can't do additive modification.

@tabatkins

This comment has been minimized.

Show comment
Hide comment
@tabatkins

tabatkins May 26, 2017

Member

Or, from another direction: all the filters can be conceptually thought of as just rendering the subject to a bitmap and then fiddling with the pixels. To have >100% opacity work, you'd need to allow the alpha channel of the pixels to be an unbounded value, which is very inconsistent with current models of pixel color.

Member

tabatkins commented May 26, 2017

Or, from another direction: all the filters can be conceptually thought of as just rendering the subject to a bitmap and then fiddling with the pixels. To have >100% opacity work, you'd need to allow the alpha channel of the pixels to be an unbounded value, which is very inconsistent with current models of pixel color.

@AmeliaBR

This comment has been minimized.

Show comment
Hide comment
@AmeliaBR

AmeliaBR May 26, 2017

I think it's kinda weird to do it multiplicatively; in particular, it means that something which is currently 0% opacity can't ever become visible, but something that's 1% can be

That's exactly the functionality I want!
You can currently apply multiplicative alpha with <feComponentTransfer> and I use it to make blurred edges more opaque (without also suddenly creating a solid background out of nothing).

And as far as weirdness goes, I'd say it's even less intuitive for brightness, which also works as a multiplicative factor: you can use brightness(255) to turn every shade of gray that isn't pure black into white, but black itself will never get any brighter. (Also true for pure saturated colors with one channel at 0; that channel never gets any brighter.)

To have >100% opacity work, you'd need to allow the alpha channel of the pixels to be an unbounded value, which is very inconsistent with current models of pixel color.

I'm not saying that the end result should be something greater than 100% opacity. The output of the filter operator would be clipped to the allowable range, just like it is for every other operator.


It would be nice to also have an additive option for both opacity and brightness. Maybe a second parameter to the function (which would then be the intercept in the <feComponentTransfer> function). But that's a separate feature, I think.

AmeliaBR commented May 26, 2017

I think it's kinda weird to do it multiplicatively; in particular, it means that something which is currently 0% opacity can't ever become visible, but something that's 1% can be

That's exactly the functionality I want!
You can currently apply multiplicative alpha with <feComponentTransfer> and I use it to make blurred edges more opaque (without also suddenly creating a solid background out of nothing).

And as far as weirdness goes, I'd say it's even less intuitive for brightness, which also works as a multiplicative factor: you can use brightness(255) to turn every shade of gray that isn't pure black into white, but black itself will never get any brighter. (Also true for pure saturated colors with one channel at 0; that channel never gets any brighter.)

To have >100% opacity work, you'd need to allow the alpha channel of the pixels to be an unbounded value, which is very inconsistent with current models of pixel color.

I'm not saying that the end result should be something greater than 100% opacity. The output of the filter operator would be clipped to the allowable range, just like it is for every other operator.


It would be nice to also have an additive option for both opacity and brightness. Maybe a second parameter to the function (which would then be the intercept in the <feComponentTransfer> function). But that's a separate feature, I think.

@AmeliaBR

This comment has been minimized.

Show comment
Hide comment
@AmeliaBR

AmeliaBR May 26, 2017

I use it to make blurred edges more opaque (without also suddenly creating a solid background out of nothing).

PS. This is used in the nice SVG version of the so-called "gooey" filter effect. In contrast, the current all-shorthand version that is popular requires adding a solid background and using contrast(), which ruins colors.

Example: https://codepen.io/AmeliaBR/details/jmReYr/

AmeliaBR commented May 26, 2017

I use it to make blurred edges more opaque (without also suddenly creating a solid background out of nothing).

PS. This is used in the nice SVG version of the so-called "gooey" filter effect. In contrast, the current all-shorthand version that is popular requires adding a solid background and using contrast(), which ruins colors.

Example: https://codepen.io/AmeliaBR/details/jmReYr/

@dirkschulze

This comment has been minimized.

Show comment
Hide comment
@dirkschulze

dirkschulze Jun 10, 2017

Contributor

@AmeliaBR Just to verify, you want the intermediate opacity value to increase beyond 100% but the input as well as the output of the opacity() effect would still be clamped?

Contributor

dirkschulze commented Jun 10, 2017

@AmeliaBR Just to verify, you want the intermediate opacity value to increase beyond 100% but the input as well as the output of the opacity() effect would still be clamped?

@AmeliaBR

This comment has been minimized.

Show comment
Hide comment
@AmeliaBR

AmeliaBR Jun 10, 2017

Inputs and outputs would be clamped. The multiplicative factor would not be clamped. So opacity(200%) would double the per-pixel alpha values of the input image, and then clamp them (per pixel) to the range 0-1.

The equivalent long-hand definition would be:

<filter id="opacity">
  <feComponentTransfer>
      <feFuncA type="linear" slope="[amount]"/>
  </feComponentTransfer>
</filter> 

where [amount] is the shorthand parameter as a decimal number.

AmeliaBR commented Jun 10, 2017

Inputs and outputs would be clamped. The multiplicative factor would not be clamped. So opacity(200%) would double the per-pixel alpha values of the input image, and then clamp them (per pixel) to the range 0-1.

The equivalent long-hand definition would be:

<filter id="opacity">
  <feComponentTransfer>
      <feFuncA type="linear" slope="[amount]"/>
  </feComponentTransfer>
</filter> 

where [amount] is the shorthand parameter as a decimal number.

@dirkschulze dirkschulze added the Agenda+ label Jan 2, 2018

@AmeliaBR

This comment has been minimized.

Show comment
Hide comment
@AmeliaBR

AmeliaBR Jan 17, 2018

A test of how browsers currently handle opacity filter values greater than 1 / 100%:
https://codepen.io/AmeliaBR/pen/ypRgEY?editors=0100

Sadly for me, they all seem to match the spec. Parameters are clamped to 1, so that opacity of a partially-transparent element can never be increased with the shorthand filters.

AmeliaBR commented Jan 17, 2018

A test of how browsers currently handle opacity filter values greater than 1 / 100%:
https://codepen.io/AmeliaBR/pen/ypRgEY?editors=0100

Sadly for me, they all seem to match the spec. Parameters are clamped to 1, so that opacity of a partially-transparent element can never be increased with the shorthand filters.

@svgeesus

This comment has been minimized.

Show comment
Hide comment
@svgeesus

svgeesus Jan 24, 2018

Contributor

Sadly for me, they all seem to match the spec. Parameters are clamped to 1, so that opacity of a partially-transparent element can never be increased with the shorthand filters.

That seems to imply that we should continue to require clamping, but then later have an explicit no-clamping opt-in.

Contributor

svgeesus commented Jan 24, 2018

Sadly for me, they all seem to match the spec. Parameters are clamped to 1, so that opacity of a partially-transparent element can never be increased with the shorthand filters.

That seems to imply that we should continue to require clamping, but then later have an explicit no-clamping opt-in.

@smfr

This comment has been minimized.

Show comment
Hide comment
@smfr

smfr Jan 24, 2018

I think we should keep opacity() as a multiplicative alpha effect, just like the opacity CSS property. If we want to allow some different behavior, I think that would be a new filter that exposes the kinds of things that feComponentTransfer can do.

smfr commented Jan 24, 2018

I think we should keep opacity() as a multiplicative alpha effect, just like the opacity CSS property. If we want to allow some different behavior, I think that would be a new filter that exposes the kinds of things that feComponentTransfer can do.

@AmeliaBR

This comment has been minimized.

Show comment
Hide comment
@AmeliaBR

AmeliaBR Jan 24, 2018

as a multiplicative alpha effect

Technically, what I'm asking for would still be a multiplicative alpha effect. Just allowing multiplication with values greater than 1. 😉

opacity() as currently defined has very few use cases in the filter property, since there's nothing it can do that the opacity property can't. I've seen it used as part of workarounds for broken supports testing, that's all. It would have some use in the image filter function (if anyone implemented that).

I agree that adding any other behavior (e.g., additive offsets) would be something to defer to another level of the spec.

The problem with defering opacity(150%) to a future spec is that, as it is currently spec'd, that is a valid declaration. The parser accepts it. It just doesn't have any effect different from opacity(100%). So changing later becomes a compat risk.

(Maybe it's already a compat risk, I don't know. People could be doing weird things with calc and variables, confident that if the result is at least 100% then the filter won't change anything.)

Adding this functionality in the future would require adding a separate function (alpha(), maybe), that has the full functionality that opacity() should have had.

AmeliaBR commented Jan 24, 2018

as a multiplicative alpha effect

Technically, what I'm asking for would still be a multiplicative alpha effect. Just allowing multiplication with values greater than 1. 😉

opacity() as currently defined has very few use cases in the filter property, since there's nothing it can do that the opacity property can't. I've seen it used as part of workarounds for broken supports testing, that's all. It would have some use in the image filter function (if anyone implemented that).

I agree that adding any other behavior (e.g., additive offsets) would be something to defer to another level of the spec.

The problem with defering opacity(150%) to a future spec is that, as it is currently spec'd, that is a valid declaration. The parser accepts it. It just doesn't have any effect different from opacity(100%). So changing later becomes a compat risk.

(Maybe it's already a compat risk, I don't know. People could be doing weird things with calc and variables, confident that if the result is at least 100% then the filter won't change anything.)

Adding this functionality in the future would require adding a separate function (alpha(), maybe), that has the full functionality that opacity() should have had.

@css-meeting-bot

This comment has been minimized.

Show comment
Hide comment
@css-meeting-bot

css-meeting-bot Feb 21, 2018

Member

The Working Group just discussed Why can't opacity() filter function ever increase opacity?.

The full IRC log of that discussion <dael> Topic: Why can't opacity() filter function ever increase opacity?
<krit> https://github.com//issues/178
<dael> github: https://github.com//issues/178
<dael> AmeliaBR: We have an opacity shorthald filter function. It takes any int >0 but any >1 is clamped to 1. So opacity filter reduces but cannot increase opacity. So a number of features like taking a blur or drop shadow and inclreasing opacity of blurred areas is not possible.
<dael> AmeliaBR: We're getting late int he process for major changes. All engines currently impl as spec. Problem is because the way it's spec it won't be easy to add this in later. If it was currently written that >1 is invalid we could add it later without worrying about breaking.
<dael> AmeliaBR: As far as an author prespective I found this to be an arbitrary restriction so I wanted to change, but I recognize it's late in the game.
<dael> krit: 2 comments. Spec was following impl already, that was already impl. Point 2 that I think TabAtkins mentioned if you have some areas with a 0 they will not get opaque again. THere might be issues there. Also some browsers might have optimizations.
<dael> krit: Biggest issue is there might be content already that can increase >1 and this code will result in 2 differnt results.
<dael> TabAtkins: I take back my objection. AmeliaBR pointed out that's exactly what you do want.
<dael> AmeliaBR: It's consistant with behavior of other shorthands like brightness.
<dael> smfr: There are other issues. 1 is that some browsers may rely on platform graphics libraries that expect 0-1 value. Second is with premultiplied alpha. Many engines will store in that and you have very small rgb units and when you multiply that you get this grey. I think that'll happen with >1 opacity.
<dael> krit: For some effects we require to go back to unmodified, yes. Depending on how impl is done you get very different results.
<dael> smfr: You've got data laoss with premultiplied alpha
<dael> smfr: I also don't like because it gives us different behavior in opacity. If we want this we should think about a different filter.
<dael> AmeliaBR: Yes, that one lets you modify each channel.
<dael> Chris: Agree. Exposing that is the best way forward.
<dael> AmeliaBR: That is something that could be added in the future without web compat. Add a separate function in the future.
<dael> smfr: That would be fine.
<dael> TabAtkins: sgtm
<dael> AmeliaBR: Sounds like a reasonable way forward. hoping to get filters stable so I'll aceept
<dael> astearns: So we'll close this issue no change and put fe component transfer as future work.
<dael> AmeliaBR: I'll open an issue on filters 2.
Member

css-meeting-bot commented Feb 21, 2018

The Working Group just discussed Why can't opacity() filter function ever increase opacity?.

The full IRC log of that discussion <dael> Topic: Why can't opacity() filter function ever increase opacity?
<krit> https://github.com//issues/178
<dael> github: https://github.com//issues/178
<dael> AmeliaBR: We have an opacity shorthald filter function. It takes any int >0 but any >1 is clamped to 1. So opacity filter reduces but cannot increase opacity. So a number of features like taking a blur or drop shadow and inclreasing opacity of blurred areas is not possible.
<dael> AmeliaBR: We're getting late int he process for major changes. All engines currently impl as spec. Problem is because the way it's spec it won't be easy to add this in later. If it was currently written that >1 is invalid we could add it later without worrying about breaking.
<dael> AmeliaBR: As far as an author prespective I found this to be an arbitrary restriction so I wanted to change, but I recognize it's late in the game.
<dael> krit: 2 comments. Spec was following impl already, that was already impl. Point 2 that I think TabAtkins mentioned if you have some areas with a 0 they will not get opaque again. THere might be issues there. Also some browsers might have optimizations.
<dael> krit: Biggest issue is there might be content already that can increase >1 and this code will result in 2 differnt results.
<dael> TabAtkins: I take back my objection. AmeliaBR pointed out that's exactly what you do want.
<dael> AmeliaBR: It's consistant with behavior of other shorthands like brightness.
<dael> smfr: There are other issues. 1 is that some browsers may rely on platform graphics libraries that expect 0-1 value. Second is with premultiplied alpha. Many engines will store in that and you have very small rgb units and when you multiply that you get this grey. I think that'll happen with >1 opacity.
<dael> krit: For some effects we require to go back to unmodified, yes. Depending on how impl is done you get very different results.
<dael> smfr: You've got data laoss with premultiplied alpha
<dael> smfr: I also don't like because it gives us different behavior in opacity. If we want this we should think about a different filter.
<dael> AmeliaBR: Yes, that one lets you modify each channel.
<dael> Chris: Agree. Exposing that is the best way forward.
<dael> AmeliaBR: That is something that could be added in the future without web compat. Add a separate function in the future.
<dael> smfr: That would be fine.
<dael> TabAtkins: sgtm
<dael> AmeliaBR: Sounds like a reasonable way forward. hoping to get filters stable so I'll aceept
<dael> astearns: So we'll close this issue no change and put fe component transfer as future work.
<dael> AmeliaBR: I'll open an issue on filters 2.
@AmeliaBR

This comment has been minimized.

Show comment
Hide comment
@AmeliaBR

AmeliaBR Feb 21, 2018

As promised, I created a new issue to track a more general filter function for arbitrary color-channel modification in Filter Effects Level 2. I even came up with a full-fledged syntax proposal, by borrowing from the Colors 4 color modification functions.

AmeliaBR commented Feb 21, 2018

As promised, I created a new issue to track a more general filter function for arbitrary color-channel modification in Filter Effects Level 2. I even came up with a full-fledged syntax proposal, by borrowing from the Colors 4 color modification functions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment