1 
2 
3 // TnzCore includes
4 #include "tgeometry.h"
5 #include "tstream.h"
6 #include "texception.h"
7 
8 #include "toonz/vectorizerparameters.h"
9 
10 //**************************************************************************
11 //    Local namespace  strings
12 //**************************************************************************
13 
14 namespace {
15 
16 const char *s_version = "version",
17 
18            *s_generalConfiguration = "generalConfiguration",
19            *s_outline = "outline", *s_threshold = "threshold",
20            *s_leaveUnpainted = "leaveUnpainted",
21            *s_visibilityBits = "visibilityBits",
22 
23            *s_Centerline = "Centerline", *s_despeckling = "despeckling",
24            *s_maxThickness = "maxThickness", *s_penalty = "penalty",
25            *s_thicknessRatio = "thicknessRatio", *s_makeFrame = "makeFrame",
26            *s_naaSource = "naaSource",
27 
28            *s_accuracy                      = "accuracy",
29            *s_thicknessRatioFirst           = "thicknessRatioFirst",
30            *s_thicknessRatioLast            = "thicknessRatioLast",
31            *s_paintFill                     = "paintFill",
32            *s_alignBoundaryStrokesDirection = "alignBoundaryStrokesDirection",
33 
34            *s_Outline = "Outline", *s_adherenceTol = "adherenceTol",
35            *s_angleTol = "angleTol", *s_relativeTol = "relativeTol",
36            *s_mergeTol = "mergeTol", *s_maxColors = "maxColors",
37            *s_transparentColor = "transparentColor", *s_toneTol = "toneTol",
38 
39            *s_adherence = "adherence", *s_angle = "angle",
40            *s_relative = "relative", *s_toneThreshold = "toneThreshold";
41 
42 }  // namespace
43 
44 //**************************************************************************
45 //    Local namespace  stuff
46 //**************************************************************************
47 
48 namespace {
49 
50 const VersionNumber l_versionNumber(71, 0);
51 
52 //=======================================================
53 
saveData(const VectorizerConfiguration & conf,TOStream & os)54 void saveData(const VectorizerConfiguration &conf, TOStream &os) {
55   int leaveUnpainted = conf.m_leaveUnpainted ? 1 : 0;
56 
57   os.child(s_threshold) << conf.m_threshold;
58   os.child(s_leaveUnpainted) << leaveUnpainted;
59 }
60 
61 //-------------------------------------------------------
62 
loadData(VectorizerConfiguration & conf,TIStream & is)63 void loadData(VectorizerConfiguration &conf, TIStream &is) {
64   std::string tagName;
65   while (is.matchTag(tagName)) {
66     if (tagName == s_threshold)
67       is >> conf.m_threshold, is.matchEndTag();
68     else if (tagName == s_leaveUnpainted) {
69       int leaveUnpainted;
70       is >> leaveUnpainted,
71           conf.m_leaveUnpainted = (leaveUnpainted == 0) ? false : true;
72 
73       is.matchEndTag();
74     } else
75       is.skipCurrentTag();
76   }
77 }
78 
79 //-------------------------------------------------------
80 
saveData(const CenterlineConfiguration & conf,TOStream & os)81 void saveData(const CenterlineConfiguration &conf, TOStream &os) {
82   os.openChild(s_generalConfiguration);
83   saveData(static_cast<const VectorizerConfiguration &>(conf), os);
84   os.closeChild();
85 
86   int makeFrame = conf.m_makeFrame ? 1 : 0;
87 
88   os.child(s_despeckling) << conf.m_despeckling;
89   os.child(s_maxThickness) << conf.m_maxThickness;
90   os.child(s_penalty) << conf.m_penalty;
91   os.child(s_thicknessRatio) << conf.m_thicknessRatio;
92   os.child(s_makeFrame) << makeFrame;
93   os.child(s_naaSource) << (conf.m_naaSource ? 1 : 0);
94 }
95 
96 //-------------------------------------------------------
97 
loadData(CenterlineConfiguration & conf,TIStream & is)98 void loadData(CenterlineConfiguration &conf, TIStream &is) {
99   std::string tagName;
100   while (is.matchTag(tagName)) {
101     if (tagName == s_generalConfiguration)
102       loadData(static_cast<VectorizerConfiguration &>(conf), is),
103           is.matchEndTag();
104     else if (tagName == s_despeckling)
105       is >> conf.m_despeckling, is.matchEndTag();
106     else if (tagName == s_maxThickness)
107       is >> conf.m_maxThickness, is.matchEndTag();
108     else if (tagName == s_penalty)
109       is >> conf.m_penalty, is.matchEndTag();
110     else if (tagName == s_thicknessRatio)
111       is >> conf.m_thicknessRatio, is.matchEndTag();
112     else if (tagName == s_makeFrame) {
113       int makeFrame;
114       is >> makeFrame, conf.m_makeFrame = (makeFrame == 0) ? false : true;
115       is.matchEndTag();
116     } else if (tagName == s_naaSource) {
117       int naaSource;
118       is >> naaSource, conf.m_naaSource = (naaSource == 0) ? false : true;
119       is.matchEndTag();
120     } else
121       is.skipCurrentTag();
122   }
123 }
124 
125 //-------------------------------------------------------
126 
saveData(const NewOutlineConfiguration & conf,TOStream & os)127 void saveData(const NewOutlineConfiguration &conf, TOStream &os) {
128   os.openChild(s_generalConfiguration);
129   saveData(static_cast<const VectorizerConfiguration &>(conf), os);
130   os.closeChild();
131 
132   os.child(s_despeckling) << conf.m_despeckling;
133   os.child(s_adherenceTol) << conf.m_adherenceTol;
134   os.child(s_angleTol) << conf.m_angleTol;
135   os.child(s_relativeTol) << conf.m_relativeTol;
136   os.child(s_mergeTol) << conf.m_mergeTol;
137   os.child(s_maxColors) << conf.m_maxColors;
138   os.child(s_transparentColor) << conf.m_transparentColor;
139   os.child(s_toneTol) << conf.m_toneTol;
140 }
141 
142 //-------------------------------------------------------
143 
loadData(NewOutlineConfiguration & conf,TIStream & is)144 void loadData(NewOutlineConfiguration &conf, TIStream &is) {
145   std::string tagName;
146   while (is.matchTag(tagName)) {
147     if (tagName == s_generalConfiguration)
148       loadData(static_cast<VectorizerConfiguration &>(conf), is),
149           is.matchEndTag();
150     else if (tagName == s_despeckling)
151       is >> conf.m_despeckling, is.matchEndTag();
152     else if (tagName == s_adherenceTol)
153       is >> conf.m_adherenceTol, is.matchEndTag();
154     else if (tagName == s_angleTol)
155       is >> conf.m_angleTol, is.matchEndTag();
156     else if (tagName == s_relativeTol)
157       is >> conf.m_relativeTol, is.matchEndTag();
158     else if (tagName == s_mergeTol)
159       is >> conf.m_mergeTol, is.matchEndTag();
160     else if (tagName == s_maxColors)
161       is >> conf.m_maxColors, is.matchEndTag();
162     else if (tagName == s_transparentColor)
163       is >> conf.m_transparentColor, is.matchEndTag();
164     else if (tagName == s_toneTol)
165       is >> conf.m_toneTol, is.matchEndTag();
166     else
167       is.skipCurrentTag();
168   }
169 }
170 
171 //-------------------------------------------------------
172 
convert(const CenterlineConfiguration & conf,VectorizerParameters & params)173 void convert(const CenterlineConfiguration &conf,
174              VectorizerParameters &params) {
175   params.m_cThreshold    = conf.m_threshold / 25.0;
176   params.m_cAccuracy     = 10 - conf.m_penalty;
177   params.m_cDespeckling  = conf.m_despeckling / 2.0;
178   params.m_cMaxThickness = conf.m_maxThickness * 2;
179   // params.m_cThicknessRatio        = centConf.m_thicknessRatio;
180   params.m_cThicknessRatioFirst = conf.m_thicknessRatio;
181   params.m_cThicknessRatioLast  = conf.m_thicknessRatio;
182   params.m_cMakeFrame           = conf.m_makeFrame;
183   params.m_cPaintFill           = !conf.m_leaveUnpainted;
184   params.m_cAlignBoundaryStrokesDirection =
185       conf.m_alignBoundaryStrokesDirection;
186   params.m_cNaaSource = conf.m_naaSource;
187 }
188 
189 //-------------------------------------------------------
190 
convert(const NewOutlineConfiguration & conf,VectorizerParameters & params)191 void convert(const NewOutlineConfiguration &conf,
192              VectorizerParameters &params) {
193   params.m_oDespeckling      = conf.m_despeckling;
194   params.m_oAccuracy         = tround((5.0 - conf.m_mergeTol) * 2.0);
195   params.m_oAdherence        = tround(conf.m_adherenceTol * 100.0);
196   params.m_oAngle            = tround(conf.m_angleTol * 180.0);
197   params.m_oRelative         = tround(conf.m_relativeTol * 100.0);
198   params.m_oMaxColors        = conf.m_maxColors;
199   params.m_oToneThreshold    = conf.m_toneTol;
200   params.m_oTransparentColor = conf.m_transparentColor;
201   params.m_oPaintFill        = !conf.m_leaveUnpainted;
202   params.m_oAlignBoundaryStrokesDirection =
203       conf.m_alignBoundaryStrokesDirection;
204 }
205 
206 }  // namespace
207 
208 //**************************************************************************
209 //    VectorizerConfiguration  implementation
210 //**************************************************************************
211 
212 PERSIST_IDENTIFIER(VectorizerParameters, "vectorizerParameters")
213 
214 //--------------------------------------------------------------------------
215 
VectorizerParameters()216 VectorizerParameters::VectorizerParameters()
217     : m_visibilityBits(-1)  // All visible by default
218     , m_isOutline(false) {
219   CenterlineConfiguration cConf;
220   convert(cConf, *this);
221 
222   NewOutlineConfiguration oConf;
223   convert(oConf, *this);
224 }
225 
226 //--------------------------------------------------------------------------
227 
getCenterlineConfiguration(double frame) const228 CenterlineConfiguration VectorizerParameters::getCenterlineConfiguration(
229     double frame) const {
230   CenterlineConfiguration conf;
231 
232   conf.m_outline      = false;
233   conf.m_threshold    = m_cThreshold * 25;
234   conf.m_penalty      = 10 - m_cAccuracy;  // m_cAccuracy in [1,10]
235   conf.m_despeckling  = m_cDespeckling * 2;
236   conf.m_maxThickness = m_cMaxThickness / 2.0;
237   // conf.m_thicknessRatio   = m_cThicknessRatio;
238   conf.m_thicknessRatio =
239       (1 - frame) * m_cThicknessRatioFirst + frame * m_cThicknessRatioLast;
240   conf.m_leaveUnpainted                = !m_cPaintFill;
241   conf.m_alignBoundaryStrokesDirection = m_cAlignBoundaryStrokesDirection;
242   conf.m_makeFrame                     = m_cMakeFrame;
243   conf.m_naaSource                     = m_cNaaSource;
244 
245   return conf;
246 }
247 
248 //--------------------------------------------------------------------------
249 
getOutlineConfiguration(double frame) const250 NewOutlineConfiguration VectorizerParameters::getOutlineConfiguration(
251     double frame) const {
252   NewOutlineConfiguration conf;
253 
254   conf.m_outline                       = true;
255   conf.m_despeckling                   = m_oDespeckling;
256   conf.m_adherenceTol                  = m_oAdherence * 0.01;
257   conf.m_angleTol                      = m_oAngle / 180.0;
258   conf.m_relativeTol                   = m_oRelative * 0.01;
259   conf.m_mergeTol                      = 5.0 - m_oAccuracy * 0.5;
260   conf.m_leaveUnpainted                = !m_oPaintFill;
261   conf.m_alignBoundaryStrokesDirection = m_oAlignBoundaryStrokesDirection;
262   conf.m_maxColors                     = m_oMaxColors;
263   conf.m_transparentColor              = m_oTransparentColor;
264   conf.m_toneTol                       = m_oToneThreshold;
265 
266   return conf;
267 }
268 
269 //--------------------------------------------------------------------------
270 
saveData(TOStream & os)271 void VectorizerParameters::saveData(TOStream &os) {
272   os.child(s_version) << l_versionNumber.first << l_versionNumber.second;
273   os.child(s_outline) << (m_isOutline ? 1 : 0);
274   os.child(s_visibilityBits) << int(m_visibilityBits);
275 
276   os.openChild(s_Centerline);
277   {
278     os.child(s_threshold) << m_cThreshold;
279     os.child(s_accuracy) << m_cAccuracy;
280     os.child(s_despeckling) << m_cDespeckling;
281     os.child(s_maxThickness) << m_cMaxThickness;
282     os.child(s_thicknessRatioFirst) << m_cThicknessRatioFirst;
283     os.child(s_thicknessRatioLast) << m_cThicknessRatioLast;
284     os.child(s_makeFrame) << (m_cMakeFrame ? 1 : 0);
285     os.child(s_paintFill) << (m_cPaintFill ? 1 : 0);
286     os.child(s_alignBoundaryStrokesDirection)
287         << (m_cAlignBoundaryStrokesDirection ? 1 : 0);
288     os.child(s_naaSource) << (m_cNaaSource ? 1 : 0);
289   }
290   os.closeChild();
291 
292   os.openChild(s_Outline);
293   {
294     os.child(s_despeckling) << m_oDespeckling;
295     os.child(s_accuracy) << m_oAccuracy;
296     os.child(s_adherence) << m_oAdherence;
297     os.child(s_angle) << m_oAngle;
298     os.child(s_relative) << m_oRelative;
299     os.child(s_maxColors) << m_oMaxColors;
300     os.child(s_toneThreshold) << m_oToneThreshold;
301     os.child(s_transparentColor) << m_oTransparentColor;
302     os.child(s_paintFill) << (m_oPaintFill ? 1 : 0);
303     os.child(s_alignBoundaryStrokesDirection)
304         << (m_oAlignBoundaryStrokesDirection ? 1 : 0);
305   }
306   os.closeChild();
307 }
308 
309 //--------------------------------------------------------------------------
310 
loadData(TIStream & is)311 void VectorizerParameters::loadData(TIStream &is) {
312   VersionNumber version;
313 
314   std::string tagName;
315   int val;
316 
317   while (is.matchTag(tagName)) {
318     if (tagName == s_version)
319       is >> version.first >> version.second, is.matchEndTag();
320     else if (tagName == s_outline)
321       is >> val, m_isOutline = (val != 0), is.matchEndTag();
322     else if (tagName == s_visibilityBits) {
323       is >> val, is.matchEndTag();
324 
325       if (version ==
326           l_versionNumber)  // Restore visibility bits only if the parameters
327         m_visibilityBits =
328             val;  // version is current - defaulting them is no big deal.
329     } else if (tagName == s_Centerline) {
330       while (is.matchTag(tagName)) {
331         if (tagName == s_threshold)
332           is >> m_cThreshold, is.matchEndTag();
333         else if (tagName == s_accuracy)
334           is >> m_cAccuracy, is.matchEndTag();
335         else if (tagName == s_despeckling)
336           is >> m_cDespeckling, is.matchEndTag();
337         else if (tagName == s_maxThickness)
338           is >> m_cMaxThickness, is.matchEndTag();
339         else if (tagName == s_thicknessRatioFirst)
340           is >> m_cThicknessRatioFirst, is.matchEndTag();
341         else if (tagName == s_thicknessRatioLast)
342           is >> m_cThicknessRatioLast, is.matchEndTag();
343         else if (tagName == s_makeFrame)
344           is >> val, m_cMakeFrame = (val != 0), is.matchEndTag();
345         else if (tagName == s_paintFill)
346           is >> val, m_cPaintFill = (val != 0), is.matchEndTag();
347         else if (tagName == s_alignBoundaryStrokesDirection)
348           is >> val, m_cAlignBoundaryStrokesDirection = (val != 0),
349                      is.matchEndTag();
350         else if (tagName == s_naaSource)
351           is >> val, m_cNaaSource = (val != 0), is.matchEndTag();
352         else
353           is.skipCurrentTag();
354       }
355 
356       is.matchEndTag();
357     } else if (tagName == s_Outline) {
358       while (is.matchTag(tagName)) {
359         if (tagName == s_despeckling)
360           is >> m_oDespeckling, is.matchEndTag();
361         else if (tagName == s_accuracy)
362           is >> m_oAccuracy, is.matchEndTag();
363         else if (tagName == s_adherence)
364           is >> m_oAdherence, is.matchEndTag();
365         else if (tagName == s_angle)
366           is >> m_oAngle, is.matchEndTag();
367         else if (tagName == s_relative)
368           is >> m_oRelative, is.matchEndTag();
369         else if (tagName == s_maxColors)
370           is >> m_oMaxColors, is.matchEndTag();
371         else if (tagName == s_toneThreshold)
372           is >> m_oToneThreshold, is.matchEndTag();
373         else if (tagName == s_transparentColor)
374           is >> m_oTransparentColor, is.matchEndTag();
375         else if (tagName == s_paintFill)
376           is >> val, m_oPaintFill = (val != 0), is.matchEndTag();
377         else if (tagName == s_alignBoundaryStrokesDirection)
378           is >> val, m_oAlignBoundaryStrokesDirection = (val != 0),
379                      is.matchEndTag();
380         else
381           is.skipCurrentTag();
382       }
383 
384       is.matchEndTag();
385     } else if (tagName ==
386                "CenterlineConfiguration")  // Old tags, not saved anymore
387     {
388       CenterlineConfiguration conf;
389       ::loadData(conf, is), is.matchEndTag();
390 
391       convert(conf, *this);
392     } else if (tagName == "NewOutlineConfiguration")  //
393     {
394       NewOutlineConfiguration conf;
395       ::loadData(conf, is), is.matchEndTag();
396 
397       convert(conf, *this);
398     } else
399       is.skipCurrentTag();
400   }
401 }
402