#include 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 cvImage{ public: bool setup(int _w,int _h){ //set up with internal data cv::Mat mat =cv::Mat(_w, _h, CV_8UC1); //is this goint to save time or cost it in the long run? //wrap cv::Mat or use it directly? //its reference counted etc.. could save a lot of headaches /* 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; */ return false; } uint8_t *RGBdata; uint8_t *Adata; uint16_t *Zdata; int h,w; bool ownsRGBdata,ownsAdata,ownsZdata; //better done through auto_ptr? }; 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;iRGBdata[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 "<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? }; }