#ifndef ROTOR_CVIMAGE #define ROTOR_CVIMAGE #include #include #include #include //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]; overlay=new uint8_t*[256]; min=new uint8_t*[256]; max=new uint8_t*[256]; for (int i=0;i<256;i++){ add[i]=new uint8_t[256]; multiply[i]=new uint8_t[256]; overlay[i]=new uint8_t[256]; min[i]=new uint8_t[256]; max[i]=new uint8_t[256]; for (int j=0;j<256;j++){ add[i][j]=(uint8_t)std::min(i+j,0xFF); multiply[i][j]=(uint8_t)(((double)i)*(((double)j)/255.0)); overlay[i][j]=j<128?(uint8_t)((i*j)>>7):255-(((0xFF-i)*(0xFF-j))>>7); min[i][j]=ji?j:i; } } mono_weights=new uint8_t*[3]; double 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)(((double)j)*weights[i]); } } } virtual ~pixeltables(){ for (int i=0;i<256;i++){ delete[] add[i]; delete[] multiply[i]; delete[] overlay[i]; delete[] min[i]; delete[] max[i]; } delete[] add; delete[] multiply; delete[] overlay; delete[] min; delete[] max; for (int i=0;i<3;i++) { delete[] mono_weights[i]; } delete[] mono_weights; } uint8_t **add; uint8_t **multiply; uint8_t **overlay; uint8_t **mono_weights; uint8_t **max; uint8_t **min; }; 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; rgb.release(); alpha.release(); zero(); } void zero(){ RGBdata=nullptr; Adata=nullptr; Zdata=nullptr; w=0; h=0; ownsRGBdata=ownsAdata=ownsZdata=false; } //space out to 32 bit RGB padding for cairo void convert24(); void convert32(); int getStride(){ return w*3; } bool clear(){ rgb.setTo(0); return true; }; bool setup(int _w,int _h){ //set up with internal data if ((w!=_w)|(h!=_h)){ free(); rgb.create(_h,_w,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 read_file(std::string &filename){ rgb=cv::imread(filename,CV_LOAD_IMAGE_COLOR); if (rgb.empty()) return false; RGBdata=rgb.data; ownsRGBdata=false; w=rgb.rows; h=rgb.cols; return true; } bool setup_fromRGB(int _w,int _h,uint8_t *pRGBdata,int linepadding=0){ //here the data belongs to libavcodec or other //could move to using cv::Mat there also and just passing cv:Mat over //linepadding causes crash, but it doesn't seem to be necessary // Mat::Mat(int rows, int cols, int type, void* data, size_t step=AUTO_STEP) rgb=cv::Mat(_h,_w,CV_8UC3,pRGBdata,(_w*3)+linepadding); //std::cerr<<"created cv::Mat with step= "<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; //always just deallocate cv::Mat from stack /* for (int i=0;iRGBdata[i]=RGBdata[i]; } */ return t; } Image & operator=(const Image &other); //believe these still work, don't know if these optimisations are better than opencvs.. Image & operator+=(const Image &other); Image & operator*=(const Image &other); Image & operator^=(const Image &other); Image & alpha_blend(const Image &other); Image & alpha_blend_cv(const Image &other); Image & alpha_merge(const Image &other); Image & alpha_from_cv(cv::Mat &other); Image & add_wrap(const Image &other); Image & divide_wrap(const Image &other); Image & overlay(const Image &other); Image & min(const Image &other); Image & max(const Image &other); Image & operator*=(const double &amount); Image & operator+=(const double &amount); Image & operator-=(const double &amount); Image & operator/=(const double &amount); Image * operator*(const double &amount); Image * operator+(const double &amount); Image * operator-(const double &amount); Image * operator/(const double &amount); uint8_t *RGBdata; uint8_t *Adata; uint16_t *Zdata; int h,w; bool ownsRGBdata,ownsAdata,ownsZdata; //better done through auto_ptr? //making the interface for mip mapping //should reduce in powers of 2 // cv::Mat rgb; cv::Mat alpha; //store a library of mipmaps std::unordered_map mipmaps; cv::Mat& get_mipmap(int level); }; } #endif