Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

VG95.cxx

Go to the documentation of this file.
00001 /*
00002  * @(#)src/VG95.cxx  1.0  2002-09-07 09:52
00003  *
00004  * Copyright (C)  2002  Daniel Léonard
00005  *
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * as published by the Free Software Foundation; either version 2
00009  * of the License, or (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00019  */
00020 
00026 #include <utility>
00027 #include "Image.h"
00028 #include "SFCPath.h"
00029 #include "SFCPathFactory.h"
00030 #include "VG95.h"
00031 #include "VGSpec.h"
00032 
00033 namespace halftoner
00034 {
00035 
00036 //---------------------------
00037 // Constructor
00038 //---------------------------
00039 
00040    VG95::VG95() throw()
00041    {
00042    // nothing
00043    }
00044 
00045 
00046 //---------------------------
00047 // Destructor
00048 //---------------------------
00049 
00050    VG95::~VG95()
00051    {
00052    // nothing
00053    }
00054 
00055 
00056 //---------------------------
00057 // Implemented method from Halftoner
00058 //---------------------------
00059 
00060    Image* VG95::halftone(const Image& source, const HalftonerSpec* spec) throw (std::invalid_argument)
00061    {
00062    // dimensions
00063       const int width = source.getWidth();
00064       const int height = source.getHeight();
00065    // square check
00066       if (width != height)
00067       {
00068          string s("image is not square");
00069          throw std::invalid_argument(s);
00070       }
00071 
00072    // getting the curve (can throw std::invalid_argument)
00073       const VGSpec* vgspec = dynamic_cast<const VGSpec*>(spec);
00074       int cluster = vgspec->getClusterSize();
00075       const SFCPathFactory::SizeMnemonic& mnemonic = vgspec->getMnemonic();
00076       SFCPath* curve = SFCPathFactory::getInstance(mnemonic);
00077 
00078    // destination image
00079       Image* out = new Image(width, height);
00080    // needed variables
00081       int accumulator = 0;
00082       int len = width * height;
00083       std::pair<int, int> maxblack; maxblack.first = 0; maxblack.second = 255;
00084       int grey;
00085       std::pair<int, int> p;
00086       int black;
00087       int step;
00088    // here we go
00089       for (int i = 0; i < len; i += cluster)
00090       {
00091       // accumulator
00092          for (int n = 0; n < cluster; n++)
00093          {
00094             if (i + n < len)
00095             {
00096             // coordinates
00097                p = (*curve)[i + n];
00098             // colour
00099                grey = source.getColorAt(p.first, p.second);
00100             // accumulation
00101                accumulator += grey;
00102             // index
00103                if (maxblack.second > grey)
00104                {
00105                   maxblack.first = i + n;
00106                   maxblack.second = grey;
00107                }
00108             // all cluster pixels to white
00109                out->setColorAt(p.first, p.second, 1);
00110             }
00111          }
00112       // finding how many black pixels
00113          black = cluster;
00114          step = len - i;
00115          if (black > step) black = step;
00116          while (accumulator >= 255)
00117          {
00118             black--;
00119             accumulator -=255;
00120          }
00121       // distributing black pixels
00122          if (black > 0)
00123          {
00124             p = (*curve)[maxblack.first];
00125             out->setColorAt(p.first, p.second, 0);
00126             black--;
00127          }
00128          int pos;
00129          for (int n = 1; i + n < len; n++)
00130          {
00131          // checking invariants
00132             if (black == 0) break;
00133          // to the left
00134             pos = maxblack.first - n;
00135             if (pos >= i)
00136             {
00137                p = (*curve)[pos];
00138                out->setColorAt(p.first, p.second, 0);
00139                black--;
00140             }
00141             // we hit the edge of the cluster
00142             else
00143             {
00144                while (black > 0)
00145                {
00146                   pos = maxblack.first + n; n++;
00147                   p = (*curve)[pos];
00148                   out->setColorAt(p.first, p.second, 0);
00149                   black--;
00150                }
00151                break;
00152             }
00153          // checking invariants
00154             if (black == 0) break;
00155          // to the right
00156             pos = maxblack.first + n;
00157             if (pos < (i + cluster))
00158             {
00159                p = (*curve)[pos];
00160                out->setColorAt(p.first, p.second, 0);
00161                black--;
00162             }
00163             // we hit the edge of the cluster
00164             else
00165             {
00166                while (black > 0)
00167                {
00168                   n++; pos = maxblack.first - n;
00169                   p = (*curve)[pos];
00170                   out->setColorAt(p.first, p.second, 0);
00171                   black--;
00172                }
00173                break;
00174             }
00175          }
00176       // reset index
00177          maxblack.first = 0; maxblack.second = 255;
00178       }
00179       delete curve;
00180       return out;
00181    }
00182 
00183 }

Generated on Sat Sep 7 16:31:41 2002 for Halftoning Library by doxygen1.2.17