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.

 Doom9's Forum Some finger exercises with image levels
 Register FAQ Calendar Search Today's Posts Mark Forums Read

 18th July 2004, 18:23 #1  |  Link Didée Registered User   Join Date: Apr 2002 Location: Germany Posts: 5,390 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.
 18th July 2004, 20:16 #2  |  Link malkion Registered User   Join Date: Feb 2004 Posts: 156 Thanks Didee! (now about that msu-sharpening script u developed, heh, just send it)
 18th July 2004, 20:25 #3  |  Link Didée Registered User   Join Date: Apr 2002 Location: Germany Posts: 5,390 I'll post it when it's ready to be posted - 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!)
 18th July 2004, 20:51 #4  |  Link malkion Registered User   Join Date: Feb 2004 Posts: 156 Hey Didee, I like YlevelsG very much, except my CRT is kinda old, and the gamma is skewed. I set fddshow's luma offset from 50 to 60 just to watch vids. I even tried YlevelsG and Ylevels together, and I still get real time decoding. Not bad at all. But the full effect of YlevelsG is missed that way. Anyways, I can still use fddshow luma offset and YlevelsG together for a more brilliant picture. I'm about to try Ylevels first then YlevelsG to see if this option works... There's so many options... hehe
 23rd July 2004, 20:40 #6  |  Link jorel Guest   Posts: n/a @ Didée and all : no luck here, the image still dark and changing the matizes(more green) comparing with the dvd(cartoon) source. anyone had good results? Didée, suggestions or differents adjusts in the scrip? thanks!....i lost my will to encode, we're loosing quality! ...waiting good solutions or hints.
 24th July 2004, 14:05 #7  |  Link Didée Registered User   Join Date: Apr 2002 Location: Germany Posts: 5,390 Speaking of above functions, perhaps you'd need it to "bite" more in the darks only. Technically no problem, the distribution can be made at free will. However, the following is YlevelS() with still careful settings: To my eyes, that's effective. - 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!)
 24th July 2004, 17:57 #8  |  Link morsa the dumbest   Join Date: Oct 2002 Location: Malvinas Posts: 494 Amazing!!!!!!!!!!!!!!!!!!!!!!!!!!! Wouldn't be better to turn this directly into a plug-in??
 24th July 2004, 18:03 #9  |  Link Manao Registered User   Join Date: Jan 2002 Location: France Posts: 2,856 No, it wouldn't be faster, and it would lose all the tweakability of YV12LUT. Didee's functions are wrappers to make the use of YV12LUT easier in these kind of levels filtering, and for that, avs scripts are perfectly fit.
 24th July 2004, 18:06 #10  |  Link LigH German doom9/Gleitz SuMo     Join Date: Oct 2001 Location: Germany, rural Altmark Posts: 4,891 By now, I was quite satisfied with the results of Code: ```Levels(0,1.4,255,8,248) Tweak(sat=1.2,cont=1.1)``` I'll be interrestend in comparing the results!
 24th July 2004, 19:01 #11  |  Link jorel Guest   Posts: n/a thank you boys....i did more tests. differents results and reasons: from vob in vdubmod: http://img20.exs.cx/img20/6633/a105.jpg using .avs script (source only)from dvd2avi project: http://img20.exs.cx/img20/802/b98.jpg little differences cos here was with xvid decompressor in vdub mod! now here,big differences: from vobs in vdubmod: http://img34.imageshack.us/img34/5236/vobs.jpg using .avs script (source only)from dvd2avi project: http://img39.imageshack.us/img39/7083/pcscale.jpg great differences cos was using ati decompressor in vdubmod(file information). then,(correct me please) the differences in vdub depend of the decompressor used to show the pictures (like in vdub file informations). now my doubt: if i'm using the ati the image is dark,if using xvid "seems" equal ..... what is working when encoding in CCE(D2S)?
24th July 2004, 19:52   #12  |  Link
Didée
Registered User

Join Date: Apr 2002
Location: Germany
Posts: 5,390
Quote:
 Originally posted by LigH By now, I was quite satisfied with the results of Code: ```Levels(0,1.4,255,8,248) Tweak(sat=1.2,cont=1.1)``` I'll be interrestend in comparing the results!
Okay.

What I see here, is:

One picture where detail in dark areas is clearly visible, but that suffers from contrast over the full range, making the overall appearance somewhat dull,
and one picture where detail in dark areas is clearly visible, and that has good contrast over the full range, making the overall appearance vivid.

q.e.d.

- Didee

*damnit*

Sorry for the misspelling, LigH.
__________________
- 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; 24th July 2004 at 19:56.

 25th July 2004, 12:16 #13  |  Link LigH German doom9/Gleitz SuMo     Join Date: Oct 2001 Location: Germany, rural Altmark Posts: 4,891 Well - a little tweaking of the Levels(gamma) and Tweak(sat,cont) parameters may lead to even better results than my default ones. But finally: If your Ylevels or the Levels/Tweak combo are more or less successful, is beyond my ability of recognition. Other people may be more trained in spotting differences.
 25th July 2004, 18:57 #14  |  Link Didée Registered User   Join Date: Apr 2002 Location: Germany Posts: 5,390 It gets clearer with some curves. The following curves are not mathematically exact - they're quickly free-handed, but give the idea. A plain gamma correction looks like this: We get a strong brightening effect over the full range. But from about 35% of the available range, we start loosing contrast (steepyness of curve gets < 1). Ylevels simply blends the normal gamma curve, weightened with the inverse of the input's brightness. The result is similar to this: By this weightening, the brightening of the dark areas is still achieved. But here, the cost of the additional levels that were assigned to the darks is distributed more equally over the remaining ranges: the curve's steepyness goes only a little below '1', plus the curve's overall deviation from y=x is much smaller. You can tweak your levels().tweak() - combo until you get blue in the face: you'll never get the same effect. Starting with normal levels(), contrast in the upper 65% is lost. Then, you can get it back - if at all, only with loss. Expanding the compressed ranges again will lead to posterization, because actually values got lost during gamma correction - not at all with tweak() - (not really), since its contrast parameter works symetrically to Y=127. Hey, I don't want to sell anything here But the difference is really easy to spot, in my opinion: interleave( levels(...).tweak(...), Ylevels(...) ) Flip this back 'n forth, and don't say you see no difference - 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; 25th July 2004 at 19:10.
 25th July 2004, 19:24 #15  |  Link scharfis_brain brainless     Join Date: Mar 2003 Location: Germany Posts: 3,605 hehe, I was using Photoshops curves to build a curve, that improved the image, and then used RGBLut (the curves mostly seem to be similar to your one) __________________ Don't forget the 'c'! Don't PM me for technical support, please.
 25th July 2004, 19:52 #16  |  Link Didée Registered User   Join Date: Apr 2002 Location: Germany Posts: 5,390 RGBLUT ony a YUV souce ... didn't you get some banding effects in areas of low luma? You're getting gaps through the YUV->RGB conversion (look at the histogram in Photoshop before-after), are spreading these gaps through gamma adjustment, and are left with the gaps after backconversion (again look at the histogram). I don't pretend this springs to the eye obviously, but generally it's just like that. - 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!)
 25th July 2004, 19:56 #17  |  Link scharfis_brain brainless     Join Date: Mar 2003 Location: Germany Posts: 3,605 hehe, but since TMPEGenc only accepts RGB input, that isn't a big problem, isn't it? __________________ Don't forget the 'c'! Don't PM me for technical support, please.
 7th December 2004, 12:13 #18  |  Link Didée Registered User   Join Date: Apr 2002 Location: Germany Posts: 5,390 All Ylevels()-functions updated to the latest MaskTools' semantics (needs to specify "U=2,V=2" to carry the original color planes through). __________________ - 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!)
 6th November 2006, 05:55 #19  |  Link Jeremy Duncan Didée Fan     Join Date: Feb 2006 Location: Canada Posts: 1,079 Didée, I notified the FFdshow developers that the FFdshow Levels tab uses your code wrong. That it doesn't work as you've shown in this thread. Here's the link: Link I asked them to look at this thread and implement the Levels you made in this thread into FFdshow properly.
 6th November 2006, 13:53 #20  |  Link Alain2 Registered User   Join Date: May 2005 Posts: 236 Talking about ylevels, Didee I sent you a pm on this subject back in June, but you never replied..