///////////////////////////////////////////////////////////////////////////// // Name: ImageProc.cpp // Purpose: Image processing functions. // Author: Alex Thuering // Created: 18.06.2003 // RCS-ID: $Id: ImageProc.cpp,v 1.2 2006/12/06 14:08:03 ntalex Exp $ // Copyright: (c) Alex Thuering // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// #include "ImageProc.h" #include ////////////////////////////////////////////////////////////////////////////// /////////////////////////////// Adjust /////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// typedef void wxAdjustColourFunc( unsigned char& r, unsigned char& g, unsigned char& b, void* param); void wxAdjustColours(wxImage& img, wxRect rect, void* arg, wxAdjustColourFunc* func) { int w = img.GetWidth(); int h = img.GetHeight(); int k = wxMax(rect.GetLeft(),0); rect.width += rect.x-k; rect.x = k; //rect.SetLeft(k); k = wxMax(rect.GetTop(),0); rect.height += rect.y-k; rect.y = k; //rect.SetTop(k); rect.SetRight(wxMin(rect.GetRight(),w-1)); rect.SetBottom(wxMin(rect.GetBottom(),h-1)); unsigned char* data = img.GetData() + rect.GetTop()*w*3; if (img.HasMask()) { unsigned char maskRed = img.GetMaskRed(); unsigned char maskGreen = img.GetMaskGreen(); unsigned char maskBlue = img.GetMaskBlue(); for (int y=rect.GetTop(); y<=rect.GetBottom(); y++) { data += rect.GetLeft()*3; for (int x=rect.GetLeft(); x<=rect.GetRight(); x++) { if (maskRed != *data || maskGreen != *(data+1) || maskBlue != *(data+2)) (*func)(*data, *(data+1), *(data+2), arg); data += 3; } data += (w-rect.GetRight()-1)*3; } } else { for (int y=rect.GetTop(); y<=rect.GetBottom(); y++) { data += rect.GetLeft()*3; for (int x=rect.GetLeft(); x<=rect.GetRight(); x++) { (*func)(*data, *(data+1), *(data+2), arg); data += 3; } data += (w-rect.GetRight()-1)*3; } } } ////////////////////////////////////////////////////////////////////////////// ///////////////////////////// Brightness ///////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// void wxAdjustBrightness(wxImage& img, char n) { wxAdjustBrightness(img, wxRect(0,0,img.GetWidth(),img.GetHeight()), n); } void wxAdjustBrightnessFunc(unsigned char& r, unsigned char& g, unsigned char& b, void* arg) { wxAdjustBrightness(r, g, b, *((char*) arg)); } void wxAdjustBrightness(wxImage& img, wxRect rect, char n) { wxAdjustColours(img, rect, &n, &wxAdjustBrightnessFunc); } ////////////////////////////////////////////////////////////////////////////// ////////////////////////////// To colour ///////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// void wxAdjustToColour(wxImage& img, wxColour colour) { wxAdjustToColour(img, wxRect(0,0,img.GetWidth(),img.GetHeight()), colour); } void wxAdjustToColourFunc(unsigned char& r, unsigned char& g, unsigned char& b, void* arg) { wxAdjustToColour(r, g, b, *((wxColour*) arg)); } void wxAdjustToColour(wxImage& img, wxRect rect, wxColour colour) { wxAdjustColours(img, rect, &colour, &wxAdjustToColourFunc); } ////////////////////////////////////////////////////////////////////////////// ///////////////////////////// Contrast ///////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// wxArrayInt contrastTable; void InitializateContrastTable() { if (contrastTable.IsEmpty()) for (int i=0; i<256; i++) { double brightness = double(i)/255; contrastTable.Add(int( 1000*((sin(3.1415*(brightness-0.5))+1)/2-brightness))); } } // Adjust contrast: dark color become darker, light color become lighter. inline void wxAdjustContrast( unsigned char& r, unsigned char& g, unsigned char& b, char n) { int brightness = wxGetBrightness(r,g,b); wxAdjustBrightness(r,g,b, contrastTable[brightness]*n/100); } void wxAdjustContrast(wxImage& img, char n) { wxAdjustContrast(img, wxRect(0,0,img.GetWidth(),img.GetHeight()), n); } void wxAdjustContrast(wxImage& img, wxRect rect, char n) { InitializateContrastTable(); unsigned char* data = img.GetData() + rect.GetTop()*img.GetWidth()*3; for (int y=rect.GetTop(); y<=rect.GetBottom(); y++) { data += rect.GetLeft()*3; for (int x=rect.GetLeft(); x<=rect.GetRight(); x++) { wxAdjustContrast(*data, *(data+1), *(data+2), n); data += 3; } data += (img.GetWidth()-rect.GetRight()-1)*3; } } ////////////////////////////////////////////////////////////////////////////// ///////////////////////// Convert functions ////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// // Convert RGB to HSL void RGB2HSL(const wxColour colour, double& hue, double& saturation, double& luminosity) { double r = (double) colour.Red()/255; double g = (double) colour.Green()/255; double b = (double) colour.Blue()/255; double max = wxMax(r, wxMax(g,b)); double min = wxMin(r, wxMin(g,b)); hue = 0; saturation = 0; luminosity = (min+max)/2; double delta=max-min; if (delta == 0) return; saturation = delta/((luminosity <= 0.5) ? (min+max) : (2-max-min)); if (r == max) hue = (g == min ? 5+(max-b)/delta : 1-(max-g)/delta); else if (g == max) hue = (b == min ? 1+(max-r)/delta : 3-(max-b)/delta); else hue = (r == min ? 3+(max-g)/delta : 5-(max-r)/delta); hue /= 6; } // Convert HSL to RGB wxColour HSL2RGB(double hue, double saturation, double luminosity) { wxColour colour; if (saturation == 0) { int c = (int) (255*luminosity+0.5); colour.Set(c, c, c); return colour; } double v=(luminosity <= 0.5) ? (luminosity*(1+saturation)) : (luminosity+saturation-luminosity*saturation); double y=2*luminosity-v; double x=y+(v-y)*(6*hue-floor(6*hue)); double z=v-(v-y)*(6*hue-floor(6*hue)); double r,g,b; switch ((int) (6*hue)) { case 0: r=v; g=x; b=y; break; case 1: r=z; g=v; b=y; break; case 2: r=y; g=v; b=x; break; case 3: r=y; g=z; b=v; break; case 4: r=x; g=y; b=v; break; case 5: r=v; g=y; b=z; break; default: r=v; g=x; b=y; break; } colour.Set((int) (255*r+0.5), (int) (255*g+0.5), (int) (255*b+0.5)); return colour; }