b3bd842e04
This patch used -Wmissing-declarations warning to show functions and symbols that had no declarations, and either: - Make static - Add to header This helps avoid possability that declarations and functions get out of sync. And ensures all source files reference headers correctly. It also makes sure functions defined with extern "C", have this defined in the header. An error found in calligraph.h while writing this patch. This has been applied to toonzlib, to avoid making very large global changes. If accepted, -Wmissing-declarations warning could be added to CMake.
232 lines
6.9 KiB
C++
232 lines
6.9 KiB
C++
|
|
|
|
// The following contains classes and prototypes for most code of centerline
|
|
// vectorization.
|
|
#include "tcenterlinevectP.h"
|
|
|
|
// TnzLib includes
|
|
#include "toonz/tcenterlinevectorizer.h"
|
|
#include "toonz/Naa2TlvConverter.h"
|
|
|
|
// TnzCore includes
|
|
#include "tpalette.h"
|
|
#include "tcolorstyles.h"
|
|
#include "trastercm.h"
|
|
#include "ttoonzimage.h"
|
|
#include "trasterimage.h"
|
|
#include "tvectorimage.h"
|
|
#include "tgeometry.h"
|
|
#include "tstroke.h"
|
|
#include "tropcm.h"
|
|
|
|
// STD includes
|
|
#include <vector>
|
|
#include <list>
|
|
#include <queue>
|
|
#include <map>
|
|
#include <functional>
|
|
#include <algorithm>
|
|
#include <math.h>
|
|
#include <assert.h>
|
|
|
|
//==========================================================================
|
|
|
|
//*********************************
|
|
//* Further miscellaneous *
|
|
//*********************************
|
|
|
|
//--------------------------------------------------------------------------
|
|
|
|
// Reduces strokes of image by currConfig->m_reduceThicknessRatio/100
|
|
inline void reduceThickness(TVectorImageP image, double thicknessRatio) {
|
|
thicknessRatio *= 0.01;
|
|
|
|
unsigned int i;
|
|
int j;
|
|
for (i = 0; i < image->getStrokeCount(); ++i) {
|
|
for (j = 0; j < image->getStroke(i)->getControlPointCount(); ++j) {
|
|
TThickPoint newCP = image->getStroke(i)->getControlPoint(j);
|
|
newCP.thick *= thicknessRatio;
|
|
image->getStroke(i)->setControlPoint(j, newCP);
|
|
}
|
|
}
|
|
}
|
|
|
|
//========================================================================
|
|
|
|
// Delete Skeleton graphs and list
|
|
inline void deleteSkeletonList(SkeletonList *skeleton) {
|
|
unsigned int i;
|
|
for (i = 0; i < skeleton->size(); ++i) delete (*skeleton)[i];
|
|
|
|
delete skeleton;
|
|
}
|
|
|
|
//========================================================================
|
|
|
|
static TVectorImageP copyStrokes(std::vector<TStroke *> &strokes) {
|
|
unsigned int i;
|
|
TVectorImageP result = new TVectorImage;
|
|
|
|
for (i = 0; i < strokes.size(); ++i)
|
|
if (strokes[i]->getStyle() >= 0) result->addStroke(strokes[i]);
|
|
|
|
return result;
|
|
}
|
|
|
|
//========================================================================
|
|
|
|
inline TThickPoint randomized(const TThickPoint &P) {
|
|
TThickPoint Q = P;
|
|
|
|
Q.x += ((((double)rand()) / RAND_MAX) - 0.5) * 0.1;
|
|
Q.y += ((((double)rand()) / RAND_MAX) - 0.5) * 0.1;
|
|
|
|
return Q;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
// Give stroke extremities a random shake. May help for region computing.
|
|
static void randomizeExtremities(TVectorImageP vi) {
|
|
unsigned int i;
|
|
for (i = 0; i < vi->getStrokeCount(); ++i) {
|
|
TThickPoint P = vi->getStroke(i)->getControlPoint(0);
|
|
vi->getStroke(i)->setControlPoint(0, randomized(P));
|
|
int n = vi->getStroke(i)->getControlPointCount();
|
|
P = vi->getStroke(i)->getControlPoint(n - 1);
|
|
vi->getStroke(i)->setControlPoint(n - 1, randomized(P));
|
|
}
|
|
}
|
|
|
|
//========================================================================
|
|
|
|
// Looped frame
|
|
inline void addFrameStrokes(TVectorImageP vi, TRasterP ras, TPalette *palette) {
|
|
const double epsThick = 1.0;
|
|
TStroke *frameStroke;
|
|
std::vector<TThickPoint> CPs;
|
|
|
|
CPs.push_back(TThickPoint(0, 0, epsThick));
|
|
CPs.push_back(TThickPoint(ras->getLx() / 2.0, 0, epsThick));
|
|
CPs.push_back(TThickPoint(ras->getLx(), 0, epsThick));
|
|
CPs.push_back(TThickPoint(ras->getLx(), 0, epsThick));
|
|
CPs.push_back(TThickPoint(ras->getLx(), 0, epsThick));
|
|
CPs.push_back(TThickPoint(ras->getLx(), ras->getLy() / 2.0, epsThick));
|
|
CPs.push_back(TThickPoint(ras->getLx(), ras->getLy(), epsThick));
|
|
CPs.push_back(TThickPoint(ras->getLx(), ras->getLy(), epsThick));
|
|
CPs.push_back(TThickPoint(ras->getLx(), ras->getLy(), epsThick));
|
|
CPs.push_back(TThickPoint(ras->getLx() / 2.0, ras->getLy(), epsThick));
|
|
CPs.push_back(TThickPoint(0, ras->getLy(), epsThick));
|
|
CPs.push_back(TThickPoint(0, ras->getLy(), epsThick));
|
|
CPs.push_back(TThickPoint(0, ras->getLy(), epsThick));
|
|
CPs.push_back(TThickPoint(0, ras->getLy() / 2.0, epsThick));
|
|
CPs.push_back(TThickPoint(0, 0, epsThick));
|
|
|
|
frameStroke = new TStroke(CPs);
|
|
frameStroke->setStyle(0);
|
|
frameStroke->setSelfLoop(true);
|
|
vi->addStroke(frameStroke);
|
|
}
|
|
|
|
//========================================================================
|
|
|
|
// Returns if input stroke is edge boundary of an ink-filled region
|
|
bool VectorizerCore::isInkRegionEdge(TStroke *stroke) {
|
|
return stroke->getFlag(SkeletonArc::SS_OUTLINE);
|
|
}
|
|
|
|
// Similar as above
|
|
bool VectorizerCore::isInkRegionEdgeReversed(TStroke *stroke) {
|
|
return stroke->getFlag(SkeletonArc::SS_OUTLINE_REVERSED);
|
|
}
|
|
|
|
void VectorizerCore::clearInkRegionFlags(TVectorImageP vi) {
|
|
int flag = SkeletonArc::SS_OUTLINE | SkeletonArc::SS_OUTLINE_REVERSED;
|
|
for (int i = 0; i < (int)vi->getStrokeCount(); i++)
|
|
vi->getStroke(i)->setFlag(flag, false);
|
|
}
|
|
|
|
//==========================================================================
|
|
|
|
//************************
|
|
//* Vectorizer Main *
|
|
//************************
|
|
|
|
//--------------------------------------------------------------------------
|
|
|
|
TVectorImageP VectorizerCore::centerlineVectorize(
|
|
TImageP &image, const CenterlineConfiguration &configuration,
|
|
TPalette *palette) {
|
|
TRasterImageP ri = image;
|
|
TToonzImageP ti = image;
|
|
|
|
TRasterP ras;
|
|
if (ri)
|
|
ras = ri->getRaster();
|
|
else {
|
|
ras = ti->getRaster()->clone();
|
|
TRop::expandPaint(ras);
|
|
}
|
|
|
|
if (configuration.m_naaSource) {
|
|
if (TRaster32P ras32 = ras) {
|
|
Naa2TlvConverter converter;
|
|
|
|
converter.process(ras32);
|
|
converter.setPalette(palette);
|
|
|
|
if (ti = converter.makeTlv(true)) // Transparent synthetic inks
|
|
{
|
|
image = ti;
|
|
ras = ti->getRaster();
|
|
|
|
TRop::expandPaint(ras);
|
|
}
|
|
}
|
|
}
|
|
|
|
VectorizerCoreGlobals globals;
|
|
globals.currConfig = &configuration;
|
|
|
|
Contours polygons;
|
|
polygonize(ras, polygons, globals);
|
|
|
|
// Most time-consuming part of vectorization, 'this' is passed to inform of
|
|
// partial progresses
|
|
SkeletonList *skeletons = skeletonize(polygons, this, globals);
|
|
|
|
if (isCanceled()) {
|
|
// Clean and return 0 at cancel command
|
|
deleteSkeletonList(skeletons);
|
|
|
|
return TVectorImageP();
|
|
}
|
|
|
|
organizeGraphs(skeletons, globals);
|
|
|
|
// junctionRecovery(polygons); //Da' problemi per maxThickness<inf...
|
|
// sarebbe da rendere compatibile
|
|
|
|
std::vector<TStroke *> sortibleResult;
|
|
TVectorImageP result;
|
|
|
|
calculateSequenceColors(ras, globals); // Extract stroke colors here
|
|
conversionToStrokes(sortibleResult, globals);
|
|
applyStrokeColors(sortibleResult, ras, palette,
|
|
globals); // Strokes get sorted here
|
|
result = copyStrokes(sortibleResult);
|
|
|
|
// Further misc adjustments
|
|
if (globals.currConfig->m_thicknessRatio < 100)
|
|
reduceThickness(result, configuration.m_thicknessRatio);
|
|
if (globals.currConfig->m_maxThickness == 0.0)
|
|
for (unsigned int i = 0; i < result->getStrokeCount(); ++i)
|
|
result->getStroke(i)->setSelfLoop(true);
|
|
if (globals.currConfig->m_makeFrame) addFrameStrokes(result, ras, palette);
|
|
// randomizeExtremities(result); //Cuccio random - non serve...
|
|
|
|
deleteSkeletonList(skeletons);
|
|
|
|
return result;
|
|
}
|