View Full Version : GradCurve VapourSynth plugin port of virtualdub Gradation Curves plugin
xekon
10th December 2016, 15:13
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/jieiku/GradCurve
windows dll: https://github.com/jieiku/GradCurve/blob/master/GradCurve/x64/Release/GradCurve.dll
project files that can be used for testing: http://www.mediafire.com/file/9nc2etdr9i1tc9j/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 :)
Mystery Keeper
10th December 2016, 15:42
Why did you convert C++ code to Python? You could just make a C++ VapourSynth plugin.
xekon
10th December 2016, 15:46
oh I did not realize that. is there any advantage to one or the other? As far as vapoursynth is concerned.
jackoneill
10th December 2016, 22:39
If you do this in Python, it will be too slow to be usable.
captaiŋadamo
10th December 2016, 23:43
Just check out basically anything in here (https://github.com/vapoursynth/vapoursynth/tree/master/src/filters).
xekon
11th December 2016, 14:10
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)
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.
feisty2
11th December 2016, 14:18
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
jackoneill
11th December 2016, 15:16
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.
xekon
12th December 2016, 01:17
Thank you very much for the replies guys, I was looking at the wrong API page, thanks again Jackoneill.
StainlessS
12th December 2016, 02:57
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.
feisty2
12th December 2016, 04:35
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.
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.
StainlessS
12th December 2016, 18:41
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.]
while(*d++=*s++); // strcpy()
OR
for(;*d++=*s++;); // strcpy()
captaiŋadamo
12th December 2016, 19:15
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?
shekh
12th December 2016, 19:43
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? ;)
feisty2
12th December 2016, 19:47
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",,,
captaiŋadamo
12th December 2016, 19:47
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."
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.
feisty2
12th December 2016, 19:56
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
shekh
12th December 2016, 20:10
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
jackoneill
12th December 2016, 20:46
And none of this is relevant to the topic at hand...
xekon
16th December 2016, 11:59
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/jieiku/GradCurve
here are some project files that can be used for testing it: http://www.mediafire.com/file/9nc2etdr9i1tc9j/gradcurve.7z
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()
cd $HOME/.installs/VapourSynthPlugins
git clone https://github.com/jieiku/GradCurve
cd $HOME/.installs/VapourSynthPlugins/GradCurve
./configure
make
sudo make install
Myrsloik
16th December 2016, 12:19
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.
...
Run it in a debugger then.
shekh
16th December 2016, 13:41
Some hints assuming you use Visual Studio
build just the plugin with debug info and with no optimizations
set breakpoints to all major functions
specify launch options for debugging (application and command line)
feisty2
16th December 2016, 14:21
rgblab = new long[16777216];
labrgb = new long[16777216];
and no delete[] for both arrays, basic memory leak..
use smart pointers if you want some kind of automatic GC for C++ like in Java or C#
and both arrays do not feature a runtime determined length, simply make them static if worrying about blowing the stack up
static int32_t rgblab[16777216];
static int32_t labrgb[16777216];
feisty2
16th December 2016, 14:58
or a bit more organized with C++ 14..
#include <cstdint>
auto operator""ElementsLUTTable(size_t length) {
struct LUTTable final {
int32_t *RGBToLab = nullptr;
int32_t *LabToRGB = nullptr;
LUTTable(size_t length = 0) {
RGBToLab = new int32_t[length];
LabToRGB = new int32_t[length];
}
LUTTable(const LUTTable &) = delete;
LUTTable(LUTTable &&obj) {
RGBToLab = obj.RGBToLab;
LabToRGB = obj.LabToRGB;
obj.RGBToLab = nullptr;
obj.LabToRGB = nullptr;
}
auto &operator=(const LUTTable &) = delete;
auto &operator=(LUTTable &&obj) {
if (this != &obj) {
RGBToLab = obj.RGBToLab;
LabToRGB = obj.LabToRGB;
obj.RGBToLab = nullptr;
obj.LabToRGB = nullptr;
}
return *this;
}
~LUTTable() {
delete[] RGBToLab;
delete[] LabToRGB;
}
};
return LUTTable(length);
}
auto table = 16777216ElementsLUTTable;
Mystery Keeper
16th December 2016, 17:03
or a bit more organized with C++ 14..
#include <cstdint>
auto operator""ElementsLUTTable(size_t length) {
struct LUTTable final {
int32_t *RGBToLab = nullptr;
int32_t *LabToRGB = nullptr;
LUTTable(size_t length = 0) {
RGBToLab = new int32_t[length];
LabToRGB = new int32_t[length];
}
LUTTable(const LUTTable &) = delete;
LUTTable(LUTTable &&obj) {
RGBToLab = obj.RGBToLab;
LabToRGB = obj.LabToRGB;
obj.RGBToLab = nullptr;
obj.LabToRGB = nullptr;
}
auto &operator=(const LUTTable &) = delete;
auto &operator=(LUTTable &&obj) {
if (this != &obj) {
RGBToLab = obj.RGBToLab;
LabToRGB = obj.LabToRGB;
obj.RGBToLab = nullptr;
obj.LabToRGB = nullptr;
}
return *this;
}
~LUTTable() {
delete[] RGBToLab;
delete[] LabToRGB;
}
};
return LUTTable(length);
}
auto table = 16777216ElementsLUTTable;
One component of good coding is explicit intent. Your example is obscure. Does it even work? Isn't the structure declared in the scope of operator? Or does "auto" pull the declaration outside?
shekh
16th December 2016, 17:18
There was nothing wrong about labrgb tables except missing delete/wrong singleton. God idea to fix just that issue. Tables must not be static (they take space).
feisty2
16th December 2016, 17:39
One component of good coding is explicit intent. Your example is obscure. Does it even work? Isn't the structure declared in the scope of operator? Or does "auto" pull the declaration outside?
it works, test code, compiled and executed smoothly under vs2015
#include <cstdint>
#include <cstdlib>
#include <iostream>
auto operator""ElementsLUTTable(size_t length) {
struct LUTTable final {
int32_t *RGBToLab = nullptr;
int32_t *LabToRGB = nullptr;
LUTTable(size_t length = 0) {
RGBToLab = new int32_t[length];
LabToRGB = new int32_t[length];
}
LUTTable(const LUTTable &) = delete;
LUTTable(LUTTable &&obj) {
RGBToLab = obj.RGBToLab;
LabToRGB = obj.LabToRGB;
obj.RGBToLab = nullptr;
obj.LabToRGB = nullptr;
}
auto &operator=(const LUTTable &) = delete;
auto &operator=(LUTTable &&obj) {
if (this != &obj) {
RGBToLab = obj.RGBToLab;
LabToRGB = obj.LabToRGB;
obj.RGBToLab = nullptr;
obj.LabToRGB = nullptr;
}
return *this;
}
~LUTTable() {
delete[] RGBToLab;
delete[] LabToRGB;
}
};
return LUTTable(length);
}
auto table = 16777216ElementsLUTTable;
auto main()->int {
table.LabToRGB[123] = 123456;
std::cout << table.LabToRGB[123] << std::endl;
system("pause");
}
One component of good coding is explicit intent.
that's exactly what I'm trying to do.
auto value = 1.234;
auto val = 123;
such statements are legal for all basic (hardware supported) data types, but wouldn't work on user defined data types before C++11.
user defined literals (operator""xxx) have been introduced to C++ since C++11, which makes such stuff
auto cval = 3 + 1.123i; //operator""i
auto table = 16777216ElementsLUTTable; //operator""ElementsLUTTable
possible, and now you could make all your custom data types just as native as the basic data types long as you want to.
Does it even work? Isn't the structure declared in the scope of operator? Or does "auto" pull the declaration outside?
it works because the move constructor (since C++11) has been defined.
captaiŋadamo
16th December 2016, 17:45
LUTTable(LUTTable &&obj) {
RGBToLab = obj.RGBToLab;
LabToRGB = obj.LabToRGB;
obj.RGBToLab = nullptr;
obj.LabToRGB = nullptr;
}
auto &operator=(LUTTable &&obj) {
if (this != &obj) {
RGBToLab = obj.RGBToLab;
LabToRGB = obj.LabToRGB;
obj.RGBToLab = nullptr;
obj.LabToRGB = nullptr;
}
return *this;
}
So a C idiom is bad coding style, but setting data within an object to null within a copy constructor is good code? lolwut? A copy constructor is only meant to clone an object, it's not meant to modify the original object. Adding side-effects to a copy constructor is horrendous.
feisty2
16th December 2016, 17:51
LUTTable(LUTTable &&obj) {
RGBToLab = obj.RGBToLab;
LabToRGB = obj.LabToRGB;
obj.RGBToLab = nullptr;
obj.LabToRGB = nullptr;
}
auto &operator=(LUTTable &&obj) {
if (this != &obj) {
RGBToLab = obj.RGBToLab;
LabToRGB = obj.LabToRGB;
obj.RGBToLab = nullptr;
obj.LabToRGB = nullptr;
}
return *this;
}
So a C idiom is bad coding style, but setting data within an object to null within a copy constructor is good code? lolwut? A copy constructor is only meant to clone an object, it's not meant to modify the original object. Adding side-effects to a copy constructor is horrendous.
LUTTable(const LUTTable &) // copy constructor
LUTTable(LUTTable &&) // MOVE constructor (since C++11)
https://msdn.microsoft.com/en-us/library/dd293665.aspx
feisty2
16th December 2016, 18:12
and @captaiŋadamo
it's almost 2017 now, not 1997, time to shake the obsolete ideas off, C++ has always been EVOLVING! (C++17 is just around the corner :))
xekon
17th December 2016, 02:29
Some hints assuming you use Visual Studio
build just the plugin with debug info and with no optimizations
set breakpoints to all major functions
specify launch options for debugging (application and command line)
I am using Visual Studio 2015, when I try to run it in debug mode it says that it is not a valid Win32 application, which is because there is no MAIN function, since its library.
I could add a main function, but I would assume that I would also have to pass data to the functions like it would when the library is in use, otherwise how could I find the problem.
when I read about debugging dll libraries on microsoft website they suggest debugging the host application.
So I am currently installing Qt5, and trying to get everything in place to debug VSedit while its using the GradCurve plugin.
I just hope I am barking up the right tree here, and not off in left field.
EDIT:
I updated the github https://github.com/jieiku/GradCurve/
Removed variables left behind from vdub specific stuff as well as variables from starting off with HolyWu's AddGrain filter.
There is more cleanup to do once I have this working.
feisty2
17th December 2016, 02:35
Fix that memory leak and ur done.
shekh
17th December 2016, 02:36
You need to start the host application but you dont have to compile and debug it, the debugger kicks in once your dll is loaded.
xekon
17th December 2016, 02:36
OH! I didn't realize that was the only problem! I will try your implementation feisty2! thank you!
shekh
17th December 2016, 02:38
Btw, concerning lab mode
AFAIK is was both slow and low quality, maybe just worth removing anyway.
feisty2
17th December 2016, 02:39
Plus it's "delete[]" for arrays...
not sure if "delete array" will still lead to memory leak (only the first element got deleted)
Edit: just googled about that and "delete" works in your case also, cuz both arrays are an array of the basic data type (no destructor). But delete[] makes more sense, so use that instead
Edit2: I'm talking about line 673 and line 674 in ur source code
xekon
17th December 2016, 03:09
Plus it's "delete[]" for arrays...
not sure if "delete array" will still lead to memory leak (only the first element got deleted)
Edit: just googled about that and "delete" works in your case also, cuz both arrays are an array of the basic data type (no destructor). But delete[] makes more sense, so use that instead
Edit2: I'm talking about line 673 and line 674 in ur source code
Thank you everyone!
and thank you feisty2, i switched it to using brackets.
I assumed there were problems other than the memory leak, because when I build under linux vsedit still crashes after correcting the memory leaks, im building a dll under windows and going to try vsedit under windows to see if I still crash.
it sounds like the plugin is functioning for you guys, so something must be up with my build environment.
feisty2
17th December 2016, 06:40
since you PMed me, some debug info from vs2015
http://i.imgur.com/hwjxNlp.png
http://i.imgur.com/AvPFyo9.png
no offense but, ur code is way too cryptic and pretty much machine code to me..
xekon
17th December 2016, 06:52
ah, thanks for taking a look for me. the second picture you posted is where my vsedit crashed I believe. I will keep trying to figure out the reason its crashing. very little of the code was actually written by me, I migrated the code from the vdub c++ filter. I will probably need to get a better idea of how gradation curves is supposed to work before i can fix the problem.
jackoneill
17th December 2016, 16:07
Is d.filename initialised with zeroes? If not, strcat may find a zero past its end. Use the "n" versions of string functions if possible, i.e. strncat. Although I don't see why this isn't str(n)cpy. And since you're using C++ you might as well use std::string.
Are you sure you want those global variables in your library?
As far as I can tell, you could call ImportCurve and PreCalcLut from GradCurveCreate. They don't seem to use any data from the filter's input frames. It also looks like oldr, oldg, oldb, medr, medg, and medb can be local variables. Then you can switch to fmParallel.
Your filter accepts integer formats, but it assumes the frames always contain float pixels. If you test your filter with integer clips, the processing loop will inevitably read and write past the end of the frame.
xekon
17th December 2016, 23:23
Thank you so much for taking a look jackoneill, you have a sharp eye, I am going to make the changes you pointed out, also for the integer/float formats, sounds like I will need to have it check if the frame contains a float or an integer before processing.
AH, Looking back, NOW I see the reason for the template type in HolyWu's functions, one handles float and one handles INT. At first glance I did not see why there were two copies of most functions. Thats how I can handle Float vs Int data.
EDIT: or it may be that I need to change the function to only support 32 bit float input, for now this is what I am going to do.
I believe I made all of the changes you pointed out Jackoneill. After making those changes VSedit no longer crashes. I am assuming it was crashing because of the last one you pointed out, using integer input but assuming frames always contain float pixels and writing past the end of the frame.
The output is not what was expected... its solid black, LOL! but atleast I am not crashing now, and all frames are returned in VSedit.
I think I need to setup some code breaks in the original Vdub filter, and see how the data is being processed, and then compare that to what is happening in this vapoursynth ported version.
I really wish there were more comments in the vdub filter, but i'm sure I can figure it out if I keep stabbing at it, I don't think I would have gotten this far this quickly without everybody's help, and I have learned a bit too!
EDIT: oh and I updated the github: https://github.com/jieiku/GradCurve
Btw, concerning lab mode
AFAIK is was both slow and low quality, maybe just worth removing anyway.
ah, maybe I should, especially if nobody is going to be using it.
TheFluff
18th December 2016, 07:23
I dunno if you figured out how to debug VS (or Avisynth) plugins so just for the sake of clarity: basically all you need to do is build a debug version of your plugin and in your VS project you set the debug command to run a custom command line that launches some application (Virtualdub, VSEdit, whatever) that will end up loading your debug DLL. Then set a breakpoint on whatever you're interested in and press debug and off you go. I think you could also attach the debugger to the already running host application process before you load your script but I don't think I've ever done that.
The Avisynth wiki doesn't disappoint (http://avisynth.nl/index.php/Filter_SDK/Debugging_instructions) by the way; it recommends printf debugging first and then provides instructions for MSVC6 because of course it effin does. God, this ancient garbage...
xekon
18th December 2016, 07:49
Thank you TheFluff, i'm at work right now but as soon as I get home I am going to try and set up my plugin to launch VSedit, because this is exactly the point i'm at, needing to set breakpoints and check current values of variables.
because i've never built libraries before this is a bit new to me. most of the debugging i have done on other projects in the past has been direct output such as the printf example.
feisty2
18th December 2016, 07:54
Actually it's much simpler than that
Just use the buggy plugin as if it works
And sure vsedit will crash
And then the OS(at least under windows 10) will pop out a "vsedit has stopped working" window
And then you click "debug" or something like that
And then vs2015 will be invoked automatically and also, automatically locate to the exact statement in ur source code that caused the crash
xekon
18th December 2016, 08:20
feisty2 that's how I opened the debug the first time back when it was crashing, but now the plugin is no longer crashing, but its outputting incorrect frames (solid black) so I now need to set breakpoints like TheFluff was saying, or output diagnostic messages directly.
TheFluff
18th December 2016, 08:34
You can attach the VS debugger to any running process, there's no need to crash it. I think it's in the Debug menu somewhere and as I said, if you have a VS (or AVS) script that loads your debug DLL, you can just attach the debugger to the host application (VSEdit or whatever), set a breakpoint (or a few) in your DLL's code and when you load the script in the host application the debugger will halt on your breakpoint... I think. As I said I used to use the other way (setting the debug command to launch the host application with the intended debug script) but I'm pretty sure it's effectively the same thing.
xekon
19th December 2016, 00:35
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.
I got debugging working, YAY! (built the original Vdub gradation curves filter, to see how the data is supposed to look with the original vdub filter) I built the solution, set debugger to launch virtualdub, and then once virtualdub loaded I went to video add filter, and loaded the debug copy of the filter that I just built.
Now I just need to be able to understand the data, alot of these fields can be expanded, for some reason I expected it to look a lot simpler, showing an R G and B value somewhere between 0 and 255...
http://i1208.photobucket.com/albums/cc361/xekon/debug_zps5lpznyj8.jpg
Wilbert
19th December 2016, 01:32
Why don't you start with one frame consisting of one color (say red=128, blue=green=0), and apply the curves filter which should do nothing? Makes it easier to debug if that already produces incorrect results.
xekon
19th December 2016, 04:38
Why don't you start with one frame consisting of one color (say red=128, blue=green=0), and apply the curves filter which should do nothing? Makes it easier to debug if that already produces incorrect results.
Thanks that definitely did help.
BlankClip(color=$FF0000)
its obvious after reading this that I didnt have a clue how pixel data was stored: http://avisynth.nl/index.php/Colors
going to experiment a bit until I have it down good
edit: got a chance to look a bit today, my version is setting the values to medr/medb/medg to 0, they get their value from the gvalue/ovalue/rvalue arrays, so they probably dont have a value set at that location in the array, I didn't have a ton of time to look today, and I have a ton of work the next 2 days. Should be able to put some serious time into this again on Wednesday or thursday.
edit2: actually probably not until after the holidays.
edit3: [B]can vapoursynth variables srcpR[x] / dstpR[x] use integers instead of floats?
videoh
20th January 2017, 14:12
Did you verify that (int) medr (etc.) is not out of range? It's customary to clip values before using them as indices.
vBulletin® v3.8.11, Copyright ©2000-2025, vBulletin Solutions Inc.