diff --git a/toonz/sources/include/toonz/tcenterlinevectorizer.h b/toonz/sources/include/toonz/tcenterlinevectorizer.h index 7b8c970..f5b718b 100644 --- a/toonz/sources/include/toonz/tcenterlinevectorizer.h +++ b/toonz/sources/include/toonz/tcenterlinevectorizer.h @@ -95,8 +95,8 @@ Returns image converted.*/ const VectorizerConfiguration &c); void applyFillColors(TRegion *r, const TRasterP &ras, TPalette *palette, const CenterlineConfiguration &c, int regionCount); - void applyFillColors(TRegion *r, const TRasterP &ras, TPalette *palette, - const OutlineConfiguration &c, int regionCount); + // void applyFillColors(TRegion *r, const TRasterP &ras, TPalette *palette, + // const OutlineConfiguration &c, int regionCount); //! Traduces the input VectorizerConfiguration into an edible form. VectorizerConfiguration traduceConfiguration( diff --git a/toonz/sources/include/toonz/vectorizerparameters.h b/toonz/sources/include/toonz/vectorizerparameters.h index 54aa533..707ed5a 100644 --- a/toonz/sources/include/toonz/vectorizerparameters.h +++ b/toonz/sources/include/toonz/vectorizerparameters.h @@ -61,13 +61,18 @@ public: TAffine m_affine; //!< Affine transform applied to the vectorization results double m_thickScale; //!< Impose a thickness reduction by this ratio + // Align stroke directions to be the same (clockwise, i.e. left to right as + // viewed from inside of the shape). + bool m_alignBoundaryStrokesDirection; + public: VectorizerConfiguration(bool outline) : m_outline(outline) , m_threshold(200) , m_leaveUnpainted(true) , m_affine() - , m_thickScale(1.0) {} + , m_thickScale(1.0) + , m_alignBoundaryStrokesDirection(false) {} }; //***************************************************************************** @@ -231,6 +236,7 @@ public: bool m_cMakeFrame; bool m_cPaintFill; + bool m_cAlignBoundaryStrokesDirection; bool m_cNaaSource; // Outline options @@ -246,6 +252,7 @@ public: TPixel32 m_oTransparentColor; bool m_oPaintFill; + bool m_oAlignBoundaryStrokesDirection; // Generic data diff --git a/toonz/sources/toonz/vectorizerpopup.cpp b/toonz/sources/toonz/vectorizerpopup.cpp index 9b88f6f..4184de9 100644 --- a/toonz/sources/toonz/vectorizerpopup.cpp +++ b/toonz/sources/toonz/vectorizerpopup.cpp @@ -276,7 +276,7 @@ void Vectorizer::setLevel(const TXshSimpleLevelP &level) { switch (m_dialog->getChoice()) { case OverwriteDialog::KEEP_OLD: - xl = scene->getLevelSet()->getLevel(levelName); + xl = scene->getLevelSet()->getLevel(levelName); if (!xl) xl = scene->loadLevel(dstPath); m_vLevel = xl->getSimpleLevel(); @@ -614,6 +614,18 @@ paramsLayout->addWidget(m_cThicknessRatio, row++, 1);*/ } { + static const QString name = tr("Align Boundary Strokes Direction"); + locals.addParameter(l_centerlineParamGroups, name); + + m_cAlignBoundaryStrokesDirection = new CheckBox(name, this); + m_cAlignBoundaryStrokesDirection->setFixedHeight(WidgetHeight); + m_cAlignBoundaryStrokesDirection->setToolTip( + tr("Align boundary strokes direction to be the same.\n(clockwise, i.e. " + "left to right as viewed from inside of the shape)")); + m_paramsLayout->addWidget(m_cAlignBoundaryStrokesDirection, row++, 1); + } + + { static const QString name = tr("Add Border"); locals.addParameter(l_centerlineParamGroups, name); @@ -669,6 +681,17 @@ paramsLayout->addWidget(m_cThicknessRatio, row++, 1);*/ m_paramsLayout->addWidget(m_oPaintFill, row++, 1); } + { + static const QString name = tr("Align Boundary Strokes Direction"); + locals.addParameter(l_outlineParamGroups, name); + + m_oAlignBoundaryStrokesDirection = new CheckBox(name, this); + m_oAlignBoundaryStrokesDirection->setFixedHeight(WidgetHeight); + m_oAlignBoundaryStrokesDirection->setToolTip( + tr("Align boundary strokes direction to be the same.\n(clockwise, i.e. " + "left to right as viewed from inside of the shape)")); + m_paramsLayout->addWidget(m_oAlignBoundaryStrokesDirection, row++, 1); + } locals.addParameterGroup(l_outlineParamGroups, group++, row + 1, row); m_oCornersSeparator = new Separator(tr("Corners")); @@ -825,6 +848,8 @@ paramsLayout->addWidget(m_cThicknessRatio, row++, 1);*/ SLOT(onValueEdited())); connect(m_cMakeFrame, SIGNAL(stateChanged(int)), this, SLOT(onValueEdited())); connect(m_cPaintFill, SIGNAL(stateChanged(int)), this, SLOT(onValueEdited())); + connect(m_cAlignBoundaryStrokesDirection, SIGNAL(stateChanged(int)), this, + SLOT(onValueEdited())); connect(m_cNaaSource, SIGNAL(stateChanged(int)), this, SLOT(onValueEdited())); connect(m_oAccuracy, SIGNAL(valueChanged(bool)), this, @@ -832,6 +857,8 @@ paramsLayout->addWidget(m_cThicknessRatio, row++, 1);*/ connect(m_oDespeckling, SIGNAL(valueChanged(bool)), this, SLOT(onValueEdited(bool))); connect(m_oPaintFill, SIGNAL(stateChanged(int)), this, SLOT(onValueEdited())); + connect(m_oAlignBoundaryStrokesDirection, SIGNAL(stateChanged(int)), this, + SLOT(onValueEdited())); connect(m_oAdherence, SIGNAL(valueChanged(bool)), this, SLOT(onValueEdited(bool))); connect(m_oAngle, SIGNAL(valueChanged(bool)), this, @@ -905,7 +932,7 @@ bool VectorizerPopup::apply() { int r1 = 0; int c1 = 0; bool isCellSelection = getSelectedLevels(levels, r0, c0, r1, c1); - if (c0 < 0) c0 = 0; + if (c0 < 0) c0 = 0; if (levels.empty()) { error(tr("The current selection is invalid.")); return false; @@ -1112,6 +1139,8 @@ void VectorizerPopup::updateSceneSettings() { vParams->m_oToneThreshold = m_oToneThreshold->getValue(); vParams->m_oTransparentColor = m_oTransparentColor->getColor(); vParams->m_oPaintFill = m_oPaintFill->isChecked(); + vParams->m_oAlignBoundaryStrokesDirection = + m_oAlignBoundaryStrokesDirection->isChecked(); } else { vParams->m_cThreshold = m_cThreshold->getValue(); vParams->m_cAccuracy = m_cAccuracy->getValue(); @@ -1122,7 +1151,9 @@ void VectorizerPopup::updateSceneSettings() { vParams->m_cThicknessRatioLast = m_cThicknessRatioLast->getValue() * 100.0; vParams->m_cMakeFrame = m_cMakeFrame->isChecked(); vParams->m_cPaintFill = m_cPaintFill->isChecked(); - vParams->m_cNaaSource = m_cNaaSource->isChecked(); + vParams->m_cAlignBoundaryStrokesDirection = + m_cAlignBoundaryStrokesDirection->isChecked(); + vParams->m_cNaaSource = m_cNaaSource->isChecked(); } } @@ -1234,6 +1265,7 @@ void VectorizerPopup::setType(bool outline) { m_cThicknessRatioLast->setVisible(centerline); m_cPaintFill->setVisible(centerline); + m_cAlignBoundaryStrokesDirection->setVisible(centerline); m_cMakeFrame->setVisible(centerline); m_cNaaSourceSeparator->setVisible(centerline); m_cNaaSource->setVisible(centerline); @@ -1243,6 +1275,7 @@ void VectorizerPopup::setType(bool outline) { m_oDespecklingLabel->setVisible(outline); m_oDespeckling->setVisible(outline); m_oPaintFill->setVisible(outline); + m_oAlignBoundaryStrokesDirection->setVisible(outline); m_oCornersSeparator->setVisible(outline); m_oAngleLabel->setVisible(outline); m_oAngle->setVisible(outline); @@ -1293,6 +1326,8 @@ void VectorizerPopup::loadConfiguration(bool isOutline) { m_oRelative->setValue(vParams->m_oRelative); m_oAccuracy->setValue(vParams->m_oAccuracy); m_oPaintFill->setChecked(vParams->m_oPaintFill); + m_oAlignBoundaryStrokesDirection->setChecked( + vParams->m_oAlignBoundaryStrokesDirection); m_oMaxColors->setValue(vParams->m_oMaxColors); m_oTransparentColor->setColor(vParams->m_oTransparentColor); m_oToneThreshold->setValue(vParams->m_oToneThreshold); @@ -1300,6 +1335,8 @@ void VectorizerPopup::loadConfiguration(bool isOutline) { m_cThreshold->setValue(vParams->m_cThreshold); m_cDespeckling->setValue(vParams->m_cDespeckling); m_cPaintFill->setChecked(vParams->m_cPaintFill); + m_cAlignBoundaryStrokesDirection->setChecked( + vParams->m_cAlignBoundaryStrokesDirection); m_cMakeFrame->setChecked(vParams->m_cMakeFrame); m_cNaaSource->setChecked(vParams->m_cNaaSource); m_cMaxThickness->setValue(vParams->m_cMaxThickness); @@ -1388,9 +1425,10 @@ void VectorizerPopup::populateVisibilityMenu() { menu->clear(); VectorizerParameters *vParams = getParameters(); - locals.addActions(menu, vParams->m_isOutline ? l_outlineParamGroups - : l_centerlineParamGroups, - vParams->m_visibilityBits); + locals.addActions( + menu, + vParams->m_isOutline ? l_outlineParamGroups : l_centerlineParamGroups, + vParams->m_visibilityBits); } //----------------------------------------------------------------------------- diff --git a/toonz/sources/toonz/vectorizerpopup.h b/toonz/sources/toonz/vectorizerpopup.h index a0fb062..daf865f 100644 --- a/toonz/sources/toonz/vectorizerpopup.h +++ b/toonz/sources/toonz/vectorizerpopup.h @@ -41,7 +41,7 @@ class IntField; class MeasuredDoubleLineEdit; class ColorField; class CheckBox; -} +} // namespace DVGui //==================================================== @@ -141,6 +141,8 @@ private: DVGui::CheckBox *m_cPaintFill; + DVGui::CheckBox *m_cAlignBoundaryStrokesDirection; + DVGui::Separator *m_cNaaSourceSeparator; DVGui::CheckBox *m_cNaaSource; @@ -156,6 +158,8 @@ private: QLabel *m_oPaintFillLabel; DVGui::CheckBox *m_oPaintFill; + DVGui::CheckBox *m_oAlignBoundaryStrokesDirection; + DVGui::Separator *m_oCornersSeparator; QLabel *m_oAdherenceLabel; diff --git a/toonz/sources/toonzlib/tnewoutlinevectorize.cpp b/toonz/sources/toonzlib/tnewoutlinevectorize.cpp index 25f38e1..0757a62 100644 --- a/toonz/sources/toonzlib/tnewoutlinevectorize.cpp +++ b/toonz/sources/toonzlib/tnewoutlinevectorize.cpp @@ -772,7 +772,7 @@ void outlineVectorize(TVectorImageP &vi, const TRasterImageP &ri, vi->transform(conf.m_affine); vi->findRegions(); - if (!conf.m_leaveUnpainted) + if (!conf.m_leaveUnpainted || conf.m_alignBoundaryStrokesDirection) // Finally, build region colors. buildColorsRGBM(vi, reader.scHash()); } @@ -798,7 +798,8 @@ void outlineVectorize(TVectorImageP &vi, const TToonzImageP &ti, vi->transform(conf.m_affine); vi->findRegions(); - if (!conf.m_leaveUnpainted) buildColorsCM(vi, reader.scHash()); + if (!conf.m_leaveUnpainted || conf.m_alignBoundaryStrokesDirection) + buildColorsCM(vi, reader.scHash()); } } // namespace diff --git a/toonz/sources/toonzlib/toutlinevectorizer.cpp b/toonz/sources/toonzlib/toutlinevectorizer.cpp index c75858e..23bfae3 100644 --- a/toonz/sources/toonzlib/toutlinevectorizer.cpp +++ b/toonz/sources/toonzlib/toutlinevectorizer.cpp @@ -363,7 +363,7 @@ void OutlineVectorizer::link(DataPixel *pix, DataPixel *srcPix, node = tmp; } } - if (!node) node = createNode(pix); + if (!node) node = createNode(pix); if (!srcNode) srcNode = createNode(srcPix); if (!dstNode) dstNode = createNode(dstPix); @@ -450,7 +450,7 @@ Node *OutlineVectorizer::findOtherSide(Node *node) { } } if (!pix->m_node) return 0; - Node *q = pix->m_node; + Node *q = pix->m_node; while (q->m_pixel == 0 && q->m_other) q = q->m_other; assert(q && q->m_pixel == pix); @@ -595,9 +595,8 @@ void OutlineVectorizer::makeDataRaster(const TRasterP &src) { if (srcRGBM) { assert(m_palette); int inkId = m_palette->getClosestStyle(m_configuration.m_inkColor); - if (!inkId || - m_configuration.m_inkColor != - m_palette->getStyle(inkId)->getMainColor()) { + if (!inkId || m_configuration.m_inkColor != + m_palette->getStyle(inkId)->getMainColor()) { inkId = m_palette->getStyleCount(); m_palette->getStylePage(1)->insertStyle(1, m_configuration.m_inkColor); m_palette->setStyle(inkId, m_configuration.m_inkColor); @@ -635,9 +634,8 @@ void OutlineVectorizer::makeDataRaster(const TRasterP &src) { } else if (srcGR) { assert(m_palette); int inkId = m_palette->getClosestStyle(m_configuration.m_inkColor); - if (!inkId || - m_configuration.m_inkColor != - m_palette->getStyle(inkId)->getMainColor()) { + if (!inkId || m_configuration.m_inkColor != + m_palette->getStyle(inkId)->getMainColor()) { inkId = m_palette->getStyleCount(); m_palette->getStylePage(1)->insertStyle(1, m_configuration.m_inkColor); m_palette->setStyle(inkId, m_configuration.m_inkColor); @@ -695,8 +693,8 @@ void OutlineVectorizer::makeDataRaster(const TRasterP &src) { DataPixel *dataPix = dataRaster->pixels(y + 1) + 1; x = 0; while (inPix < inEndPix) { - *dataPix = DataPixel(); - int value = inPix->getTone(); + *dataPix = DataPixel(); + int value = inPix->getTone(); if (m_configuration.m_ignoreInkColors) inkId = 1; if (y == 0 || y == m_src->getLy() - 1 || x == 0 || x == m_src->getLx() - 1) { @@ -1387,7 +1385,7 @@ void VectorizerCore::applyFillColors(TRegion *r, const TRasterP &ras, } //----------------------------------------------------------------- - +/* void VectorizerCore::applyFillColors(TRegion *r, const TRasterP &ras, TPalette *palette, const OutlineConfiguration &c, @@ -1473,7 +1471,7 @@ void VectorizerCore::applyFillColors(TRegion *r, const TRasterP &ras, for (int i = 0; i < (int)r->getSubregionCount(); ++i) applyFillColors(r->getSubregion(i), ras, palette, c, regionCount); } - +*/ //----------------------------------------------------------------- void VectorizerCore::applyFillColors(TVectorImageP vi, const TImageP &img, @@ -1481,11 +1479,14 @@ void VectorizerCore::applyFillColors(TVectorImageP vi, const TImageP &img, const VectorizerConfiguration &c) { const CenterlineConfiguration ¢Conf = static_cast(c); - const OutlineConfiguration &outConf = - static_cast(c); + // const OutlineConfiguration &outConf = + // static_cast(c); // If configuration is not set for color fill at all, quit. - if (c.m_leaveUnpainted && (!c.m_outline || outConf.m_ignoreInkColors)) return; + if (c.m_leaveUnpainted && !c.m_outline && !c.m_alignBoundaryStrokesDirection) + return; + // if (c.m_leaveUnpainted && (!c.m_outline || outConf.m_ignoreInkColors)) + // return; TToonzImageP ti = img; TRasterImageP ri = img; @@ -1496,18 +1497,116 @@ void VectorizerCore::applyFillColors(TVectorImageP vi, const TImageP &img, vi->findRegions(); int r, regionsCount = vi->getRegionCount(); - if (c.m_outline) { - for (r = 0; r < regionsCount; ++r) - applyFillColors(vi->getRegion(r), ras, palette, outConf, 1); - } else { - for (r = 0; r < regionsCount; ++r) - applyFillColors(vi->getRegion(r), ras, palette, centConf, - 1); // 1 - c.m_makeFrame; - - clearInkRegionFlags(vi); + // filling colors in outline mode is done in tnewoutlinevectorize.cpp + // if (c.m_outline) { + // for (r = 0; r < regionsCount; ++r) + // applyFillColors(vi->getRegion(r), ras, palette, outConf, 1); + //} else { + for (r = 0; r < regionsCount; ++r) + applyFillColors(vi->getRegion(r), ras, palette, centConf, + 1); // 1 - c.m_makeFrame; + + clearInkRegionFlags(vi); + //} +} + +namespace { +struct StrokeData { + UCHAR m_hasColor, m_hasRegion; +}; + +// found the shape boundaries and recognize their stroke direction. +// based on the function getBoundaries() in levelselection.cpp +void alignBoundariesDirection(TVectorImageP vi) { + enum { FORWARD = 0x1, BACKWARD = 0x2, INTERNAL = FORWARD | BACKWARD }; + + struct locals { + static void markEdges(const TRegion ®ion, std::vector &sData, + bool parentRegionHasColor) { + bool regionHasColor = (region.getStyle() != 0); + + // Traverse region edges, marking associated strokes accordingly + UINT e, eCount = region.getEdgeCount(); + for (e = 0; e != eCount; ++e) { + const TEdge &ed = *region.getEdge(e); + assert(ed.m_s); + + int strokeIdx = ed.m_index; + if (strokeIdx >= 0) // Could be <0 in case the corresponding + { // stroke is a region 'closure' (autoclose) + assert(0 <= strokeIdx && strokeIdx < sData.size()); + + StrokeData &sd = sData[strokeIdx]; + + UCHAR side = (ed.m_w1 > ed.m_w0) ? FORWARD : BACKWARD; + + sd.m_hasRegion |= side; + if (regionHasColor) sd.m_hasColor |= side; + } + } + + if (parentRegionHasColor) { + // Mark non-region edge sides with color + for (e = 0; e != eCount; ++e) { + const TEdge &ed = *region.getEdge(e); + assert(ed.m_s); + + int strokeIdx = ed.m_index; + if (strokeIdx >= 0) { + StrokeData &sd = sData[strokeIdx]; + sd.m_hasColor |= (INTERNAL & ~sd.m_hasRegion); + } + } + } + + // Mark recursively on sub-regions + UINT sr, srCount = region.getSubregionCount(); + for (sr = 0; sr != srCount; ++sr) + markEdges(*region.getSubregion(sr), sData, regionHasColor); + } + }; // locals + + std::vector sData(vi->getStrokeCount()); + + // Traverse regions, mark each stroke edge with the side a COLORED region is + // on + UINT r, rCount = vi->getRegionCount(); + for (r = 0; r != rCount; ++r) + locals::markEdges(*vi->getRegion(r), sData, false); + + UINT s, sCount = vi->getStrokeCount(); + for (s = 0; s != sCount; ++s) { + // Strokes not appearing as region edges must be checked for region + // inclusion separately + if (!sData[s].m_hasRegion) { + TRegion *parentRegion = vi->getRegion(vi->getStroke(s)->getPoint(0.5)); + + if (parentRegion && parentRegion->getStyle()) + sData[s].m_hasColor = INTERNAL; + } + + // flip the stroke here + if (sData[s].m_hasColor == FORWARD) vi->getStroke(s)->changeDirection(); + } +} +void removeFillColors(TRegion *r) { + UINT i, edgeCount = r->getEdgeCount(); + for (i = 0; i < edgeCount; ++i) { + r->getEdge(i)->setStyle(0); } + // Build the color for its sub-regions + int j, rCount = r->getSubregionCount(); + for (j = 0; j < rCount; ++j) removeFillColors(r->getSubregion(j)); } +void removeFillColors(TVectorImageP vi) { + int i, rCount = vi->getRegionCount(); + for (i = 0; i < rCount; ++i) { + removeFillColors(vi->getRegion(i)); + } +} +} // namespace + //================================================================= TVectorImageP VectorizerCore::vectorize(const TImageP &img, @@ -1538,6 +1637,13 @@ TVectorImageP VectorizerCore::vectorize(const TImageP &img, applyFillColors(vi, img2, plt, c); } } + // align boundary strokes direction + if (c.m_alignBoundaryStrokesDirection) { + alignBoundariesDirection(vi); + vi->validateRegions(false); + vi->findRegions(); + if (c.m_leaveUnpainted) removeFillColors(vi); + } return vi; } diff --git a/toonz/sources/toonzlib/vectorizerparameters.cpp b/toonz/sources/toonzlib/vectorizerparameters.cpp index 1486421..7e96bb3 100644 --- a/toonz/sources/toonzlib/vectorizerparameters.cpp +++ b/toonz/sources/toonzlib/vectorizerparameters.cpp @@ -25,10 +25,11 @@ const char *s_version = "version", *s_thicknessRatio = "thicknessRatio", *s_makeFrame = "makeFrame", *s_naaSource = "naaSource", - *s_accuracy = "accuracy", - *s_thicknessRatioFirst = "thicknessRatioFirst", - *s_thicknessRatioLast = "thicknessRatioLast", - *s_paintFill = "paintFill", + *s_accuracy = "accuracy", + *s_thicknessRatioFirst = "thicknessRatioFirst", + *s_thicknessRatioLast = "thicknessRatioLast", + *s_paintFill = "paintFill", + *s_alignBoundaryStrokesDirection = "alignBoundaryStrokesDirection", *s_Outline = "Outline", *s_adherenceTol = "adherenceTol", *s_angleTol = "angleTol", *s_relativeTol = "relativeTol", @@ -180,7 +181,9 @@ void convert(const CenterlineConfiguration &conf, params.m_cThicknessRatioLast = conf.m_thicknessRatio; params.m_cMakeFrame = conf.m_makeFrame; params.m_cPaintFill = !conf.m_leaveUnpainted; - params.m_cNaaSource = conf.m_naaSource; + params.m_cAlignBoundaryStrokesDirection = + conf.m_alignBoundaryStrokesDirection; + params.m_cNaaSource = conf.m_naaSource; } //------------------------------------------------------- @@ -196,6 +199,8 @@ void convert(const NewOutlineConfiguration &conf, params.m_oToneThreshold = conf.m_toneTol; params.m_oTransparentColor = conf.m_transparentColor; params.m_oPaintFill = !conf.m_leaveUnpainted; + params.m_oAlignBoundaryStrokesDirection = + conf.m_alignBoundaryStrokesDirection; } } // namespace @@ -232,9 +237,10 @@ CenterlineConfiguration VectorizerParameters::getCenterlineConfiguration( // conf.m_thicknessRatio = m_cThicknessRatio; conf.m_thicknessRatio = (1 - frame) * m_cThicknessRatioFirst + frame * m_cThicknessRatioLast; - conf.m_leaveUnpainted = !m_cPaintFill; - conf.m_makeFrame = m_cMakeFrame; - conf.m_naaSource = m_cNaaSource; + conf.m_leaveUnpainted = !m_cPaintFill; + conf.m_alignBoundaryStrokesDirection = m_cAlignBoundaryStrokesDirection; + conf.m_makeFrame = m_cMakeFrame; + conf.m_naaSource = m_cNaaSource; return conf; } @@ -245,16 +251,17 @@ NewOutlineConfiguration VectorizerParameters::getOutlineConfiguration( double frame) const { NewOutlineConfiguration conf; - conf.m_outline = true; - conf.m_despeckling = m_oDespeckling; - conf.m_adherenceTol = m_oAdherence * 0.01; - conf.m_angleTol = m_oAngle / 180.0; - conf.m_relativeTol = m_oRelative * 0.01; - conf.m_mergeTol = 5.0 - m_oAccuracy * 0.5; - conf.m_leaveUnpainted = !m_oPaintFill; - conf.m_maxColors = m_oMaxColors; - conf.m_transparentColor = m_oTransparentColor; - conf.m_toneTol = m_oToneThreshold; + conf.m_outline = true; + conf.m_despeckling = m_oDespeckling; + conf.m_adherenceTol = m_oAdherence * 0.01; + conf.m_angleTol = m_oAngle / 180.0; + conf.m_relativeTol = m_oRelative * 0.01; + conf.m_mergeTol = 5.0 - m_oAccuracy * 0.5; + conf.m_leaveUnpainted = !m_oPaintFill; + conf.m_alignBoundaryStrokesDirection = m_oAlignBoundaryStrokesDirection; + conf.m_maxColors = m_oMaxColors; + conf.m_transparentColor = m_oTransparentColor; + conf.m_toneTol = m_oToneThreshold; return conf; } @@ -276,6 +283,8 @@ void VectorizerParameters::saveData(TOStream &os) { os.child(s_thicknessRatioLast) << m_cThicknessRatioLast; os.child(s_makeFrame) << (m_cMakeFrame ? 1 : 0); os.child(s_paintFill) << (m_cPaintFill ? 1 : 0); + os.child(s_alignBoundaryStrokesDirection) + << (m_cAlignBoundaryStrokesDirection ? 1 : 0); os.child(s_naaSource) << (m_cNaaSource ? 1 : 0); } os.closeChild(); @@ -291,6 +300,8 @@ void VectorizerParameters::saveData(TOStream &os) { os.child(s_toneThreshold) << m_oToneThreshold; os.child(s_transparentColor) << m_oTransparentColor; os.child(s_paintFill) << (m_oPaintFill ? 1 : 0); + os.child(s_alignBoundaryStrokesDirection) + << (m_oAlignBoundaryStrokesDirection ? 1 : 0); } os.closeChild(); } @@ -333,6 +344,9 @@ void VectorizerParameters::loadData(TIStream &is) { is >> val, m_cMakeFrame = (val != 0), is.matchEndTag(); else if (tagName == s_paintFill) is >> val, m_cPaintFill = (val != 0), is.matchEndTag(); + else if (tagName == s_alignBoundaryStrokesDirection) + is >> val, m_cAlignBoundaryStrokesDirection = (val != 0), + is.matchEndTag(); else if (tagName == s_naaSource) is >> val, m_cNaaSource = (val != 0), is.matchEndTag(); else @@ -360,6 +374,9 @@ void VectorizerParameters::loadData(TIStream &is) { is >> m_oTransparentColor, is.matchEndTag(); else if (tagName == s_paintFill) is >> val, m_oPaintFill = (val != 0), is.matchEndTag(); + else if (tagName == s_alignBoundaryStrokesDirection) + is >> val, m_oAlignBoundaryStrokesDirection = (val != 0), + is.matchEndTag(); else is.skipCurrentTag(); }