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 > VapourSynth

Reply
 
Thread Tools Search this Thread Display Modes
Old 10th December 2016, 15:13   #1  |  Link
xekon
Registered User
 
Join Date: Jul 2011
Posts: 213
GradCurve VapourSynth plugin port of virtualdub Gradation Curves plugin

GradCurve filter can be used to edit the gradation curves similar to the curves function of painting programs. It is a powerful tool that allows you to do some basic correction like brightness, contrast and gamma as well as a wide range of advanced color correcting and manipulations.

GradCurve is a VapourSynth c++ plugin converted from the VirtualDub c++ plugin Gradation Curves(http://forum.doom9.org/showthread.php?t=133191)

There is a working test version of GradCurve on github: https://github.com/xekon/GradCurve

windows dll: https://github.com/xekon/GradCurve/b.../GradCurve.dll

project files that can be used for testing: http://www.mediafire.com/file/9nc2et...j/gradcurve.7z

Disclaimer: I have only tested amp/acv files with pmode=1 (RGB + R/G/B), so if you come across a bug please let me know.

Thanks so very much to everyone that has helped me throughout this thread, I really apprciate it.

Also, I welcome any improvements/changes, so please share

Last edited by xekon; 3rd February 2017 at 05:50. Reason: update title, and opening post now that there is a working test version
xekon is offline   Reply With Quote
Old 10th December 2016, 15:42   #2  |  Link
Mystery Keeper
Beyond Kawaii
 
Mystery Keeper's Avatar
 
Join Date: Feb 2008
Location: Russia
Posts: 661
Why did you convert C++ code to Python? You could just make a C++ VapourSynth plugin.
__________________
...desu!
Mystery Keeper is online now   Reply With Quote
Old 10th December 2016, 15:46   #3  |  Link
xekon
Registered User
 
Join Date: Jul 2011
Posts: 213
oh I did not realize that. is there any advantage to one or the other? As far as vapoursynth is concerned.

Last edited by xekon; 10th December 2016 at 15:48.
xekon is offline   Reply With Quote
Old 10th December 2016, 22:39   #4  |  Link
jackoneill
unsigned int
 
jackoneill's Avatar
 
Join Date: Oct 2012
Location: 🇪🇺
Posts: 620
If you do this in Python, it will be too slow to be usable.
jackoneill is offline   Reply With Quote
Old 10th December 2016, 23:43   #5  |  Link
captaiŋadamo
Registered User
 
Join Date: Jul 2016
Posts: 33
Just check out basically anything in here.
captaiŋadamo is offline   Reply With Quote
Old 11th December 2016, 14:10   #6  |  Link
xekon
Registered User
 
Join Date: Jul 2011
Posts: 213
im slowly getting a feel for how things are connected. i found an example in the vapoursynth source invert_example
and im following through the c++ code of gradation and found what I believe is the main processing loop when processing in the mode I am currently using which is mode 1 (RGB + R/G/B)

Code:
for (h = 0; h < height; h++)
{
	for (w = 0; w < width; w++)
	{
		old_pixel = *src++;
		med_pixel = mfd->rvalue[1][(old_pixel & 0xFF0000)>>16] + mfd->gvalue[1][(old_pixel & 0x00FF00)>>8] + mfd->ovalue[3][(old_pixel & 0x0000FF)];
		new_pixel = mfd->rvalue[0][(med_pixel & 0xFF0000)>>16] + mfd->gvalue[0][(med_pixel & 0x00FF00)>>8] + mfd->ovalue[0][(med_pixel & 0x0000FF)];
		*dst++ = new_pixel;
	}
	src = (Pixel32 *)((char *)src + fa->src.modulo);
	dst = (Pixel32 *)((char *)dst + fa->dst.modulo);
}
I believe once I have this block using the appropriate vapoursynth API functions that I should be able to get it working, the naming of these variables suggests that it processes the frames by looping through all pixels of each frame, does that mean I would need to use get_read_array() ? the vapoursynth documentation says that returns the frames data. any help with this code block is appreciated.

I have some basic coding experience in java, c++, c#, and now python. But nothing I have ever coded involved image or video manipulation. Mostly web apps that work with databases. I feel like the learning curve is a little steep, but im slowly getting a grasp on this.

Last edited by xekon; 11th December 2016 at 14:30.
xekon is offline   Reply With Quote
Old 11th December 2016, 14:18   #7  |  Link
feisty2
I'm Siri
 
feisty2's Avatar
 
Join Date: Oct 2012
Location: Los Angeles, California
Posts: 2,060
Tell me how is *src++ any better than src[w]?
Sometimes I just fail to understand why would anyone write such unreadable stuff along with whole bunch of pointless, again, unreadable bit wise operations..
C++ is not assembly
__________________
If I got new ideas, will post here: https://github.com/IFeelBloated
feisty2 is offline   Reply With Quote
Old 11th December 2016, 15:16   #8  |  Link
jackoneill
unsigned int
 
jackoneill's Avatar
 
Join Date: Oct 2012
Location: 🇪🇺
Posts: 620
Quote:
Originally Posted by xekon View Post
I believe once I have this block using the appropriate vapoursynth API functions that I should be able to get it working, the naming of these variables suggests that it processes the frames by looping through all pixels of each frame, does that mean I would need to use get_read_array() ? the vapoursynth documentation says that returns the frames data. any help with this code block is appreciated.

I have some basic coding experience in java, c++, c#, and now python. But nothing I have ever coded involved image or video manipulation. Mostly web apps that work with databases. I feel like the learning curve is a little steep, but im slowly getting a grasp on this.
get_read_array is a Python function. Aren't you doing this in C(++)? But yeah, if you want to do it in Python you'll want to use get_read_array and get_write_array to access the pixels.

If you're going to use C++, this is the page you need: http://www.vapoursynth.com/doc/api/vapoursynth.h.html
Read about the functions you see in the invert example.

Virtualdub uses packed RGB32, which means that the red, green, blue, and alpha pixels are interleaved in a single array (R0 G0 B0 A0 R1 G1 B1 A1 R2 ...). This is why you have all those shifts and bitwise AND operations. In VapourSynth the red, green, and blue pixels are in individual arrays (R0 R1 R2..., G0 G1 G2 ..., B0 B1 B2 ...), so the equivalent VapourSynth code will be a bit simpler.
jackoneill is offline   Reply With Quote
Old 12th December 2016, 01:17   #9  |  Link
xekon
Registered User
 
Join Date: Jul 2011
Posts: 213
Thank you very much for the replies guys, I was looking at the wrong API page, thanks again Jackoneill.
xekon is offline   Reply With Quote
Old 12th December 2016, 02:57   #10  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 5,157
Quote:
Originally Posted by feisty2 View Post
Tell me how is *src++ any better than src[w]?
Sometimes I just fail to understand why would anyone write such unreadable stuff along with whole bunch of pointless, again, unreadable bit wise operations..
C++ is not assembly
I suggest that if you dont understand it, you dont use that style,
and old_pixel=*src++ is more like old_pixel=src[0]; src=src+1;
C is part of CPP, if you dont understand C, then you dont understand CPP.

C is a beautifully succinct language, dont knock it.
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but are any of them infinitely bigger ???
StainlessS is offline   Reply With Quote
Old 12th December 2016, 04:35   #11  |  Link
feisty2
I'm Siri
 
feisty2's Avatar
 
Join Date: Oct 2012
Location: Los Angeles, California
Posts: 2,060
Quote:
Originally Posted by StainlessS View Post
I suggest that if you dont understand it, you dont use that style,
and old_pixel=*src++ is more like old_pixel=src[0]; src=src+1;
C is part of CPP, if you dont understand C, then you dont understand CPP.

C is a beautifully succinct language, dont knock it.
Code:
old_pixel = src[w] // also legitimate C code, and much more readable, and faster than *src++ cuz u got one less "add src, sizeof(pixel type)" operation
Right, we should definitely talk more about succinctness.
__________________
If I got new ideas, will post here: https://github.com/IFeelBloated
feisty2 is offline   Reply With Quote
Old 12th December 2016, 18:41   #12  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 5,157
For some processors x=*p++; is [EDIT: compiles to] a single m/c instruction, (perhaps Intel/AMD not amongst them).

Of course it also depends upon the whole context of the code where the code fragment lives as to whether it would be
better used or avoided.

EDIT: eg perfectly acceptable here:- [especially where short strings.]
Code:
    while(*d++=*s++);   // strcpy()

    OR

    for(;*d++=*s++;);   // strcpy()
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but are any of them infinitely bigger ???

Last edited by StainlessS; 13th December 2016 at 23:30.
StainlessS is offline   Reply With Quote
Old 12th December 2016, 19:15   #13  |  Link
captaiŋadamo
Registered User
 
Join Date: Jul 2016
Posts: 33
Quote:
Originally Posted by feisty2 View Post
Tell me how is *src++ any better than src[w]?
Sometimes I just fail to understand why would anyone write such unreadable stuff along with whole bunch of pointless, again, unreadable bit wise operations..
C++ is not assembly
To be pedantic, that's not a bitwise operation, it's pointer arithmetic. &, ~, ^, |, << and >> are bitwise operations.

Also, the code is extremely simplistic so what is so hard about reading it?
captaiŋadamo is offline   Reply With Quote
Old 12th December 2016, 19:43   #14  |  Link
shekh
Registered User
 
Join Date: Mar 2015
Posts: 405
Quote:
x=*p++
This is simple example of (bad) practice to squeeze multiple independent statements into single one. A matter of taste (I hate it).
And while we are here what is better: tabs or spaces?
shekh is offline   Reply With Quote
Old 12th December 2016, 19:47   #15  |  Link
feisty2
I'm Siri
 
feisty2's Avatar
 
Join Date: Oct 2012
Location: Los Angeles, California
Posts: 2,060
Quote:
Originally Posted by captaiŋadamo View Post
To be pedantic, that's not a bitwise operation, it's pointer arithmetic. &, ~, ^, |, << and >> are bitwise operations.

Also, the code is extremely simplistic so what is so hard about reading it?
Using the pointer as an array is much saner and easier for programmers to read than doing it with the raw pointer arithmetic style.

"Along with bunch of bit wise operations", I was referring to crap like "&0xff0000, >>16",,,
__________________
If I got new ideas, will post here: https://github.com/IFeelBloated
feisty2 is offline   Reply With Quote
Old 12th December 2016, 19:47   #16  |  Link
captaiŋadamo
Registered User
 
Join Date: Jul 2016
Posts: 33
How is it bad practice? It's a bog-standard idiom that's been used for decades.

The funny thing is that people who complain about these idioms and then try to be smarter by rewriting them tend to introduce bugs in code that never existed before. "All code is crap except what I write."

Quote:
Originally Posted by feisty2 View Post
Using the pointer as an array is much saner and easier for programmers to read than doing it with the raw pointer arithmetic style.

"Along with bunch of bit wise operations", I was referring to crap like "&0xff0000, >>16",,,
A programmer who can't read the code is likely incompetent. I don't know a single programmer that I've ever worked with that would be tripped up by that line of code.

Last edited by captaiŋadamo; 12th December 2016 at 19:49.
captaiŋadamo is offline   Reply With Quote
Old 12th December 2016, 19:56   #17  |  Link
feisty2
I'm Siri
 
feisty2's Avatar
 
Join Date: Oct 2012
Location: Los Angeles, California
Posts: 2,060
I certainly CAN read that kind of code, but that was way too assembly style and kinda makes me feel gross whenever reading such crap
__________________
If I got new ideas, will post here: https://github.com/IFeelBloated
feisty2 is offline   Reply With Quote
Old 12th December 2016, 20:10   #18  |  Link
shekh
Registered User
 
Join Date: Mar 2015
Posts: 405
Quote:
Originally Posted by captaiŋadamo View Post
How is it bad practice? It's a bog-standard idiom that's been used for decades.
IMO it is "bad" because:

cons:
it is more difficult to read and understand order of operations in complex expression than sequence of simple expressions
pros:
nothing
shekh is offline   Reply With Quote
Old 12th December 2016, 20:46   #19  |  Link
jackoneill
unsigned int
 
jackoneill's Avatar
 
Join Date: Oct 2012
Location: 🇪🇺
Posts: 620
And none of this is relevant to the topic at hand...
jackoneill is offline   Reply With Quote
Old 16th December 2016, 11:59   #20  |  Link
xekon
Registered User
 
Join Date: Jul 2011
Posts: 213
Ok, I finally got everything to compile, most of the errors were linking errors, it had been a couple years since I did any coding.
Also I did not realize that Visual Studio community 2015 by default did not install with a C++ compiler, you have to do advanced options install and check the boxes for that.
Thanks to HolyWu too! I found his C++ plugin/filter ports to be well structured and easy to follow (AddGrain, Deblock, DePan, W3FDIF). It provided with me with a good starting point for a Vapoursynth C++ filter

So there are no compiler errors, but VSedit crashes without any error messages when I try to use the filter.

how can I get VSedit to report the reason it crashed? to get more details, it has something to do with this filter, but i have no idea what without some kind of feedback.

I uploaded what I have so far: https://github.com/xekon/GradCurve

here are some project files that can be used for testing it: http://www.mediafire.com/file/9nc2et...j/gradcurve.7z

Code:
import vapoursynth as vs
core = vs.get_core()
ret = core.d2v.Source(input=r'/media/sf_enc/032t.d2v', rff=False)#Frame 6167
ret = core.resize.Bicubic(clip=ret, format=vs.RGB24, matrix_in_s="709")
ret = core.grad.Curve(ret,var='/media/sf_enc/032t.acv')
ret.set_output()
Code:
cd $HOME/.installs/VapourSynthPlugins
git clone https://github.com/xekon/GradCurve
cd $HOME/.installs/VapourSynthPlugins/GradCurve
./configure
make
sudo make install

Last edited by xekon; 29th January 2017 at 04:50.
xekon is offline   Reply With Quote
Reply

Tags
color correct, curves, gradation, vapoursynth, virtualdub

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 05:23.


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