diff options
| -rw-r--r-- | rotord/image.h | 211 | ||||
| -rwxr-xr-x | rotord/rotor.cpp | 1 | ||||
| -rwxr-xr-x | rotord/rotor.h | 228 | ||||
| -rwxr-xr-x | rotord/rotord.cpp | 2 |
4 files changed, 246 insertions, 196 deletions
diff --git a/rotord/image.h b/rotord/image.h new file mode 100644 index 0000000..5e39b18 --- /dev/null +++ b/rotord/image.h @@ -0,0 +1,211 @@ +namespace Rotor { + class pixeltables{ + //handy pixel arithmetic lookup tables as nested arrays + //so - pixels.add[0x78][0x66]; will give the precalculated result of adding with saturation + // pixels.mono_weights[0][0x100]; will give the red component to convert to mono + public: + pixeltables(){ + add=new uint8_t*[256]; + multiply=new uint8_t*[256]; + for (int i=0;i<256;i++){ + add[i]=new uint8_t[256]; + multiply[i]=new uint8_t[256]; + for (int j=0;j<256;j++){ + add[i][j]=(uint8_t)min(i+j,0xFF); + multiply[i][j]=(uint8_t)((((float)i)/255.0f)*(((float)j)/255.0f)*255.0f); + } + } + mono_weights=new uint8_t*[3]; + float weights[3]={0.2989, 0.5870, 0.1140}; + for (int i=0;i<3;i++) { + mono_weights[i]=new uint8_t[256]; + for (int j=0;j<256;j++){ + mono_weights[i][j]=(uint8_t)(((float)j)*weights[i]); + } + } + } + virtual ~pixeltables(){ + for (int i=0;i<256;i++){ + delete[] add[i]; + delete[] multiply[i]; + } + delete[] add; + delete[] multiply; + for (int i=0;i<3;i++) { + delete[] mono_weights[i]; + } + delete[] mono_weights; + } + uint8_t **add; + uint8_t **multiply; + uint8_t **mono_weights; + }; + static pixeltables pixels; + class Image{ + public: + Image(){ + zero(); + }; + Image(int _w,int _h){ + zero(); + setup(_w,_h); + }; + ~Image() { + free(); + }; + void free(){ + if (RGBdata&&ownsRGBdata) delete[] RGBdata; + if (Adata&&ownsAdata) delete[] Adata; + if (Zdata&&ownsZdata) delete[] Zdata; + zero(); + } + void zero(){ + RGBdata=nullptr; + Adata=nullptr; + Zdata=nullptr; + w=0; + h=0; + ownsRGBdata=ownsAdata=ownsZdata=false; + } + bool setup(int _w,int _h){ //set up with internal data + if (w!=_w||h!=_h||!ownsRGBdata||!ownsAdata||!ownsZdata){ + free(); + w=_w; + h=_h; + RGBdata=new uint8_t[w*h*3]; + Adata=new uint8_t[w*h]; + Zdata=new uint16_t[w*h]; + ownsRGBdata=ownsAdata=ownsZdata=true; + return true; + } + else return false; + } + bool setup_fromRGB(int _w,int _h,uint8_t *pRGBdata){ //possibility of just resetting pointer? + if (w!=_w||h!=_h||ownsRGBdata||!ownsAdata||!ownsZdata){ + free(); + w=_w; + h=_h; + RGBdata=pRGBdata; + Adata=new uint8_t[w*h]; + Zdata=new uint16_t[w*h]; + ownsRGBdata=false; + ownsAdata=ownsZdata=true; + return true; + } + return false; + } + Image* clone(){ + Image *t=new Image(w,h); + for (int i=0;i<w*h*3;i++) { + t->RGBdata[i]=RGBdata[i]; + } + return t; + } + Image & operator+=(const Image &other) { + if (other.w!=w||other.h!=h) { + cerr<<"Rotor: cannot add images with different sizes! (wanted "<<w<<"x"<<h<<", got "<<other.w<<"x"<<other.h<<")"<<endl; + } + else { + for (int i=0;i<w*h*3;i++){ + //calculate with tables + RGBdata[i]=pixels.add[RGBdata[i]][other.RGBdata[i]]; + } + } + return *this; + } + Image & operator*=(const Image &other) { + if (other.w!=w||other.h!=h) { + cerr<<"Rotor: cannot multiply images with different sizes! (wanted "<<w<<"x"<<h<<", got "<<other.w<<"x"<<other.h<<")"<<endl; + } + else { + for (int i=0;i<w*h*3;i++){ + //calculate with tables + uint8_t p1=RGBdata[i]; + uint8_t p2=other.RGBdata[i]; + RGBdata[i]=pixels.multiply[RGBdata[i]][other.RGBdata[i]]; + } + } + return *this; + } + Image & add_wrap(const Image &other) { + if (other.w!=w||other.h!=h) { + cerr<<"Rotor: cannot add images with different sizes! (wanted "<<w<<"x"<<h<<", got "<<other.w<<"x"<<other.h<<")"<<endl; + } + else { + for (int i=0;i<w*h*3;i++){ + //creates rainbow overload + RGBdata[i]=(unsigned char)(((int)other.RGBdata[i]+(int)RGBdata[i])); + } + } + return *this; + } + //scalar operations allocate a new image. + //maybe this could not be the case if the data is owned by this image? + //need to look into auto_ptr + Image & operator*=(const float &amount) { + uint8_t *LUT=new uint8_t[256]; + for (int i=0;i<256;i++) { + LUT[i]=(uint8_t)min(0xFF,max(0,(int)(i*amount))); + } + for (int i=0;i<w*h*3;i++){ + //calculate with table + RGBdata[i]=LUT[RGBdata[i]]; + } + delete[] LUT; + return *this; + } + Image * operator*(const float &amount) { + Image *other=new Image(w,h); + uint8_t *LUT=new uint8_t[256]; + for (int i=0;i<256;i++) { + LUT[i]=(uint8_t)min(0xFF,max(0,(int)(i*amount))); + } + for (int i=0;i<w*h*3;i++){ + other->RGBdata[i]=LUT[RGBdata[i]]; + } + delete[] LUT; + return other; + } + Image * operator+(const float &amount) { + Image *other=new Image(w,h); + uint8_t *LUT=new uint8_t[256]; + for (int i=0;i<256;i++) { + LUT[i]=(uint8_t)min(0xFF,max(0,(int)(i+(amount*255.0f)))); + } + for (int i=0;i<w*h*3;i++){ + other->RGBdata[i]=LUT[RGBdata[i]]; + } + delete[] LUT; + return other; + } + Image * operator-(const float &amount) { + Image *other=new Image(w,h); + uint8_t *LUT=new uint8_t[256]; + for (int i=0;i<256;i++) { + LUT[i]=(uint8_t)min(0xFF,max(0,(int)(i-(amount*255.0f)))); + } + for (int i=0;i<w*h*3;i++){ + other->RGBdata[i]=LUT[RGBdata[i]]; + } + delete[] LUT; + return other; + } + Image * operator/(const float &amount) { + Image *other=new Image(w,h); + uint8_t *LUT=new uint8_t[256]; + for (int i=0;i<256;i++) { + LUT[i]=(uint8_t)min(0xFF,max(0,(int)(i/amount))); + } + for (int i=0;i<w*h*3;i++){ + other->RGBdata[i]=LUT[RGBdata[i]]; + } + delete[] LUT; + return other; + } + uint8_t *RGBdata; + uint8_t *Adata; + uint16_t *Zdata; + int h,w; + bool ownsRGBdata,ownsAdata,ownsZdata; //better done through auto_ptr? + }; +}
\ No newline at end of file diff --git a/rotord/rotor.cpp b/rotord/rotor.cpp index 12741f9..33b8597 100755 --- a/rotord/rotor.cpp +++ b/rotord/rotor.cpp @@ -28,6 +28,7 @@ Node_factory::Node_factory(){ add_type("random",new Random()); add_type("blend",new Blend()); add_type("mirror",new Mirror()); + add_type("monochrome",new Monochrome()); } bool Signal_input::connect(Signal_node* source) { diff --git a/rotord/rotor.h b/rotord/rotor.h index 4e22f1f..ae17e9a 100755 --- a/rotord/rotor.h +++ b/rotord/rotor.h @@ -7,6 +7,8 @@ TODO - parameter class that automatically links variable to correctly named inpu TODO - use try.. catch and dynamic_cast to verify node connections rather than checking 'type' tag TODO - put the boilerplate code for checking inputs into the base class, finally call checked_output + +http://stackoverflow.com/questions/5261658/how-to-seek-in-ffmpeg-c-c */ #include <unordered_map> @@ -66,6 +68,7 @@ extern "C" { #include "xmlIO.h" #include "utils.h" //fequal #include "libavwrapper.h" +#include "image.h" namespace Rotor { #define IDLE 0 @@ -115,34 +118,6 @@ namespace Rotor { AVPacket packet; }; - class pixeltables{ - //handy pixel arithmetic lookup tables as nested arrays - //so - pixels.add[0x78][0x66]; will give the precalculated result of adding with saturation - public: - pixeltables(){ - add=new uint8_t*[256]; - multiply=new uint8_t*[256]; - for (int i=0;i<256;i++){ - add[i]=new uint8_t[256]; - multiply[i]=new uint8_t[256]; - for (int j=0;j<256;j++){ - add[i][j]=(uint8_t)min(i+j,0xFF); - multiply[i][j]=(uint8_t)((((float)i)/255.0f)*(((float)j)/255.0f)*255.0f); - } - } - } - virtual ~pixeltables(){ - for (int i=0;i<256;i++){ - delete[] add[i]; - delete[] multiply[i]; - } - delete[] add; - delete[] multiply; - } - uint8_t **add; - uint8_t **multiply; - }; - static pixeltables pixels; class Time_spec{ public: Time_spec(){}; @@ -187,173 +162,7 @@ namespace Rotor { } uint8_t r,g,b; }; - class Image{ - public: - Image(){ - zero(); - }; - Image(int _w,int _h){ - zero(); - setup(_w,_h); - }; - ~Image() { - free(); - }; - void free(){ - if (RGBdata&&ownsRGBdata) delete[] RGBdata; - if (Adata&&ownsAdata) delete[] Adata; - if (Zdata&&ownsZdata) delete[] Zdata; - zero(); - } - void zero(){ - RGBdata=nullptr; - Adata=nullptr; - Zdata=nullptr; - w=0; - h=0; - ownsRGBdata=ownsAdata=ownsZdata=false; - } - bool setup(int _w,int _h){ //set up with internal data - if (w!=_w||h!=_h||!ownsRGBdata||!ownsAdata||!ownsZdata){ - free(); - w=_w; - h=_h; - RGBdata=new uint8_t[w*h*3]; - Adata=new uint8_t[w*h]; - Zdata=new uint16_t[w*h]; - ownsRGBdata=ownsAdata=ownsZdata=true; - return true; - } - else return false; - } - bool setup_fromRGB(int _w,int _h,uint8_t *pRGBdata){ //possibility of just resetting pointer? - if (w!=_w||h!=_h||ownsRGBdata||!ownsAdata||!ownsZdata){ - free(); - w=_w; - h=_h; - RGBdata=pRGBdata; - Adata=new uint8_t[w*h]; - Zdata=new uint16_t[w*h]; - ownsRGBdata=false; - ownsAdata=ownsZdata=true; - return true; - } - return false; - } - Image* clone(){ - Image *t=new Image(w,h); - for (int i=0;i<w*h*3;i++) { - t->RGBdata[i]=RGBdata[i]; - } - return t; - } - Image & operator+=(const Image &other) { - if (other.w!=w||other.h!=h) { - cerr<<"Rotor: cannot add images with different sizes! (wanted "<<w<<"x"<<h<<", got "<<other.w<<"x"<<other.h<<")"<<endl; - } - else { - for (int i=0;i<w*h*3;i++){ - //calculate with tables - RGBdata[i]=pixels.add[RGBdata[i]][other.RGBdata[i]]; - } - } - return *this; - } - Image & operator*=(const Image &other) { - if (other.w!=w||other.h!=h) { - cerr<<"Rotor: cannot multiply images with different sizes! (wanted "<<w<<"x"<<h<<", got "<<other.w<<"x"<<other.h<<")"<<endl; - } - else { - for (int i=0;i<w*h*3;i++){ - //calculate with tables - uint8_t p1=RGBdata[i]; - uint8_t p2=other.RGBdata[i]; - RGBdata[i]=pixels.multiply[RGBdata[i]][other.RGBdata[i]]; - } - } - return *this; - } - Image & add_wrap(const Image &other) { - if (other.w!=w||other.h!=h) { - cerr<<"Rotor: cannot add images with different sizes! (wanted "<<w<<"x"<<h<<", got "<<other.w<<"x"<<other.h<<")"<<endl; - } - else { - for (int i=0;i<w*h*3;i++){ - //creates rainbow overload - RGBdata[i]=(unsigned char)(((int)other.RGBdata[i]+(int)RGBdata[i])); - } - } - return *this; - } - //scalar operations allocate a new image. - //maybe this could not be the case if the data is owned by this image? - //need to look into auto_ptr - Image & operator*=(const float &amount) { - uint8_t *LUT=new uint8_t[256]; - for (int i=0;i<256;i++) { - LUT[i]=(uint8_t)min(0xFF,max(0,(int)(i*amount))); - } - for (int i=0;i<w*h*3;i++){ - //calculate with table - RGBdata[i]=LUT[RGBdata[i]]; - } - delete[] LUT; - return *this; - } - Image * operator*(const float &amount) { - Image *other=new Image(w,h); - uint8_t *LUT=new uint8_t[256]; - for (int i=0;i<256;i++) { - LUT[i]=(uint8_t)min(0xFF,max(0,(int)(i*amount))); - } - for (int i=0;i<w*h*3;i++){ - other->RGBdata[i]=LUT[RGBdata[i]]; - } - delete[] LUT; - return other; - } - Image * operator+(const float &amount) { - Image *other=new Image(w,h); - uint8_t *LUT=new uint8_t[256]; - for (int i=0;i<256;i++) { - LUT[i]=(uint8_t)min(0xFF,max(0,(int)(i+(amount*255.0f)))); - } - for (int i=0;i<w*h*3;i++){ - other->RGBdata[i]=LUT[RGBdata[i]]; - } - delete[] LUT; - return other; - } - Image * operator-(const float &amount) { - Image *other=new Image(w,h); - uint8_t *LUT=new uint8_t[256]; - for (int i=0;i<256;i++) { - LUT[i]=(uint8_t)min(0xFF,max(0,(int)(i-(amount*255.0f)))); - } - for (int i=0;i<w*h*3;i++){ - other->RGBdata[i]=LUT[RGBdata[i]]; - } - delete[] LUT; - return other; - } - Image * operator/(const float &amount) { - Image *other=new Image(w,h); - uint8_t *LUT=new uint8_t[256]; - for (int i=0;i<256;i++) { - LUT[i]=(uint8_t)min(0xFF,max(0,(int)(i/amount))); - } - for (int i=0;i<w*h*3;i++){ - other->RGBdata[i]=LUT[RGBdata[i]]; - } - delete[] LUT; - return other; - } - uint8_t *RGBdata; - uint8_t *Adata; - uint16_t *Zdata; - int h,w; - bool ownsRGBdata,ownsAdata,ownsZdata; //better done through auto_ptr? - }; + class Render_status{ public: int id; @@ -1317,6 +1126,35 @@ namespace Rotor { Image *image; //is an image generator int mode; }; + class Monochrome: public Image_node { + public: + Monochrome(){}; + Monochrome(map<string,string> &settings) { + base_settings(settings); + }; + ~Monochrome(){ + }; + Monochrome* clone(map<string,string> &_settings) { return new Monochrome(_settings);}; + Image *output(const Frame_spec &frame){ + if (image_inputs.size()) { + if (image_inputs[0]->connection){ + Image *other=(((Image_node*)image_inputs[0]->connection)->get_output(frame)); + image.setup(other->w,other->h); + for (int i=0;i<image.w;i++){ + for (int j=0;j<image.h;j++){ + uint8_t luma=0; + for (int l=0;l<3;l++) luma+=pixels.mono_weights[l][other->RGBdata[(((j*image.w)+i)*3)+l]]; + for (int k=0;k<3;k++) image.RGBdata[(((j*image.w)+i)*3)+k]=luma; + } + } + return ℑ + } + } + return nullptr; + } + private: + Image image; + }; //------------------------------------------------------------------- class Node_factory{ public: diff --git a/rotord/rotord.cpp b/rotord/rotord.cpp index b46cebc..15210e9 100755 --- a/rotord/rotord.cpp +++ b/rotord/rotord.cpp @@ -260,7 +260,7 @@ int RotorServer::main(const std::vector<std::string>& args){ xmlIO xml; if(xml.loadFile("settings.xml") ){ - port=xml.getAttribute("Rotor","port",9980,0); + port=xml.getAttribute("Rotor","port",9000,0); } else cerr<<"Rotord: settings.xml not found, using defaults"<<endl; |
