00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00026 #include <utility>
00027 #include "Image.h"
00028 #include "SFCPath.h"
00029 #include "SFCPathFactory.h"
00030 #include "VGexp.h"
00031 #include "VGexpSpec.h"
00032 
00033 namespace halftoner
00034 {
00035 
00036 
00037 
00038 
00039 
00040    VGexp::VGexp() throw()
00041    {
00042    
00043    }
00044 
00045 
00046 
00047 
00048 
00049 
00050    VGexp::~VGexp()
00051    {
00052    
00053    }
00054 
00055 
00056 
00057 
00058 
00059 
00060    Image* VGexp::halftone(const Image& source, const HalftonerSpec* spec) throw (std::invalid_argument)
00061    {
00062    
00063       const int width = source.getWidth();
00064       const int height = source.getHeight();
00065    
00066       if (width != height)
00067       {
00068          string s("image is not square");
00069          throw std::invalid_argument(s);
00070       }
00071 
00072    
00073       const VGexpSpec* vgspec = dynamic_cast<const VGexpSpec*>(spec);
00074       const int cluster = vgspec->getClusterSize();
00075       const float err1 = vgspec->getErr1();
00076       const float err2 = vgspec->getErr2();
00077       const float err3 = vgspec->getErr3();
00078       float acc[] = {0.0f, 0.0f, 0.0f};
00079 
00080    
00081       const SFCPathFactory::SizeMnemonic& mnemonic = vgspec->getMnemonic();
00082       SFCPath* curve = SFCPathFactory::getInstance(mnemonic);
00083    
00084       Image* out = new Image(width, height);
00085    
00086       int len = width * height;
00087       std::pair<int, int> maxblack; maxblack.first = 0; maxblack.second = 255;
00088       int grey;
00089       float accumulator = 0.0;
00090       std::pair<int, int> p;
00091       int black;
00092       int step;
00093    
00094       for (int i = 0; i < len; i += cluster)
00095       {
00096       
00097          accumulator = acc[0];
00098          for (int n = 0; n < cluster; n++)
00099          {
00100             if (i + n < len)
00101             {
00102             
00103                p = (*curve)[i + n];
00104             
00105                grey = source.getColorAt(p.first, p.second);
00106             
00107                accumulator += grey;
00108             
00109                if (maxblack.second > grey)
00110                {
00111                   maxblack.first = i + n;
00112                   maxblack.second = grey;
00113                }
00114             
00115                out->setColorAt(p.first, p.second, 1);
00116             }
00117          }
00118       
00119          black = cluster;
00120          step = len - i;
00121          if (black > step) black = step;
00122          while (accumulator >= 255)
00123          {
00124             black--;
00125             accumulator -= 255;
00126          }
00127       
00128          acc[0] = acc[1] + accumulator * err1;
00129          acc[1] = acc[2] + accumulator * err2;
00130          acc[2] = accumulator * err3;
00131       
00132          if (black > 0)
00133          {
00134             p = (*curve)[maxblack.first];
00135             out->setColorAt(p.first, p.second, 0);
00136             black--;
00137          }
00138          int pos;
00139          for (int n = 1; i + n < len; n++)
00140          {
00141          
00142             if (black == 0) break;
00143          
00144             pos = static_cast<int>(maxblack.first - n);
00145             if (pos >= static_cast<int>(i))
00146             {
00147                p = (*curve)[pos];
00148                out->setColorAt(p.first, p.second, 0);
00149                black--;
00150             }
00151             
00152             else
00153             {
00154                while (black > 0)
00155                {
00156                   pos = maxblack.first + n; n++;
00157                   p = (*curve)[pos];
00158                   out->setColorAt(p.first, p.second, 0);
00159                   black--;
00160                }
00161                break;
00162             }
00163          
00164             if (black == 0) break;
00165          
00166             pos = maxblack.first + n;
00167             if (pos < static_cast<int>(i + cluster))
00168             {
00169                p = (*curve)[pos];
00170                out->setColorAt(p.first, p.second, 0);
00171                black--;
00172             }
00173             
00174             else
00175             {
00176                while (black > 0)
00177                {
00178                   n++; pos = maxblack.first - n;
00179                   p = (*curve)[pos];
00180                   out->setColorAt(p.first, p.second, 0);
00181                   black--;
00182                }
00183                break;
00184             }
00185          }
00186       
00187          maxblack.first = 0; maxblack.second = 255;
00188       }
00189       delete curve;
00190       return out;
00191    }
00192 
00193 }