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 }