#include #include using namespace std; //converting to use a cv image... //cv::Mat supports most of what we want here //need to think //http://answers.opencv.org/question/8202/using-external-image-data-in-a-cvmat/ //all access to the image is presently through a pointer to the data //cv::Mat supports this //how will copying work? //Rotor::Image will contain a cv::Mat object which may own its data or inherit it //cv::Mat should take care of reference counting //can cv::Mat 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 rgb.create(_w,_h,CV_8UC3); RGBdata=rgb.data; //can move to use the bare pointer eventually ownsRGBdata=false; //will not be necessary w=_w; h=_h; return true; /* 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){ //here the data belongs to libavcodec or other //could move to using cv::Mat there also and just passing cv:Mat over rgb=cv::Mat(_w,_h,CV_8UC3,pRGBdata); RGBdata=rgb.data; //can move to use the bare pointer eventually ownsRGBdata=false; //will not be necessary w=_w; h=_h; return true; /* 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; */ } bool setup_fromMat(cv::Mat& othermat){ //here the mat belongs to another Image object rgb=cv::Mat(othermat); RGBdata=rgb.data; //can move to use the bare pointer eventually ownsRGBdata=false; //will not be necessary w=rgb.rows; h=rgb.cols; return true; } Image* clone(){ Image *t=new Image(); t->rgb=rgb.clone(); t->w=w; t->h=h; t->RGBdata=t->rgb.data; //can move to use the bare pointer eventually t->ownsRGBdata=false; //will not be necessary /* for (int i=0;iRGBdata[i]=RGBdata[i]; } */ return t; } //believe these still work, don't know if these optimisations are better than opencvs.. Image & operator+=(const Image &other) { if (other.w!=w||other.h!=h) { cerr<<"Rotor: cannot add images with different sizes! (wanted "<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;iRGBdata[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;iRGBdata[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;iRGBdata[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? cv::Mat rgb; }; }