Logo Search packages:      
Sourcecode: hitop version File versions

color.cc

#ifndef __pluginh__
  #include "../plugin.h"
#endif
#ifndef __errorh__
  #include "../error.h"
#endif
#ifndef __polytypeh__
  #include "../polytype.h"
#endif

#include <cmath>
#include <string>
#include <vector>
#include <cstdio>
#include <map>

class dsoColorMod :public Plugin{
public:
  dsoColorMod();
  virtual void Init();
private:
  static void WEBSAFE(__HITOPFUNC__);
  static void SMARTSAFE(__HITOPFUNC__);
  static void ROUND(__HITOPFUNC__);
  static void BRIGHTEN(__HITOPFUNC__);
  static void BRIGHTENABS(__HITOPFUNC__);
  static void DARKEN(__HITOPFUNC__);
  static void DARKENABS(__HITOPFUNC__);
  static void INTERPOLATE(__HITOPFUNC__);
  static void ROTATE(__HITOPFUNC__);
  static void CONTRAST(__HITOPFUNC__);
  static void SATURATE(__HITOPFUNC__);
  static void SATURATEABS(__HITOPFUNC__);
  static void DISTANCE(__HITOPFUNC__);
};

static dsoColorMod initmodule;

dsoColorMod::dsoColorMod() {
  RegisterPlugin(string("color"),1);
}

void dsoColorMod::Init(){
  RegisterFunction("WEBSAFE",&dsoColorMod::WEBSAFE);
  RegisterFunction("SMARTSAFE",&dsoColorMod::SMARTSAFE);
  RegisterFunction("ROUND",&dsoColorMod::ROUND);
  RegisterFunction("BRIGHTEN",&dsoColorMod::BRIGHTEN);
  RegisterFunction("BRIGHTENABS",&dsoColorMod::BRIGHTENABS);
  RegisterFunction("DARKEN",&dsoColorMod::DARKEN);
  RegisterFunction("DARKENABS",&dsoColorMod::DARKENABS);
  RegisterFunction("INTERPOLATE",&dsoColorMod::INTERPOLATE);
  RegisterFunction("ROTATE",&dsoColorMod::ROTATE);
  RegisterFunction("CONTRAST",&dsoColorMod::CONTRAST);
  RegisterFunction("SATURATE",&dsoColorMod::SATURATE);
  RegisterFunction("SATURATEABS",&dsoColorMod::SATURATEABS);
  RegisterFunction("DISTANCE",&dsoColorMod::DISTANCE);
}

static void StringToRGB(const string& col,int& r,int& g,int& b){
  unsigned int ur,ug,ub;
  sscanf(col.c_str(),"#%02X%02X%02X",&ur,&ug,&ub);
  r=ur; g=ug; b=ub;
}

static inline void CropRange(int& value,int minimum,int maximum){
  value=max(min(value,maximum),minimum);
}

static void RGBToString(int r,int g,int b,string& col){
  CropRange(r,0,255);
  CropRange(g,0,255);
  CropRange(b,0,255);
  char buff[8];
  sprintf(buff,"#%02X%02X%02X",r,g,b);
  col=buff;
}

static void RGBToHSV(int r,int g,int b,int& h,int& s,int& v){
  int maxval=max(r,max(g,b)),minval=min(r,min(g,b)),delta=maxval-minval,half=delta/2;
  v=maxval;
  if(maxval!=0) s=(delta*255)/maxval; else s=0;
  if(s==0){
    h=0;
  }else{
    if(r==maxval){
      h=((g-b)*60+half)/delta;
    }else if(g==maxval){
      h=120+((b-r)*60+half)/delta;
    }else{
      h=240+((r-g)*60+half)/delta;
    }
    if(h<0) h+=360;
  }
}

static void HSVToXYZ(int h,int s,int v,int& x,int& y,int& z){
  double hrad=h/57.295779513082320876798154814105;
  double scale=s*v/255.0;
  x=int(cos(hrad)*scale);
  y=int(sin(hrad)*scale);
  z=(v*3)/2;
}

static inline int RGBToY(int r,int g,int b){
  return (r*77+g*150+b*29)/256;
}

static inline void RGBToYUV(int r,int g,int b,int& y,int& u,int& v){
  y=((66*r)+(129*g)+(25*b))/256+16;
  u=((-38*r)-(74*g)+(112*b))/256+128;
  v=((112*r)-(94*g)-(18*b))/256+128;
}

static inline void YUVToRGB(int y,int u,int v,int& r,int& g,int& b){
  r=(298*(y-16)+409*(v-128))/256;
  g=(298*(y-16)-208*(v-128)-100*(u-128))/256;
  b=(298*(y-16)+517*(u-128))/256;
  CropRange(r,0,255);
  CropRange(g,0,255);
  CropRange(b,0,255);
}

static inline void Assign(int& a,int& b,int& c,int d,int e,int f){
  a=d; b=e; c=f;
}

static void HSVToRGB(int h,int s,int v,int& r,int& g,int& b){
  while(h<0) h+=360;
  h%=360;
  int i=h/60,f=h-i*60;
  int p=(v*(255-s)+128)/255;
  int q=(v*(255-(s*f+30)/60)+128)/255;
  int t=(v*(255-(s*(60-f)+30)/60)+128)/255;
  switch(i){
  case 0: Assign(r,g,b,v,t,p); break;
  case 1: Assign(r,g,b,q,v,p); break;
  case 2: Assign(r,g,b,p,v,t); break;
  case 3: Assign(r,g,b,p,q,v); break;
  case 4: Assign(r,g,b,t,p,v); break;
  case 5: Assign(r,g,b,v,p,q); break;
  }
}

static int Nearest(int n){
  return ((n+25)/51)*51;
}

void dsoColorMod::WEBSAFE(__HITOPFUNC__){
  if(params.size()!=0) Error(cur,"WEBSAFE",e_ParamNone);
  int r,g,b;
  StringToRGB(data,r,g,b);
  r=Nearest(r);
  g=Nearest(g);
  b=Nearest(b);
  RGBToString(r,g,b,data.AsString());
}

void dsoColorMod::SMARTSAFE(__HITOPFUNC__){
  if(params.size()!=0) Error(cur,"SMARTSAFE",e_ParamNone);
  int r,g,b;
  StringToRGB(data,r,g,b);
  map<int,int> twist;
  twist.insert(make_pair(r,0));
  twist.insert(make_pair(g,0));
  twist.insert(make_pair(b,0));
  int from=255,to=255;
  for(map<int,int>::reverse_iterator i=twist.rbegin();i!=twist.rend();++i){
    i->second=Nearest((i->first*to)/from);
    from=i->first;
    to=i->second;
  }
  r=twist[r];
  g=twist[g];
  b=twist[b];
  RGBToString(r,g,b,data.AsString());
}

void dsoColorMod::ROUND(__HITOPFUNC__){
  if(params.size()!=1) Error(cur,"ROUND",e_ParamOne);
  int r,g,b,rr=0,gr=0,br=0;
  StringToRGB(params[0].AsString(),rr,gr,br);
  rr=min(255,max(rr,1));
  gr=min(255,max(gr,1));
  br=min(255,max(br,1));
  StringToRGB(data,r,g,b);
  r=((r+rr/2)/rr)*rr;
  g=((g+gr/2)/rr)*rr;
  b=((b+br/2)/br)*br;
  RGBToString(r,g,b,data.AsString());
}

void dsoColorMod::BRIGHTEN(__HITOPFUNC__){
  if(params.size()!=1) Error(cur,"BRIGHTEN",e_ParamOne);
  int r,g,b,v=params[0].AsInt();
  StringToRGB(data,r,g,b);
  r=r+((255-r)*v+50)/100;
  g=g+((255-g)*v+50)/100;
  b=b+((255-b)*v+50)/100;
  RGBToString(r,g,b,data.AsString());
}

void dsoColorMod::BRIGHTENABS(__HITOPFUNC__){
  if(params.size()!=1) Error(cur,"BRIGHTEN",e_ParamOne);
  int r,g,b,v=params[0].AsInt();
  StringToRGB(data,r,g,b);
  r+=v;
  CropRange(r,0,255);
  g+=v;
  CropRange(g,0,255);
  b+=v;
  CropRange(b,0,255);
  RGBToString(r,g,b,data.AsString());
}

void dsoColorMod::DARKEN(__HITOPFUNC__){
  if(params.size()!=1) Error(cur,"DARKEN",e_ParamOne);
  int r,g,b,v=params[0].AsInt();
  StringToRGB(data,r,g,b);
  r=(r*(100-v)+50)/100;
  g=(g*(100-v)+50)/100;
  b=(b*(100-v)+50)/100;
  RGBToString(r,g,b,data.AsString());
}

void dsoColorMod::DARKENABS(__HITOPFUNC__){
  if(params.size()!=1) Error(cur,"DARKEN",e_ParamOne);
  int r,g,b,v=params[0].AsInt();
  StringToRGB(data,r,g,b);
  r-=v;
  CropRange(r,0,255);
  g-=v;
  CropRange(g,0,255);
  b-=v;
  CropRange(b,0,255);
  RGBToString(r,g,b,data.AsString());
}

void dsoColorMod::INTERPOLATE(__HITOPFUNC__){
  int v=50,size=params.size();
  if(size==2){
    v=params[1].AsInt();
  }else if(size!=1){
    Error(cur,"INTERPOLATE",e_ParamWrong);
  }
  int r,g,b,rd,gd,bd;
  StringToRGB(params[0].AsString(),rd,gd,bd);
  StringToRGB(data,r,g,b);
  r=r+((rd-r)*v+50)/100;
  g=g+((gd-g)*v+50)/100;
  b=b+((bd-b)*v+50)/100;
  RGBToString(r,g,b,data.AsString());
}

void dsoColorMod::ROTATE(__HITOPFUNC__){
  if(params.size()!=1) Error(cur,"ROTATE",e_ParamOne);
  int r,g,b,h=0,s=0,v=0,y1,y2,ang=params[0].AsInt();
  StringToRGB(data,r,g,b);
  RGBToHSV(r,g,b,h,s,v);
  y1=RGBToY(r,g,b);
  h+=ang;
  HSVToRGB(h,s,v,r,g,b);
  y2=RGBToY(r,g,b);
  if(y2!=0){
    r=(r*y1)/y2;
    g=(g*y1)/y2;
    b=(b*y1)/y2;
    CropRange(r,0,255);
    CropRange(g,0,255);
    CropRange(b,0,255);
  }
  RGBToString(r,g,b,data.AsString());
}

void dsoColorMod::CONTRAST(__HITOPFUNC__){
  if(params.size()!=0) Error(cur,"CONTRAST",e_ParamNone);
  int r,g,b;
  StringToRGB(data,r,g,b);
  int y=(299*r+587*g+114*b)/1000;
  if(y<128){
    data="#FFFFFF";
  }else{
    data="#000000";
  }
}

void dsoColorMod::SATURATE(__HITOPFUNC__){
  if(params.size()!=1) Error(cur,"SATURATE",e_ParamOne);
  int dist=params[0].AsInt();
  int r,g,b,h,s,v;
  StringToRGB(data,r,g,b);
  RGBToHSV(r,g,b,h,s,v);
  if(dist<0){
    s=(s*(100+dist))/100;
  }else{
    s=s+((255-s)*dist)/100;
  }
  HSVToRGB(h,s,v,r,g,b);
  RGBToString(r,g,b,data.AsString());
}

void dsoColorMod::SATURATEABS(__HITOPFUNC__){
  if(params.size()!=1) Error(cur,"SATURATE",e_ParamOne);
  int dist=params[0].AsInt();
  int r,g,b,h,s,v;
  StringToRGB(data,r,g,b);
  RGBToHSV(r,g,b,h,s,v);
  s+=dist;
  CropRange(s,0,255);
  HSVToRGB(h,s,v,r,g,b);
  RGBToString(r,g,b,data.AsString());
}

void dsoColorMod::DISTANCE(__HITOPFUNC__){
  if(params.size()!=1) Error(cur,"DISTANCE",e_ParamOne);
  int r1,g1,b1,r2,g2,b2,h1,s1,v1,h2,s2,v2,x1,y1,z1,x2,y2,z2;
  StringToRGB(data,r1,g1,b1);
  StringToRGB(params[0].AsString(),r2,g2,b2);
  RGBToHSV(r1,g1,b1,h1,s1,v1);
  RGBToHSV(r2,g2,b2,h2,s2,v2);
  HSVToXYZ(h1,s1,v1,x1,y1,z1);
  HSVToXYZ(h2,s2,v2,x2,y2,z2);
  int dx=x1-x2,dy=y1-y2,dz=z1-z2;
  data.AsInt()=(dx*dx)+(dy*dy)+(dz*dz);
}

Generated by  Doxygen 1.6.0   Back to index