diff options
| author | Comment <tim@gray.(none)> | 2013-08-19 18:35:05 +0100 |
|---|---|---|
| committer | Comment <tim@gray.(none)> | 2013-08-19 18:35:05 +0100 |
| commit | f485d31d2dd2e80f835b648115067a341f1b4fb3 (patch) | |
| tree | 3132c8190bed2872d7b16f8071a60532d9ed1b13 | |
| parent | 318ba67bf91c07ff1edd0f2547b49d80ef9e0f83 (diff) | |
fix random node initialisation bug
| -rw-r--r-- | rotord/src/nodes_filters.h | 246 | ||||
| -rw-r--r-- | rotord/src/nodes_maths.h | 8 | ||||
| -rwxr-xr-x | rotord/src/rotor.cpp | 6 | ||||
| -rwxr-xr-x | rotord/src/rotor.h | 311 |
4 files changed, 303 insertions, 268 deletions
diff --git a/rotord/src/nodes_filters.h b/rotord/src/nodes_filters.h index 263b4b2..0cc1d77 100644 --- a/rotord/src/nodes_filters.h +++ b/rotord/src/nodes_filters.h @@ -31,6 +31,252 @@ namespace Rotor { private: float size; }; + class Luma_levels: public Image_node { + public: + Luma_levels(){ + create_image_input("image input","Image input"); + create_parameter("black_in","number","input black point","Input black point",0.0f,0.0f,1.0f); + create_parameter("white_in","number","input white point","Input white point",1.0f,0.0f,1.0f); + create_parameter("gamma","number","gamma level","Gamma",1.0f,0.0f,10.0f); + create_parameter("black_out","number","output black point","Output black point",0.0f,0.0f,1.0f); + create_parameter("white_out","number","output white point","Output white point",1.0f,0.0f,1.0f); + title="Luma levels"; + description="Remap luma values of image"; + LUT=nullptr; + }; + Luma_levels(map<string,string> &settings):Luma_levels() { + base_settings(settings); + } + ~Luma_levels(){if (LUT) { delete[] LUT;} }; + void generate_LUT(){ + //can check here if anything has changed + if (LUT) delete[] LUT; + LUT=new unsigned char[256]; + float fltmax=(255.0f/256.0f); + for (int i=0;i<256;i++){ + LUT[i]=(unsigned char)(((pow(min(fltmax,max(0.0f,(((((float)i)/256.0f)-parameters["black_in"]->value)/(parameters["white_in"]->value-parameters["black_in"]->value)))),(1.0/parameters["gamma"]->value))*(parameters["white_out"]->value-parameters["black_out"]->value))+parameters["black_out"]->value)*255.0f); + } + } + void apply_LUT(const Image& in){ + apply_LUT(in,image); + } + void apply_LUT(const Image& in,Image &out){ //facility to apply to other images for inherited classes + out.setup(in.w,in.h); + for (int i=0;i<out.w*out.h*3;i++){ + out.RGBdata[i]=LUT[in.RGBdata[i]]; + } + } + Image *output(const Frame_spec &frame){ + Image *in=image_inputs[0]->get(frame); + if (in){ + generate_LUT(); + apply_LUT(*in); + } + return ℑ + } + Luma_levels* clone(map<string,string> &_settings) { return new Luma_levels(_settings);}; + protected: + unsigned char *LUT; + }; + class Echo_trails: public Luma_levels { + //draw trail frames additively that fade off over time + //the hard thing here is how to cache frames, if its done cleverly it could have no impact when + //used linearly + //Image needs to overload operator+ + //need a clever data structure to cache frames - maybe a map of Image pointers + + //we know the frames we want to overlay as offsets ie -25,-20,-15,-10,-5 + //do we keep 25 frames loaded in order to benefit? 25 PAL frames is 60MB so probably so + //OK so: + //make a new set of pointers + //identify if any of the new pointers can inherit old frames + //delete unneeded old frames + //load new frames + //do the calculations + + //new set of pointers? or track frames by absolute frame number? + //with relative pointers and switching frames, could use auto_ptr? + + //this cache mechanism should maybe be inheritable too? + + //it could be hugely beneficial to only do the LUT once? + //although maybe the way to do the fading is to have a LUT for each frame? + + //or is it actually best to use alpha keying after all! + public: + Echo_trails(){ + //calls base class constructor first + create_parameter("number","number","number of echoes","Number echoes",25.0f); + create_parameter("fadeto","number","amount that echoes fade out","Fadout amount",1.0f,0.0f,1.0f); + create_attribute("mode","blend mode for echoes","Blend mode","screen",{"screen","wrap"}); + title="Echo trails"; + description="Draw trail frames additively that fade off over time"; + }; + Echo_trails(map<string,string> &settings):Echo_trails() { + base_settings(settings); + lastframe=-1; + } + ~Echo_trails(){ + for (auto i:images) delete i.second; + }; + Image *output(const Frame_spec &frame){ + //check if cache is valid + if (images.size()){ + if (frame.w!=image.w||frame.h!=image.h){ //or framerate changed? + //clear cache and start over + images.clear(); + lastframe=-1; + //calculate frame interval + //interval=(int)(((duration/number)*frame.framerate)+0.5); + //total=interval*number; + } + } + int thisframe=frame.frame(); + //iterate cache and throw out any obsolete frames + auto i = std::begin(images); + while (i != std::end(images)) { + // check if the image is in the range we need + if (thisframe-(*i).first>(int)parameters["number"]->value||thisframe-(*i).first<0) { + delete (*i).second; + i = images.erase(i); + } + else + ++i; + } + //if frame has already been calculated just return it + if (thisframe!=lastframe) { + Image *in=image_inputs[0]->get(frame); + if (in) { + generate_LUT(); + //need a better strategy here, should be able to get each image once + //copy incoming image **writable + image=*(in); + images[thisframe]=new Image(frame.w,frame.h); + apply_LUT(image,*(images[thisframe])); + for (int i=1;i<(int)parameters["number"]->value;i++){ + //check echo frame isn't at negative time + int absframe=thisframe-i; + if (absframe>-1){ + //check if image is in the cache + if (images.find(absframe)==images.end()){ + images[absframe]=new Image(frame.w,frame.h); + Frame_spec wanted=Frame_spec(absframe,frame.framerate,frame.duration,frame.w,frame.h); + apply_LUT(*(((Image_node*)image_inputs[0]->connection)->get_output(wanted)),*(images[absframe])); + } + if (fless(1.0f,parameters["fadeto"]->value)){ + float amount=(((parameters["number"]->value-i)/parameters["number"]->value)*(1.0f-parameters["fadeto"]->value))+(1.0f-parameters["fadeto"]->value); + Image *temp=*images[absframe]*amount; + if (attributes["mode"]->value=="screen") { + image+=*temp; + } + else { + image.add_wrap(*temp); + } + delete temp; + } + else { + if (attributes["mode"]->value=="screen") image+=*(images[absframe]); + else image=image.add_wrap(*(images[absframe])); + } + } + } + //for (int i=0;i<frame.w*frame.h*3;i++){ + // image->RGBdata[i]=LUT[in->RGBdata[i]]; + //} + lastframe=thisframe; + } + } + return ℑ + } + Echo_trails* clone(map<string,string> &_settings) { return new Echo_trails(_settings);}; + protected: + int interval,total,lastframe; //number of frames between displayed echoes + unordered_map<int,Image*> images; + }; + class RGB_levels: public Image_node { + public: + RGB_levels(){ + create_image_input("image input","Image input"); + create_parameter("red_black_in","number","Red input black-point","Red input black-point",0.0f,0.0f,1.0f); + create_parameter("red_white_in","number","Red input white-point","Red input white-point",1.0f,0.0f,1.0f); + create_parameter("red_gamma","number","Red gamma level","Red gamma",1.0f,0.01f,10.0f); + create_parameter("red_black_out","number","Red output black point","Red output black point",0.0f,0.0f,1.0f); + create_parameter("red_white_out","number","Red output white point","Red output white point",1.0f,0.0f,1.0f); + create_parameter("green_black_in","number","Green input black point","Green input black point",0.0f,0.0f,1.0f); + create_parameter("green_white_in","number","Green input white point","Green input white point",1.0f,0.0f,1.0f); + create_parameter("green_gamma","number","Green gamma level","Green gamma",1.0f,0.01f,10.0f); + create_parameter("green_black_out","number","Green output black point","Green output black point",0.0f,0.0f,1.0f); + create_parameter("green_white_out","number","Green output white point","Green output white point",1.0f,0.0f,1.0f); + create_parameter("blue_black_in","number","Blue input black point","Blue input black point",0.0f,0.0f,1.0f); + create_parameter("blue_white_in","number","Blue input white point","Blue input white point",1.0f,0.0f,1.0f); + create_parameter("blue_gamma","number","Blue gamma level","Blue gamma",1.0f,0.01f,10.0f); + create_parameter("blue_black_out","number","Blue output black point","Blue output black point",0.0f,0.0f,1.0f); + create_parameter("blue_white_out","number","Blue output white point","Blue output white point",1.0f,0.0f,1.0f); + title="RGB levels"; + description="Remap RGB values of image"; + LUT=nullptr; + }; + RGB_levels(map<string,string> &settings):RGB_levels() { + base_settings(settings); + } + ~RGB_levels(){ + if (LUT) { + for (int i=0;i<3;i++) { + delete[] LUT[i]; + } + delete[] LUT; + } + }; + void generate_LUT(){ + //can check here if anything has changed + if (LUT) { + for (int i=0;i<3;i++) { + delete[] LUT[i]; + } + delete[] LUT; + } + LUT=new unsigned char*[3]; + for (int i=0;i<3;i++){ + LUT[i]=new unsigned char[256]; + } + float fltmax=(255.0f/256.0f); + for (int i=0;i<256;i++){ + LUT[0][i]=(unsigned char)(((\ + pow(min(fltmax,max(0.0f,(((((float)i)/256.0f)-parameters["red_black_in"]->value)/(parameters["red_white_in"]->value-parameters["red_black_in"]->value))))\ + ,(1.0/parameters["red_gamma"]->value))\ + *(parameters["red_white_out"]->value-parameters["red_black_out"]->value))+parameters["red_black_out"]->value)*255.0f); + LUT[1][i]=(unsigned char)(((\ + pow(min(fltmax,max(0.0f,(((((float)i)/256.0f)-parameters["green_black_in"]->value)/(parameters["green_white_in"]->value-parameters["green_black_in"]->value))))\ + ,(1.0/parameters["green_gamma"]->value))\ + *(parameters["green_white_out"]->value-parameters["green_black_out"]->value))+parameters["green_black_out"]->value)*255.0f); + LUT[2][i]=(unsigned char)(((\ + pow(min(fltmax,max(0.0f,(((((float)i)/256.0f)-parameters["blue_black_in"]->value)/(parameters["blue_white_in"]->value-parameters["blue_black_in"]->value))))\ + ,(1.0/parameters["blue_gamma"]->value))\ + *(parameters["blue_white_out"]->value-parameters["blue_black_out"]->value))+parameters["blue_black_out"]->value)*255.0f); + } + } + void apply_LUT(const Image& in){ + apply_LUT(in,image); + } + void apply_LUT(const Image& in,Image &out){ //facility to apply to other images for inherited classes + for (int i=0;i<out.w*out.h;i++){ + out.RGBdata[i*3]=LUT[0][in.RGBdata[i*3]]; + out.RGBdata[i*3+1]=LUT[1][in.RGBdata[i*3+1]]; + out.RGBdata[i*3+2]=LUT[2][in.RGBdata[i*3+2]]; + } + } + Image *output(const Frame_spec &frame){ + Image *in=image_inputs[0]->get(frame); + if (in){ + generate_LUT(); + apply_LUT(*in); + } + return ℑ + } + RGB_levels* clone(map<string,string> &_settings) { return new RGB_levels(_settings);}; + protected: + unsigned char **LUT; + }; } diff --git a/rotord/src/nodes_maths.h b/rotord/src/nodes_maths.h index 4ec2cf9..b1e20ca 100644 --- a/rotord/src/nodes_maths.h +++ b/rotord/src/nodes_maths.h @@ -25,7 +25,7 @@ namespace Rotor { base_settings(settings); } Comparison* clone(map<string,string> &_settings) { return new Comparison(_settings);}; - const float output(const Time_spec &time) { + const float output(const Time_spec &time) { switch (attributes["operator"]->intVal) { case COMPARISON_Equal: return fequal(parameters["value"]->value,inputs[0]->get(time))?1.0f:0.0f; @@ -46,7 +46,7 @@ namespace Rotor { return fless_or_equal(parameters["value"]->value,inputs[0]->get(time))?1.0f:0.0f; break; } - + return 0.0f; } }; @@ -193,7 +193,7 @@ namespace Rotor { create_signal_input("signal","Signal"); create_parameter("seed","number","Seed value","Seed",1.0f); }; - Random(map<string,string> &settings) { + Random(map<string,string> &settings):Random() { base_settings(settings); }; Random* clone(map<string,string> &_settings) { return new Random(_settings);}; @@ -231,4 +231,4 @@ namespace Rotor { }; } -#endif
\ No newline at end of file +#endif diff --git a/rotord/src/rotor.cpp b/rotord/src/rotor.cpp index e205492..0284223 100755 --- a/rotord/src/rotor.cpp +++ b/rotord/src/rotor.cpp @@ -17,9 +17,6 @@ Node_factory::Node_factory(){ add_type("signal_colour",new Signal_colour()); add_type("signal_greyscale",new Signal_greyscale()); add_type("image_arithmetic",new Image_arithmetic()); - add_type("luma_levels",new Luma_levels()); - add_type("echo_trails",new Echo_trails()); - add_type("rgb_levels",new RGB_levels()); add_type("blend",new Blend()); add_type("mirror",new Mirror()); add_type("monochrome",new Monochrome()); @@ -38,6 +35,9 @@ Node_factory::Node_factory(){ add_type("hello",new Hello_draw()); //nodes_filters.h add_type("blur",new Blur()); + add_type("luma_levels",new Luma_levels()); + add_type("echo_trails",new Echo_trails()); + add_type("rgb_levels",new RGB_levels()); //video nodes add_type("video_loader",new Video_loader()); add_type("video_output",new Video_output()); diff --git a/rotord/src/rotor.h b/rotord/src/rotor.h index f7d6861..eb00104 100755 --- a/rotord/src/rotor.h +++ b/rotord/src/rotor.h @@ -95,7 +95,7 @@ namespace Rotor { public: virtual ~Image_input(){}; bool connect(Node *source); - Image_input(const string &_desc,const string &_title,Node* _connect): Input(_desc,_title){ + Image_input(const string &_desc,const string &_title,Node* _connect): Input(_desc,_title){ connect(_connect); }; Image* get(const Frame_spec& time); @@ -104,7 +104,7 @@ namespace Rotor { public: virtual ~Signal_input(){}; bool connect(Node *source); - Signal_input(const string &_desc,const string &_title,Node* _connect): Input(_desc,_title){ + Signal_input(const string &_desc,const string &_title,Node* _connect): Input(_desc,_title){ connect(_connect); }; float get(const Time_spec& time); @@ -112,7 +112,7 @@ namespace Rotor { class Parameter: public Signal_input{ public: virtual ~Parameter(){}; - void init(const float &_val){ + void init(const float &_val){ value=_val; } Parameter(const string &_type,const string &_desc,const string &_title,float _value,float _min,float _max,Node* _connect): Signal_input(_desc,_title,_connect),value(_value),min(_min),max(_max),type(_type){}; @@ -204,17 +204,17 @@ namespace Rotor { void create_image_input(const string &_title,const string &_desc,Node* _connect=nullptr) { image_inputs.push_back(new Image_input(_desc,_title,_connect)); }; - Image *get_output(const Frame_spec &frame) { + Image *get_output(const Frame_spec &frame) { image.setup(frame.w,frame.h); update((Time_spec)frame); - return output(frame); + return output(frame); } virtual const Image *output(const Frame_spec &frame)=0; Image *get_preview(const Frame_spec &frame); Image image; private: float image_time; //? could be used to detect image reuse? - + }; class Audio_processor: public Signal_node { public: @@ -295,13 +295,13 @@ namespace Rotor { return ℑ } private: - + }; class Invert: public Image_node { public: Invert(){ create_image_input("Image to invert","Image input"); - create_parameter("invert","number","Invert when greater than 0.0","Negative",1.0f,0.0f,1.0f); + create_parameter("invert","number","Invert when greater than 0.0","Negative",1.0f,0.0f,1.0f); title="Negative"; description="Inverts the input picture"; }; @@ -446,259 +446,13 @@ namespace Rotor { image=(*in); image/=parameters["value"]->value; break; - } + } } return ℑ } Image_arithmetic* clone(map<string,string> &_settings) { return new Image_arithmetic(_settings);}; private: }; - class Luma_levels: public Image_node { - public: - Luma_levels(){ - create_image_input("image input","Image input"); - create_parameter("black_in","number","input black point","Input black point",0.0f,0.0f,1.0f); - create_parameter("white_in","number","input white point","Input white point",1.0f,0.0f,1.0f); - create_parameter("gamma","number","gamma level","Gamma",1.0f,0.0f,10.0f); - create_parameter("black_out","number","output black point","Output black point",0.0f,0.0f,1.0f); - create_parameter("white_out","number","output white point","Output white point",1.0f,0.0f,1.0f); - title="Luma levels"; - description="Remap luma values of image"; - LUT=nullptr; - }; - Luma_levels(map<string,string> &settings):Luma_levels() { - base_settings(settings); - } - ~Luma_levels(){if (LUT) { delete[] LUT;} }; - void generate_LUT(){ - //can check here if anything has changed - if (LUT) delete[] LUT; - LUT=new unsigned char[256]; - float fltmax=(255.0f/256.0f); - for (int i=0;i<256;i++){ - LUT[i]=(unsigned char)(((pow(min(fltmax,max(0.0f,(((((float)i)/256.0f)-parameters["black_in"]->value)/(parameters["white_in"]->value-parameters["black_in"]->value)))),(1.0/parameters["gamma"]->value))*(parameters["white_out"]->value-parameters["black_out"]->value))+parameters["black_out"]->value)*255.0f); - } - } - void apply_LUT(const Image& in){ - apply_LUT(in,image); - } - void apply_LUT(const Image& in,Image &out){ //facility to apply to other images for inherited classes - out.setup(in.w,in.h); - for (int i=0;i<out.w*out.h*3;i++){ - out.RGBdata[i]=LUT[in.RGBdata[i]]; - } - } - Image *output(const Frame_spec &frame){ - Image *in=image_inputs[0]->get(frame); - if (in){ - generate_LUT(); - apply_LUT(*in); - } - return ℑ - } - Luma_levels* clone(map<string,string> &_settings) { return new Luma_levels(_settings);}; - protected: - unsigned char *LUT; - }; - class Echo_trails: public Luma_levels { - //draw trail frames additively that fade off over time - //the hard thing here is how to cache frames, if its done cleverly it could have no impact when - //used linearly - //Image needs to overload operator+ - //need a clever data structure to cache frames - maybe a map of Image pointers - - //we know the frames we want to overlay as offsets ie -25,-20,-15,-10,-5 - //do we keep 25 frames loaded in order to benefit? 25 PAL frames is 60MB so probably so - //OK so: - //make a new set of pointers - //identify if any of the new pointers can inherit old frames - //delete unneeded old frames - //load new frames - //do the calculations - - //new set of pointers? or track frames by absolute frame number? - //with relative pointers and switching frames, could use auto_ptr? - - //this cache mechanism should maybe be inheritable too? - - //it could be hugely beneficial to only do the LUT once? - //although maybe the way to do the fading is to have a LUT for each frame? - - //or is it actually best to use alpha keying after all! - public: - Echo_trails(){ - //calls base class constructor first - create_parameter("number","number","number of echoes","Number echoes",25.0f); - create_parameter("fadeto","number","amount that echoes fade out","Fadout amount",1.0f,0.0f,1.0f); - create_attribute("mode","blend mode for echoes","Blend mode","screen",{"screen","wrap"}); - title="Echo trails"; - description="Draw trail frames additively that fade off over time"; - }; - Echo_trails(map<string,string> &settings):Echo_trails() { - base_settings(settings); - lastframe=-1; - } - ~Echo_trails(){ - for (auto i:images) delete i.second; - }; - Image *output(const Frame_spec &frame){ - //check if cache is valid - if (images.size()){ - if (frame.w!=image.w||frame.h!=image.h){ //or framerate changed? - //clear cache and start over - images.clear(); - lastframe=-1; - //calculate frame interval - //interval=(int)(((duration/number)*frame.framerate)+0.5); - //total=interval*number; - } - } - int thisframe=frame.frame(); - //iterate cache and throw out any obsolete frames - auto i = std::begin(images); - while (i != std::end(images)) { - // check if the image is in the range we need - if (thisframe-(*i).first>(int)parameters["number"]->value||thisframe-(*i).first<0) { - delete (*i).second; - i = images.erase(i); - } - else - ++i; - } - //if frame has already been calculated just return it - if (thisframe!=lastframe) { - Image *in=image_inputs[0]->get(frame); - if (in) { - generate_LUT(); - //need a better strategy here, should be able to get each image once - //copy incoming image **writable - image=*(in); - images[thisframe]=new Image(frame.w,frame.h); - apply_LUT(image,*(images[thisframe])); - for (int i=1;i<(int)parameters["number"]->value;i++){ - //check echo frame isn't at negative time - int absframe=thisframe-i; - if (absframe>-1){ - //check if image is in the cache - if (images.find(absframe)==images.end()){ - images[absframe]=new Image(frame.w,frame.h); - Frame_spec wanted=Frame_spec(absframe,frame.framerate,frame.duration,frame.w,frame.h); - apply_LUT(*(((Image_node*)image_inputs[0]->connection)->get_output(wanted)),*(images[absframe])); - } - if (fless(1.0f,parameters["fadeto"]->value)){ - float amount=(((parameters["number"]->value-i)/parameters["number"]->value)*(1.0f-parameters["fadeto"]->value))+(1.0f-parameters["fadeto"]->value); - Image *temp=*images[absframe]*amount; - if (attributes["mode"]->value=="screen") { - image+=*temp; - } - else { - image.add_wrap(*temp); - } - delete temp; - } - else { - if (attributes["mode"]->value=="screen") image+=*(images[absframe]); - else image=image.add_wrap(*(images[absframe])); - } - } - } - //for (int i=0;i<frame.w*frame.h*3;i++){ - // image->RGBdata[i]=LUT[in->RGBdata[i]]; - //} - lastframe=thisframe; - } - } - return ℑ - } - Echo_trails* clone(map<string,string> &_settings) { return new Echo_trails(_settings);}; - protected: - int interval,total,lastframe; //number of frames between displayed echoes - unordered_map<int,Image*> images; - }; - class RGB_levels: public Image_node { - public: - RGB_levels(){ - create_image_input("image input","Image input"); - create_parameter("red_black_in","number","Red input black-point","Red input black-point",0.0f,0.0f,1.0f); - create_parameter("red_white_in","number","Red input white-point","Red input white-point",1.0f,0.0f,1.0f); - create_parameter("red_gamma","number","Red gamma level","Red gamma",1.0f,0.01f,10.0f); - create_parameter("red_black_out","number","Red output black point","Red output black point",0.0f,0.0f,1.0f); - create_parameter("red_white_out","number","Red output white point","Red output white point",1.0f,0.0f,1.0f); - create_parameter("green_black_in","number","Green input black point","Green input black point",0.0f,0.0f,1.0f); - create_parameter("green_white_in","number","Green input white point","Green input white point",1.0f,0.0f,1.0f); - create_parameter("green_gamma","number","Green gamma level","Green gamma",1.0f,0.01f,10.0f); - create_parameter("green_black_out","number","Green output black point","Green output black point",0.0f,0.0f,1.0f); - create_parameter("green_white_out","number","Green output white point","Green output white point",1.0f,0.0f,1.0f); - create_parameter("blue_black_in","number","Blue input black point","Blue input black point",0.0f,0.0f,1.0f); - create_parameter("blue_white_in","number","Blue input white point","Blue input white point",1.0f,0.0f,1.0f); - create_parameter("blue_gamma","number","Blue gamma level","Blue gamma",1.0f,0.01f,10.0f); - create_parameter("blue_black_out","number","Blue output black point","Blue output black point",0.0f,0.0f,1.0f); - create_parameter("blue_white_out","number","Blue output white point","Blue output white point",1.0f,0.0f,1.0f); - title="RGB levels"; - description="Remap RGB values of image"; - LUT=nullptr; - }; - RGB_levels(map<string,string> &settings):RGB_levels() { - base_settings(settings); - } - ~RGB_levels(){ - if (LUT) { - for (int i=0;i<3;i++) { - delete[] LUT[i]; - } - delete[] LUT; - } - }; - void generate_LUT(){ - //can check here if anything has changed - if (LUT) { - for (int i=0;i<3;i++) { - delete[] LUT[i]; - } - delete[] LUT; - } - LUT=new unsigned char*[3]; - for (int i=0;i<3;i++){ - LUT[i]=new unsigned char[256]; - } - float fltmax=(255.0f/256.0f); - for (int i=0;i<256;i++){ - LUT[0][i]=(unsigned char)(((\ - pow(min(fltmax,max(0.0f,(((((float)i)/256.0f)-parameters["red_black_in"]->value)/(parameters["red_white_in"]->value-parameters["red_black_in"]->value))))\ - ,(1.0/parameters["red_gamma"]->value))\ - *(parameters["red_white_out"]->value-parameters["red_black_out"]->value))+parameters["red_black_out"]->value)*255.0f); - LUT[1][i]=(unsigned char)(((\ - pow(min(fltmax,max(0.0f,(((((float)i)/256.0f)-parameters["green_black_in"]->value)/(parameters["green_white_in"]->value-parameters["green_black_in"]->value))))\ - ,(1.0/parameters["green_gamma"]->value))\ - *(parameters["green_white_out"]->value-parameters["green_black_out"]->value))+parameters["green_black_out"]->value)*255.0f); - LUT[2][i]=(unsigned char)(((\ - pow(min(fltmax,max(0.0f,(((((float)i)/256.0f)-parameters["blue_black_in"]->value)/(parameters["blue_white_in"]->value-parameters["blue_black_in"]->value))))\ - ,(1.0/parameters["blue_gamma"]->value))\ - *(parameters["blue_white_out"]->value-parameters["blue_black_out"]->value))+parameters["blue_black_out"]->value)*255.0f); - } - } - void apply_LUT(const Image& in){ - apply_LUT(in,image); - } - void apply_LUT(const Image& in,Image &out){ //facility to apply to other images for inherited classes - for (int i=0;i<out.w*out.h;i++){ - out.RGBdata[i*3]=LUT[0][in.RGBdata[i*3]]; - out.RGBdata[i*3+1]=LUT[1][in.RGBdata[i*3+1]]; - out.RGBdata[i*3+2]=LUT[2][in.RGBdata[i*3+2]]; - } - } - Image *output(const Frame_spec &frame){ - Image *in=image_inputs[0]->get(frame); - if (in){ - generate_LUT(); - apply_LUT(*in); - } - return ℑ - } - RGB_levels* clone(map<string,string> &_settings) { return new RGB_levels(_settings);}; - protected: - unsigned char **LUT; - }; #define BLEND_blend 1 #define BLEND_screen 2 #define BLEND_multiply 3 @@ -938,7 +692,6 @@ namespace Rotor { Alpha_merge(){ create_image_input("image input","Image input"); create_image_input("alpha input","Alpha input"); - create_parameter("transformX","number","X transformation","Transform X",0.0f); title="Alpha merge"; description="Alpha merge two images"; }; @@ -964,6 +717,42 @@ namespace Rotor { } private: }; + class Difference_matte: public Image_node { + public: + Difference_matte(){ + create_image_input("image input","Image input"); + create_image_input("background input","Background input"); + create_parameter("threshold","number","Difference threshold","Threshold",0.05f,0.0f,1.0f); + title="Difference matte"; + description="Create an alpha channel using a background reference picture"; + }; + Difference_matte(map<string,string> &settings):Difference_matte() { + base_settings(settings); + }; + ~Difference_matte(){}; + Difference_matte* clone(map<string,string> &_settings) { return new Difference_matte(_settings);}; + Image *output(const Frame_spec &frame){ + Image *in1=image_inputs[0]->get(frame); + if (in1){ + //copy incoming image **writable + Image *in2=image_inputs[1]->get(frame); + if (in2) { + cv::cvtColor(in1->rgb,greyfg,CV_RGB2GRAY); + cv::cvtColor(in2->rgb,greybg,CV_RGB2GRAY); + //cv::absDiff(greybg,greyfg,greyDiff); + //adaptiveThreshold(greyDiff,parameters["threshold"].value,20,true,false); //int blockSize, int offset=0,bool invert=false, bool gauss=false); + + image.alpha_merge(*in2); + return ℑ + } + //if there aren't 2 image inputs connected just return the first + return in1; + } + return nullptr; + } + private: + cv::Mat greyfg,greybg,greyDiff; + }; #define VIDEOFRAMES_still 1 #define VIDEOFRAMES_blend 2 class Video_loader: public Image_node { @@ -1049,7 +838,7 @@ namespace Rotor { // XML.setValue("description",type.second->description,0); //} int j=0; - for (auto& input: type.second->inputs) { + for (auto& input: type.second->inputs) { XML.addTag("signal_input"); XML.addAttribute("signal_input","title",input->title,j); XML.addAttribute("signal_input","description",input->description,j); @@ -1057,7 +846,7 @@ namespace Rotor { } j=0; if (dynamic_cast<Image_node*> (type.second)!=nullptr) { - for (auto& input: (dynamic_cast<Image_node*>(type.second))->image_inputs) { + for (auto& input: (dynamic_cast<Image_node*>(type.second))->image_inputs) { XML.addTag("image_input"); XML.addAttribute("image_input","title",input->title,j); XML.addAttribute("image_input","description",input->description,j); @@ -1065,7 +854,7 @@ namespace Rotor { } } j=0; - for (auto& parameter: type.second->parameters) { + for (auto& parameter: type.second->parameters) { XML.addTag("parameter"); XML.addAttribute("parameter","name",parameter.first,j); XML.addAttribute("parameter","type",parameter.second->type,j); @@ -1077,7 +866,7 @@ namespace Rotor { j++; } j=0; - for (auto& attribute: type.second->attributes) { + for (auto& attribute: type.second->attributes) { XML.addTag("attribute"); XML.addAttribute("attribute","name",attribute.first,j); XML.addAttribute("attribute","title",attribute.second->title,j); @@ -1160,4 +949,4 @@ namespace Rotor { }; } -#endif
\ No newline at end of file +#endif |
