Levels

From Avisynth wiki
(Difference between revisions)
Jump to: navigation, search
(formatting, links, phrasing)
Line 1: Line 1:
{{Template:FuncDef|Levels(clip ''input'', int ''input_low'', float ''gamma'', int ''input_high'', int ''output_low'', int ''output_high'' [, bool ''coring''] [, bool ''dither''])}}
+
Adjusts brightness, contrast, and gamma. This is done using the following ''transfer function'':
 +
:''output'' = ( (''input'' - {{FuncArg|input_low}}) / ({{FuncArg|input_high}} - {{FuncArg|input_low}}) )<sup>(1 / {{FuncArg|gamma}})</sup> * ({{FuncArg|output_high}} - {{FuncArg|output_low}}) + {{FuncArg|output_low}}
  
The '''Levels''' filter adjusts brightness, contrast, and gamma. This is done using the following '''transfer function''':
+
*{{FuncArg|input_low}} and {{FuncArg|input_high}} determine what ''input'' pixel values are treated as pure black and pure white.  
 +
*{{FuncArg|output_low}} and {{FuncArg|output_high}} determine what ''output'' values are treated as pure black and pure white.
 +
*{{FuncArg|gamma}} controls the degree of non-linearity in the conversion.
  
:<tt>output = ((input-input_low)/(input_high-input_low))^(1/gamma)*(output_high-output_low) + output_low</tt>
 
  
The ''input_low'' and ''input_high'' parameters determine what input pixel values are treated as pure black and pure white. The ''output_low'' and ''output_high'' parameters determine what output values are treated as pure black and pure white. The gamma parameter controls the degree of non-linearity in the conversion.  
+
This is one of those filters for which it would really be nice to have a GUI. Since we can't offer a GUI (though [http://forum.doom9.org/showthread.php?t=153248 AvsP] does), we at least make this filter '''compatible''' with [[VirtualDub|VirtualDub's]] when the clip is [[RGB]]. In that case you should be able to take the numbers from VirtualDub's ''Levels'' dialog and pass them as parameters to the '''Levels''' filter and get the same results. Unlike VirtualDub's filter however, the input and output parameters can be larger than 255.  
  
This is one of those filters for which it would really be nice to have a GUI. Since we can't offer a GUI (though [http://forum.doom9.org/showthread.php?t=153248 AvsP] does), we at least make this filter '''compatible with [[VirtualDub|VirtualDub's]]''' when the clip is RGB. In that case you should be able to take the numbers from VirtualDub's Levels dialog and pass them as parameters to the Levels filter and get the same results. Unlike VirtualDub's Levels filter however, the input and output parameters can be larger than 255.  
+
When processing data in [[YUV]] mode, '''Levels''' only gamma-corrects the luma information, not the chroma. Gamma correction is really an RGB concept, and is only approximated here in YUV. If ''{{FuncArg|gamma}}=1.0'' (unity), the filter should have the same effect in both RGB and YUV modes. For adjusting brightness or contrast in YUV mode, it ''may'' be better (depending on the effect you are looking for) to use [[Tweak]] or [[ColorYUV]], because '''Levels''' changes the chroma of the clip.
  
When processing data in YUV mode, Levels only gamma-corrects the luma information, not the chroma. Gamma correction is really an RGB concept, and is only approximated here in YUV. If ''gamma = 1.0'', the filter should have the same effect in RGB and YUV modes. For adjusting brightness or contrast it may be better (depending on the effect you are looking for) to use [[Tweak]] or [[ColorYUV]], because Levels changes the chroma of the clip.
 
  
;input_low
+
==== Syntax and Parameters ====
:higher ''input_low'' darkens the output; smaller input values are ''clipped'', that is, rounded up to ''input_low''.
+
{{FuncDef|Levels(clip ''input'', <br>
 +
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int ''input_low'', float ''gamma'', int ''input_high'', <br>
 +
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int ''output_low'', int ''output_high''<br>
 +
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [, bool ''coring'' , bool ''dither'' ] )}}
  
;gamma
+
:{{Par2|clip|clip|(required)}}
:''gamma'' can be used to undo and redo gamma (see examples).
+
::Source video.
  
;input_high
+
:{{Par2|input_low|int|(required)}}
:lower ''input_high'' brightens the output; higher input values are ''clipped'', that is, rounded down to ''input_high''.
+
::Higher {{FuncArg|input_low}} darkens the output; input values below {{FuncArg|input_low}} are ''clipped'', that is, rounded up to {{FuncArg|input_low}}.
 +
::If '''0''', there is no change to the output.  
  
;output_low
+
:{{Par2|gamma|float|(required)}}
:dark values brighten to gray as ''output_low'' becomes larger.
+
::[[Wikipedia:Gamma_correction|Gamma]] adjustment. See [[#Examples|examples]].
 +
::If '''1.0''', there is no change to the output.
  
;output_high
+
:{{Par2|input_high|int|(required)}}
:light values darken to gray as ''output_high'' becomes smaller.
+
::Lower {{FuncArg|input_high}} values brighten the output; input values higher than {{FuncArg|input_high}} are ''clipped'', that is, rounded down to {{FuncArg|input_high}}.
 +
::If '''255''', there is no change to the output.
  
;coring
+
:{{Par2|output_low|int|(required)}}
:when ''true'' (the default), input luma is ''clamped'' to [16,235] and the chroma to [16,240]; this clamped input is scaled from [16,235] to [0,255], the conversion takes place according to the transfer function above, and then output is scaled back from [0,255] to [16,235]. When ''false'', the conversion takes place according to the transfer function, without any scaling.
+
::Dark values brighten to gray as {{FuncArg|output_low}} becomes larger.
<blockquote>''Coring'' was created for VirtualDub compatibility, and it it remains true by default for compatibility with scripts written for AviSynth prior to version 2.53. In the opinion of some, you should [http://forum.doom9.org/showthread.php?p=1722885#post1722885 always use ''coring=false''.] if you are working directly with luma values (whether or not your input is [16,235]).</blockquote>
+
::If '''0''', there is no change to the output.  
  
;dither
+
:{{Par2|output_high|int|(required)}}
:when ''true'', [[ordered dithering]] is applied to combat [http://en.wikipedia.org/wiki/Colour_banding banding]. Default is ''false''.
+
::Light values darken to gray as {{FuncArg|output_high}} becomes smaller.
 +
::If '''255''', there is no change to the output.
  
===== Examples:=====
+
:{{Par2|coring|bool|false}}
 +
::When ''true'' (the default), input luma is ''clamped'' to [16,235] and the chroma to [16,240]; this clamped input is scaled from [16,235] to [0,255], the conversion takes place according to the transfer function above, and then output is scaled back from [0,255] to [16,235]. When ''false'', the conversion takes place according to the transfer function, without any scaling.
 +
::{{FuncArg|coring}} was created for VirtualDub compatibility, and it remains true by default for compatibility with older scripts. In the opinion of some, you should [http://forum.doom9.org/showthread.php?p=1722885#post1722885 always use ''coring=false''] if you are working directly with luma values (whether or not your input is [16,235]).
  
  # does nothing on a [16,235] clip, but it clamps (or rounds) a [0,255] clip to [16,235]:
+
:{{Par2|dither|bool|false}}
 +
::when ''true'', [[ordered dithering]] is applied to combat [http://en.wikipedia.org/wiki/Colour_banding banding]. Default is ''false''.
 +
 
 +
 
 +
==== Examples ====
 +
<div {{BoxWidthIndent|64|2}} >
 +
  # does nothing (unity transfer function):
 
  Levels(0, 1, 255, 0, 255)
 
  Levels(0, 1, 255, 0, 255)
 +
</div>
  
  # the input is scaled from [16,235] to [0,255], the conversion [0,255]->[16,235] takes place (accordingly to the formula),
+
<div {{BoxWidthIndent|64|2}} >
# and the output is scaled back from [0,255] to [16,235]: (for example: the luma values in [0,16] are all converted to 30)
+
  # the input is scaled from [16,235] to [0,255], the conversion [0,255]->[16,235] takes place  
 +
# (accordingly to the formula), and the output is scaled back from [0,255] to [16,235]
 +
# (for example: the luma values in [0,16] are all converted to 30)
 
  Levels(0, 1, 255, 16, 235)
 
  Levels(0, 1, 255, 16, 235)
 +
</div>
  
 +
<div {{BoxWidthIndent|64|2}} >
 
  # gamma-correct image for display in a brighter environment:
 
  # gamma-correct image for display in a brighter environment:
 
  # example: luma of 16 stays 16, 59 is converted to 79, etc.
 
  # example: luma of 16 stays 16, 59 is converted to 79, etc.
 
  Levels(0, 1.3, 255, 0, 255)
 
  Levels(0, 1.3, 255, 0, 255)
 +
</div>
  
 +
<div {{BoxWidthIndent|64|2}} >
 
  # invert the image (make a photo-negative):
 
  # invert the image (make a photo-negative):
 
  # example: luma of 16 is converted to 235
 
  # example: luma of 16 is converted to 235
 
  Levels(0, 1, 255, 255, 0)
 
  Levels(0, 1, 255, 255, 0)
 +
</div>
  
 +
<div {{BoxWidthIndent|64|2}} >
 
  # does nothing on a [0,255] clip; does nothing on a [16,235]:
 
  # does nothing on a [0,255] clip; does nothing on a [16,235]:
 
  Levels(0, 1, 255, 0, 255, coring=false)
 
  Levels(0, 1, 255, 0, 255, coring=false)
 +
</div>
  
 +
<div {{BoxWidthIndent|64|2}} >
 
  # scales a [0,255] clip to [16,235]
 
  # scales a [0,255] clip to [16,235]
  Levels(0, 1, 255, 16, 235, coring=false)  # note both luma and chroma components are scaled by the same amount,
+
  Levels(0, 1, 255, 16, 235, coring=false)
                                          # so it's not exactly the same as ColorYUV(levels="PC->TV")
+
  # note both luma and chroma components are scaled by the same amount,
 +
# so it's not exactly the same as [[ColorYUV]](levels="PC->TV")
 +
</div>
  
 +
<div {{BoxWidthIndent|64|2}} >
 
  # scales a [16,235] clip to [0,255]:
 
  # scales a [16,235] clip to [0,255]:
  Levels(16, 1, 235, 0, 255, coring=false)  # note both luma and chroma components are scaled by the same amount,
+
  Levels(16, 1, 235, 0, 255, coring=false)
                                          # so it's not exactly the same as ColorYUV(levels="TV->PC")
+
  # note both luma and chroma components are scaled by the same amount,
 +
# so it's not exactly the same as [[ColorYUV]](levels="TV->PC")
 +
</div>
  
 +
<div {{BoxWidthIndent|64|2}} >
 
  # makes a clip 100% black
 
  # makes a clip 100% black
 
  Levels(0, 1.0, 255, 0, 0)
 
  Levels(0, 1.0, 255, 0, 0)
 +
</div>
  
 +
<div {{BoxWidthIndent|64|2}} >
 
  # apply fading on gamma corrected source (same holds for resizing and smoothing else well)
 
  # apply fading on gamma corrected source (same holds for resizing and smoothing else well)
 
  clip = ...  
 
  clip = ...  
 
  gamma = 2.2
 
  gamma = 2.2
 
  clip.Levels(0, gamma, 255, 0, 255) # undo gamma (also called gamma correction)
 
  clip.Levels(0, gamma, 255, 0, 255) # undo gamma (also called gamma correction)
  FadeOut(n)
+
  [[FadeOut]](n)
 
  Levels(0, 1.0/gamma, 255, 0, 255) # redo gamma
 
  Levels(0, 1.0/gamma, 255, 0, 255) # redo gamma
 +
</div>
 +
  
'''Changes'''
+
==== Changes ====
 
{|border=1 cellspacing=1 cellpadding=4
 
{|border=1 cellspacing=1 cellpadding=4
| v2.53
+
|-
| added coring (true by default, which reflects the behaviour in older versions)
+
| v2.60
|-
+
| added ''dither''
| v2.60
+
|-
| added dither
+
| v2.53
|}
+
| added ''coring'' (true by default, which reflects the behaviour in older versions)
 +
|}
  
 
[[Category:Internal filters]]
 
[[Category:Internal filters]]
 
[[Category:Levels and Chroma filters]]
 
[[Category:Levels and Chroma filters]]

Revision as of 03:57, 19 January 2016

Adjusts brightness, contrast, and gamma. This is done using the following transfer function:

output = ( (input - input_low) / (input_high - input_low) )(1 / gamma) * (output_high - output_low) + output_low
  • input_low and input_high determine what input pixel values are treated as pure black and pure white.
  • output_low and output_high determine what output values are treated as pure black and pure white.
  • gamma controls the degree of non-linearity in the conversion.


This is one of those filters for which it would really be nice to have a GUI. Since we can't offer a GUI (though AvsP does), we at least make this filter compatible with VirtualDub's when the clip is RGB. In that case you should be able to take the numbers from VirtualDub's Levels dialog and pass them as parameters to the Levels filter and get the same results. Unlike VirtualDub's filter however, the input and output parameters can be larger than 255.

When processing data in YUV mode, Levels only gamma-corrects the luma information, not the chroma. Gamma correction is really an RGB concept, and is only approximated here in YUV. If gamma=1.0 (unity), the filter should have the same effect in both RGB and YUV modes. For adjusting brightness or contrast in YUV mode, it may be better (depending on the effect you are looking for) to use Tweak or ColorYUV, because Levels changes the chroma of the clip.


Syntax and Parameters

Levels(clip input,
      int input_low, float gamma, int input_high,
      int output_low, int output_high
      [, bool coring , bool dither ] )

clip  clip = (required)
Source video.
int  input_low = (required)
Higher input_low darkens the output; input values below input_low are clipped, that is, rounded up to input_low.
If 0, there is no change to the output.
float  gamma = (required)
Gamma adjustment. See examples.
If 1.0, there is no change to the output.
int  input_high = (required)
Lower input_high values brighten the output; input values higher than input_high are clipped, that is, rounded down to input_high.
If 255, there is no change to the output.
int  output_low = (required)
Dark values brighten to gray as output_low becomes larger.
If 0, there is no change to the output.
int  output_high = (required)
Light values darken to gray as output_high becomes smaller.
If 255, there is no change to the output.
bool  coring = false
When true (the default), input luma is clamped to [16,235] and the chroma to [16,240]; this clamped input is scaled from [16,235] to [0,255], the conversion takes place according to the transfer function above, and then output is scaled back from [0,255] to [16,235]. When false, the conversion takes place according to the transfer function, without any scaling.
coring was created for VirtualDub compatibility, and it remains true by default for compatibility with older scripts. In the opinion of some, you should always use coring=false if you are working directly with luma values (whether or not your input is [16,235]).
bool  dither = false
when true, ordered dithering is applied to combat banding. Default is false.


Examples

# does nothing (unity transfer function):
Levels(0, 1, 255, 0, 255)
# the input is scaled from [16,235] to [0,255], the conversion [0,255]->[16,235] takes place 
# (accordingly to the formula), and the output is scaled back from [0,255] to [16,235]
# (for example: the luma values in [0,16] are all converted to 30)
Levels(0, 1, 255, 16, 235)
# gamma-correct image for display in a brighter environment:
# example: luma of 16 stays 16, 59 is converted to 79, etc.
Levels(0, 1.3, 255, 0, 255)
# invert the image (make a photo-negative):
# example: luma of 16 is converted to 235
Levels(0, 1, 255, 255, 0)
# does nothing on a [0,255] clip; does nothing on a [16,235]:
Levels(0, 1, 255, 0, 255, coring=false)
# scales a [0,255] clip to [16,235]
Levels(0, 1, 255, 16, 235, coring=false)  
# note both luma and chroma components are scaled by the same amount,
# so it's not exactly the same as ColorYUV(levels="PC->TV")
# scales a [16,235] clip to [0,255]:
Levels(16, 1, 235, 0, 255, coring=false)  
# note both luma and chroma components are scaled by the same amount,
# so it's not exactly the same as ColorYUV(levels="TV->PC")
# makes a clip 100% black
Levels(0, 1.0, 255, 0, 0)
# apply fading on gamma corrected source (same holds for resizing and smoothing else well)
clip = ... 
gamma = 2.2
clip.Levels(0, gamma, 255, 0, 255) # undo gamma (also called gamma correction)
FadeOut(n)
Levels(0, 1.0/gamma, 255, 0, 255) # redo gamma


Changes

v2.60 added dither
v2.53 added coring (true by default, which reflects the behaviour in older versions)
Personal tools