Welcome to Doom9's Forum, THE in-place to be for everyone interested in DVD conversion.

Before you start posting please read the forum rules. By posting to this forum you agree to abide by the rules.

 

Go Back   Doom9's Forum > Capturing and Editing Video > Avisynth Usage

 
 
Thread Tools Search this Thread Display Modes
Prev Previous Post   Next Post Next
Old 18th July 2004, 18:23   #1  |  Link
Didée
Registered User
 
Join Date: Apr 2002
Location: Germany
Posts: 5,391
Some finger exercises with image levels

Lately, the discussion about the different gamma curves of TV sets and PC monitors came up again. This reminded me of some gamma tricks I'm used to occasionally apply in image processing. And now I even found time set it up in Avisynth

The most-faced problem is: video appears "too dark" on PC monitors.
The usual solution is: raise black level, or slope-up the gamma curve.

Both make the details in very dark areas better visible - but both create the usual ugly "washed-out" effect at the same time.

A more pleasing solution is, to adjust the gamma curve for dark areas more strongly than for bright areas.

Functions:
(MaskTools.dll is needed. >= v1.5.5 is recommended.)

edit 07 dec 2004: all functions updated to latest MaskTools' semantics (currently v1.5.5)

Code:

function Ylevels(clip clp, int a, float gamma, int b, int c, int d)
       { wicked="x "+string(a)+" - "+string(b)+" "+string(a)+" - / 1 "+string(gamma)+" / ^ "+string(d)+" "+string(c)+" - * "+string(c)+" +"
        # Reminder: Yexpr = "x a - b a - / 1 gamma / ^ d c - * c +"
        # return( clp.subtitle(wicked) )
         return( clp.YV12LUT(Yexpr = wicked, U=2,V=2) )  
         }
         
function YlevelsG(clip clp, int a, float gamma, int b, int c, int d)
       { wicked = gamma > 1.0
          \      ? "x "+string(a)+" - "+string(b)+" "+string(a)+" - / 1 "+string(gamma)+" / ^ "+string(d)+" "+string(c)+" - * "+string(c)+" + x * x 255 x - * + 255 /"
          \      : "x "+string(a)+" - "+string(b)+" "+string(a)+" - / 1 "+string(gamma)+" / ^ "+string(d)+" "+string(c)+" - * "+string(c)+" + 255 x - * x x * + 255 /"
         return( clp.YV12LUT(Yexpr = wicked, U=2,V=2) )  
         }
         
function YlevelsS(clip clp, int a, float gamma, int b, int c, int d)
       { wicked="x "+string(a)+" - "+string(b)+" "+string(a)+" - / 1 "+string(gamma)+" / ^ "+string(d)+" "+string(c)+" - * "+string(c)+" + x 162,97466 / sin 255 * * x 255 x 162,97466 / sin 255 * - * + 255 /"
         return( clp.YV12LUT(Yexpr = wicked, U=2,V=2) )  
         }
All functions are called the same way as AviSynth's "levels()" command, except for the coring parameter. Coring is not available with the Ylevels() functions. They'll always work on the full [0,255] value range.

Ylevels() is a simple replacement for Avisynth's internal levels() command, with a few neat differences:

- processes only luma --> faster, better preservation of color saturation
- no clipping: Ylevels(40,1.0,220, 40, 220) will not clip the output to [40,220] as levels() does. Values below 40 / above 220 will be scaled accordingly to the correct vales. This means, one can use any values for IN_LOW, IN_HIGH as "control points" without getting the input clipped at those values.


But that's not the deal.


YlevelsG() and YlevelsS() apply the given levels conversion by 100% @ Luma==0, by 0% @ Luma=255, and accordingly in-between.

YlevelsG() does a linear sweep (G = Gradient)
YlevelsS() does a sine sweep (S = yes, exactly )

Try those with gamma values 1.5 ~ 4.0. I suppose some will like them.

YlevelsG (not YlevelsS) does "inverse" scaling for gamma values < 1.0, but that's not that great. It's just for completeness.


But that's not all, yet.


While building the LUT expression for the sine sweep , at one point I accidentially swapped some things, and the result was ...

YlevelsC()

For this one, 2.0 < gamma < 16.0 is reasonable.

No, I won't explain it - just try & enjoy it
Code:

function YlevelsC(clip clp, int a, float gamma, int b, int c, int d)
       { wicked="x "+string(a)+" - "+string(b)+" "+string(a)+" - / 1 "+string(gamma)+" / ^ "+string(d)+" "+string(c)+" - * "+string(c)+" + 255 x 162,97466 / cos 255 * - * x x 162,97466 / cos 255 * * + 255 /"
         return( clp.YV12LUT(Yexpr = wicked, U=2,V=2) )  
         }
Closing comment:

If these functions should be used for encoding or not, depends on the source. I would be carefully, at least ...

But:

These functions are pretty fast! (Manao: thankyouthankyouthank...)
- So they can be nicely used in the "Avisynth" section of ffdshow ...


Have fun


- Didée
__________________
- We´re at the beginning of the end of mankind´s childhood -

My little flickr gallery. (Yes indeed, I do have hobbies other than digital video!)

Last edited by Didée; 7th December 2004 at 11:53.
Didée is offline   Reply With Quote
 

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +1. The time now is 10:14.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.