summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--rotord/image.h211
-rwxr-xr-xrotord/rotor.cpp1
-rwxr-xr-xrotord/rotor.h228
-rwxr-xr-xrotord/rotord.cpp2
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 &image;
+ }
+ }
+ 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;